You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #310. The option channel that lands there keys per-window state as session-scoped options (@bmad_project_@3 for window @3) and reclaims keys with two generic sweeps (kill-time, launch-time orphan reconcile). Three review rounds on that branch confirmed the design and also settled three ceilings deliberately, with eyes open — this issue is the ledger for revisiting them as one safety-core unit, not a defect report against the channel.
1. The key namespace is convention-safe, not airtight
The _@<digits> suffix keeps foreign config options out of the sweeps because no naming convention in the tmux/psmux ecosystem puts @ mid-name — but psmux accepts any @ name in the map (server/options.rs:528-529 at v3.3.7), so a hand-written @theme_@3 in a user's config would match both sweeps and be deleted when window @3 dies. A caller-name prefix guard (@bmad_*) was rejected because the backend must stay generic over option names.
The airtight shape that preserves genericity: a seam-owned marker in the key grammar — owned by the channel, not by any caller — e.g. <option>__blw@<digits>. The sweep then matches only keys the seam itself minted. Costs a one-time key-format migration (the orphan reconcile can carry a transition rule for the old suffix), which is why it should ride a planned change rather than a hotfix.
2. Destructive-sweep containment edges
Cleanup-before-kill: kill_window frees the window's keys, then issues a best-effort kill-window. A kill that then fails leaves a live window key-less — its project tag gone (prune retry degrades to the untagged run-dir fallback) and its return key gone (an attached client parks without a way back). The order is mandated by the accepted contract on the psmux: per-window user options are session-scoped - the ctl-window project guard cannot discriminate and the parked-return mechanism is inert #310 branch; flipping to a verify-then-clean shape (or post-kill reconcile-only) needs that contract renegotiated, which is cheap to do here together with (1).
Foreign-key deletion is fully closed by (1); until then it remains the documented residual risk above.
3. Elevate the cross-project prune test to live E2E
The branch adds an acceptance-level unit test (_ctl_window_candidates over the real psmux backend with the subprocess seam faked) asserting only the owning project's dead-run window is a prune candidate. What no unit layer can prove is the live half: a real psmux 3.3.7 server with two projects' windows on the shared ctl session, a prune in one, and the other's window surviving kill-window. Same shape as the existing zero-token live gates — Windows-local, skipped elsewhere.
Related, smaller: name-token window targeting (=session:<window-name>) resolves first-match on duplicate ctl-window names, so option writes/frees can land on the wrong duplicate. Inherited from the callers' name-token design (tmux's native resolution is equally first-match); the migration path is the id-based targeting the #291 seam already provides — worth folding into this unit since (1) touches every key call site anyway.
Ordering
After the #310 PR merges — (1) changes the key grammar that PR introduces, and doing both in one release avoids migrating twice.
Follow-up to #310. The option channel that lands there keys per-window state as session-scoped options (
@bmad_project_@3for window@3) and reclaims keys with two generic sweeps (kill-time, launch-time orphan reconcile). Three review rounds on that branch confirmed the design and also settled three ceilings deliberately, with eyes open — this issue is the ledger for revisiting them as one safety-core unit, not a defect report against the channel.1. The key namespace is convention-safe, not airtight
The
_@<digits>suffix keeps foreign config options out of the sweeps because no naming convention in the tmux/psmux ecosystem puts@mid-name — but psmux accepts any@name in the map (server/options.rs:528-529atv3.3.7), so a hand-written@theme_@3in a user's config would match both sweeps and be deleted when window@3dies. A caller-name prefix guard (@bmad_*) was rejected because the backend must stay generic over option names.The airtight shape that preserves genericity: a seam-owned marker in the key grammar — owned by the channel, not by any caller — e.g.
<option>__blw@<digits>. The sweep then matches only keys the seam itself minted. Costs a one-time key-format migration (the orphan reconcile can carry a transition rule for the old suffix), which is why it should ride a planned change rather than a hotfix.2. Destructive-sweep containment edges
kill_windowfrees the window's keys, then issues a best-effortkill-window. A kill that then fails leaves a live window key-less — its project tag gone (prune retry degrades to the untagged run-dir fallback) and its return key gone (an attached client parks without a way back). The order is mandated by the accepted contract on the psmux: per-window user options are session-scoped - the ctl-window project guard cannot discriminate and the parked-return mechanism is inert #310 branch; flipping to a verify-then-clean shape (or post-kill reconcile-only) needs that contract renegotiated, which is cheap to do here together with (1).3. Elevate the cross-project prune test to live E2E
The branch adds an acceptance-level unit test (
_ctl_window_candidatesover the real psmux backend with the subprocess seam faked) asserting only the owning project's dead-run window is a prune candidate. What no unit layer can prove is the live half: a real psmux 3.3.7 server with two projects' windows on the shared ctl session, a prune in one, and the other's window survivingkill-window. Same shape as the existing zero-token live gates — Windows-local, skipped elsewhere.Related, smaller: name-token window targeting (
=session:<window-name>) resolves first-match on duplicate ctl-window names, so option writes/frees can land on the wrong duplicate. Inherited from the callers' name-token design (tmux's native resolution is equally first-match); the migration path is the id-based targeting the #291 seam already provides — worth folding into this unit since (1) touches every key call site anyway.Ordering
After the #310 PR merges — (1) changes the key grammar that PR introduces, and doing both in one release avoids migrating twice.
Refs: #310, #291, #288, psmux/psmux#321