#537 names the psmux control session per registry — bmad-loop-ctl-<16-hex digest of the resolved registry root> — instead of the fixed bmad-loop-ctl. That suffix exists for one reason, and it is upstream's:
psmux keys its single-server-per-name mutex on the session name, not on PSMUX_DATA_DIR. acquire_session_mutex builds Local\psmux-session-{port_file_base} (src/platform.rs:346), and port_file_base() is {socket_name}__{session_name} or the bare session name (src/types.rs) — the data root never enters it. So two per-project registries, correctly isolated for lookup and cleanup, still share one global name namespace: with a fixed control-session name, every project's TUI launch but the first fails as a duplicate cold-spawn.
Filed upstream as psmux/psmux#599, with two reproductions on installed psmux 3.3.8 (66cf613) and a source read confirming acquire_session_mutex and port_file_base() are byte-identical between v3.3.8 and master 60e59fb.
What to do when it is fixed upstream
Retire the suffix behind a version gate — do not simply delete it. While any supported psmux build lacks the fix, removing the suffix reinstates the failure for every project after the first. The shape is the one this project already used for the 3.3.7 → 3.3.8 workaround retirements in #658: the deletion lands only behind a _LAST_UNSUPPORTED bump to a release that carries the fix.
Note the retirement is operator-visible, unlike most of that family: the control session's name changes back, so psmux ls output and any operator muscle memory or scripting around bmad-loop-ctl-<digest> changes with it. That deserves a changelog entry rather than a silent revert.
Two things to check at that point, both currently load-bearing:
runs.ctl_session_for and runs.is_ctl_session_name — the mint-side and parse-side predicates. They answer different questions on purpose (#537 conflated them three times before separating them); a retirement must not re-merge them.
- The reserved-shape refusal in
--run-id is independent of this workaround and should survive it: an id equal to the control session's name hands a run the live control session as its own agent session, which is true of the fixed name too — it is why --run-id ctl was already dangerous on main.
Related: #537, #660 (the psmux adoption umbrella — this belongs on its watch list), psmux/psmux#599.
#537names the psmux control session per registry —bmad-loop-ctl-<16-hex digest of the resolved registry root>— instead of the fixedbmad-loop-ctl. That suffix exists for one reason, and it is upstream's:psmux keys its single-server-per-name mutex on the session name, not on
PSMUX_DATA_DIR.acquire_session_mutexbuildsLocal\psmux-session-{port_file_base}(src/platform.rs:346), andport_file_base()is{socket_name}__{session_name}or the bare session name (src/types.rs) — the data root never enters it. So two per-project registries, correctly isolated for lookup and cleanup, still share one global name namespace: with a fixed control-session name, every project's TUI launch but the first fails as a duplicate cold-spawn.Filed upstream as psmux/psmux#599, with two reproductions on installed
psmux 3.3.8 (66cf613)and a source read confirmingacquire_session_mutexandport_file_base()are byte-identical betweenv3.3.8and master60e59fb.What to do when it is fixed upstream
Retire the suffix behind a version gate — do not simply delete it. While any supported psmux build lacks the fix, removing the suffix reinstates the failure for every project after the first. The shape is the one this project already used for the 3.3.7 → 3.3.8 workaround retirements in
#658: the deletion lands only behind a_LAST_UNSUPPORTEDbump to a release that carries the fix.Note the retirement is operator-visible, unlike most of that family: the control session's name changes back, so
psmux lsoutput and any operator muscle memory or scripting aroundbmad-loop-ctl-<digest>changes with it. That deserves a changelog entry rather than a silent revert.Two things to check at that point, both currently load-bearing:
runs.ctl_session_forandruns.is_ctl_session_name— the mint-side and parse-side predicates. They answer different questions on purpose (#537conflated them three times before separating them); a retirement must not re-merge them.--run-idis independent of this workaround and should survive it: an id equal to the control session's name hands a run the live control session as its own agent session, which is true of the fixed name too — it is why--run-id ctlwas already dangerous onmain.Related: #537, #660 (the psmux adoption umbrella — this belongs on its watch list), psmux/psmux#599.