Skip to content

feat(#38 PR-b): bind the per-slot proxy virtual node on spawn (flag-gated)#144

Merged
aradanmn merged 1 commit into
mainfrom
feat/38-proxy-launch
Jul 25, 2026
Merged

feat(#38 PR-b): bind the per-slot proxy virtual node on spawn (flag-gated)#144
aradanmn merged 1 commit into
mainfrom
feat/38-proxy-launch

Conversation

@aradanmn

Copy link
Copy Markdown
Owner

Second PR of the #38 build (#142). With MCSS_CONTROLLER_PROXY on, 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_PROXY flag (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 — derive vendor:product for the owning /proc block (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_instance binds bind_event/bind_js from the swap; the physical event_node/js_node still go to state — CONTROLLER_REMOVE matches on them, so the swap touches only the bind target.

Tests — 7/7, hardware-free, in CI baseline

proxy_start_slot/proxy_virtual_nodes stubbed:

  • flag-off no-op (behavior-neutral — mutation-verified: dropping the flag guard fails this test)
  • handheld no-op
  • flag-on binds the virtual
  • both failure modes fall back to raw
  • _vp_of_js_node derivation

No new shellcheck warnings; test_instance_lifecycle unaffected.

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

…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
@aradanmn
aradanmn merged commit 5256106 into main Jul 25, 2026
4 checks passed
@aradanmn
aradanmn deleted the feat/38-proxy-launch branch July 25, 2026 10:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant