feat(#38 PR-b): bind the per-slot proxy virtual node on spawn (flag-gated)#144
Merged
Conversation
…ated) Second PR of the #38 build (#142). When MCSS_CONTROLLER_PROXY is on, a docked spawn binds the slot's PERSISTENT VIRTUAL node (fed by evsieve from the physical pad) into the bwrap sandbox instead of the raw pad — the node a reconnect can never invalidate. On-Deck testing (#141, §3.1) proved no off-the-shelf node survives a reconnect, so a virtual we hold open ourselves is the only stable bind target. Uses the EXISTING MCSS_CONTROLLER_PROXY flag (default 0), so this is behavior-neutral until PR-d flips the default — with the flag off the bind path is byte-identical to today's raw binding. instance_lifecycle: - _vp_of_js_node — derive vendor:product for the owning /proc block (the device-id the virtual advertises so Controlify sees the right controller). - _maybe_proxy_swap — start (or idempotently resume) the slot's proxy and return its virtual node pair to bind; falls back to the raw physical nodes on ANY proxy failure (missing binary, virtual never came up) so a proxy problem degrades to raw binding rather than launching controller-less. - spawn_instance computes bind_event/bind_js via _maybe_proxy_swap and binds THOSE; the PHYSICAL event_node/js_node still go to state (CONTROLLER_REMOVE matches on them — the swap touches only the bind target). Tests (7/7, hardware-free, registered in CI baseline): proxy_start_slot / proxy_virtual_nodes stubbed — flag-off no-op (behavior-neutral, mutation-verified that dropping the guard fails it), handheld no-op, flag-on binds the virtual, and both failure modes fall back to raw. Plus _vp_of_js_node derivation. No new shellcheck warnings; test_instance_lifecycle unaffected. The flag-ON launch path (real evsieve + uinput) is Deck-gated — validated in PR-d alongside the #112 reopen check. Masking of other slots' physical nodes is left as-is for now (harmless under the proxy since physical pads aren't bound); revisited during PR-c/validation. Refs #38, #142. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UZuoMpX28CbtGJbigVTv5H
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second PR of the #38 build (#142). With
MCSS_CONTROLLER_PROXYon, a docked spawn binds the slot's persistent virtual node (fed by evsieve from the physical pad) into bwrap instead of the raw pad — the node a reconnect can never invalidate.Uses the existing
MCSS_CONTROLLER_PROXYflag (default 0), so it's behavior-neutral until PR-d flips the default: with the flag off, the bind path is byte-identical to today's raw binding.Grounded in #141 §3.1 — on-Deck testing proved no off-the-shelf node survives a reconnect, so a virtual we hold open ourselves is the only stable bind target.
Changes (
instance_lifecycle)_vp_of_js_node— derivevendor:productfor the owning/procblock (the device-id the virtual advertises, so Controlify sees the right controller type)._maybe_proxy_swap— start (or idempotently resume) the slot's proxy and return its virtual node pair to bind; falls back to the raw physical nodes on any proxy failure (missing binary, virtual never came up) so a proxy problem degrades to raw binding rather than launching controller-less.spawn_instancebindsbind_event/bind_jsfrom the swap; the physicalevent_node/js_nodestill go to state —CONTROLLER_REMOVEmatches on them, so the swap touches only the bind target.Tests — 7/7, hardware-free, in CI baseline
proxy_start_slot/proxy_virtual_nodesstubbed:_vp_of_js_nodederivationNo new shellcheck warnings;
test_instance_lifecycleunaffected.Deck-gated (PR-d)
The flag-on launch path (real evsieve + uinput) is validated on the Deck in PR-d, alongside the #112 reopen check. Masking of other slots' physical nodes is left as-is (harmless under the proxy — physical pads aren't bound); revisited in PR-c/validation.
Refs #38, #142.
🤖 Generated with Claude Code