Summary
TerminalMultiplexer.version() may return a multi-line string, and two of its four consumers
render it as if it were one line. Observed on a native-Windows host during the #310/#315 live
verification (psmux 3.3.7, 05cc5d4).
psmux -V prints two lines — the tmux X.Y.Z compatibility line plus its own — and
BaseTmuxBackend.version() (adapters/tmux_base.py:455) returns proc.stdout.strip(), which
removes surrounding whitespace but not the embedded newline:
tmux 3.3.7
psmux 3.3.7 (05cc5d4 2026-07-20)
What breaks
bmad-loop mux on that host:
NAME PLATFORM AVAILABLE VERSION SELECTED
tmux no yes tmux 3.3.7
psmux 3.3.7 (05cc5d4 2026-07-20)
psmux yes yes tmux 3.3.7
psmux 3.3.7 (05cc5d4 2026-07-20) * platform default for win32
cmd_mux (cli.py:400-414) computes column widths with len() and pads with ljust. The
VERSION cell is 43 chars, so every row's VERSION column is padded to 43 — hence the gap in the
header — and the embedded newline then splits each data row across two printed lines, stranding
SELECTED on the second. The table is unreadable, and * platform default for win32 looks like it
belongs to a version string.
The consumers disagree about this already
diagnostics.py:218 — defends: sanitize.scrub_text(raw, max_lines=1). Someone hit this before.
cli.py:407 (bmad-loop mux) — no defense; the breakage above.
runsetup.py:183 (bmad-loop validate preflight) — no defense. The finding message becomes
multiplexer PsmuxMultiplexer available (tmux 3.3.7\npsmux 3.3.7 (…)), and the raw value also
lands in the structured {"version": version} payload.
multiplexer.py:477 (forced-backend warning) — safe by accident: it uses {version!r}, so
the newline renders escaped.
One defended caller and two undefended ones says the invariant belongs at the seam, not at each
call site. The ABC docstring (multiplexer.py:290) still says "Used by the diagnostic dump",
which is now stale — there are four consumers.
Suggested shape (not prescriptive)
Normalise in BaseTmuxBackend.version() so every consumer gets one line, and state the
single-line guarantee in the ABC docstring. One tension worth deciding rather than defaulting:
first-line-wins yields tmux 3.3.7 for psmux, which is exactly the string
PsmuxMultiplexer.available()'s regex parses (psmux_backend.py:426) but a confusing thing to
display — it hides which binary is actually running. So psmux may want to override version()
to report its own line, or the seam may need to separate "parseable version" from "display label".
Second, smaller thing on the same output
The tmux row reports psmux's version and AVAILABLE yes, because psmux ships a
tmux-named binary and TmuxMultiplexer.version() runs tmux -V.
Selection is not affected — tmux registers with platform != "win32" so it never matches on
win32, and the historical fallback (precedence step 5) picks the platform match, which is psmux.
It is purely misleading in the listing. Whether the AVAILABLE column should be gated on
matches_platform for display is a judgement call; flagging it here because it shows up in the
same two lines of output.
Refs: #315, #310
Summary
TerminalMultiplexer.version()may return a multi-line string, and two of its four consumersrender it as if it were one line. Observed on a native-Windows host during the #310/#315 live
verification (psmux 3.3.7,
05cc5d4).psmux -Vprints two lines — thetmux X.Y.Zcompatibility line plus its own — andBaseTmuxBackend.version()(adapters/tmux_base.py:455) returnsproc.stdout.strip(), whichremoves surrounding whitespace but not the embedded newline:
What breaks
bmad-loop muxon that host:cmd_mux(cli.py:400-414) computes column widths withlen()and pads withljust. TheVERSION cell is 43 chars, so every row's VERSION column is padded to 43 — hence the gap in the
header — and the embedded newline then splits each data row across two printed lines, stranding
SELECTED on the second. The table is unreadable, and
* platform default for win32looks like itbelongs to a version string.
The consumers disagree about this already
diagnostics.py:218— defends:sanitize.scrub_text(raw, max_lines=1). Someone hit this before.cli.py:407(bmad-loop mux) — no defense; the breakage above.runsetup.py:183(bmad-loop validatepreflight) — no defense. The finding message becomesmultiplexer PsmuxMultiplexer available (tmux 3.3.7\npsmux 3.3.7 (…)), and the raw value alsolands in the structured
{"version": version}payload.multiplexer.py:477(forced-backend warning) — safe by accident: it uses{version!r}, sothe newline renders escaped.
One defended caller and two undefended ones says the invariant belongs at the seam, not at each
call site. The ABC docstring (
multiplexer.py:290) still says "Used by the diagnostic dump",which is now stale — there are four consumers.
Suggested shape (not prescriptive)
Normalise in
BaseTmuxBackend.version()so every consumer gets one line, and state thesingle-line guarantee in the ABC docstring. One tension worth deciding rather than defaulting:
first-line-wins yields
tmux 3.3.7for psmux, which is exactly the stringPsmuxMultiplexer.available()'s regex parses (psmux_backend.py:426) but a confusing thing todisplay — it hides which binary is actually running. So psmux may want to override
version()to report its own line, or the seam may need to separate "parseable version" from "display label".
Second, smaller thing on the same output
The
tmuxrow reports psmux's version andAVAILABLE yes, because psmux ships atmux-named binary andTmuxMultiplexer.version()runstmux -V.Selection is not affected —
tmuxregisters withplatform != "win32"so it never matches onwin32, and the historical fallback (precedence step 5) picks the platform match, which is psmux.
It is purely misleading in the listing. Whether the AVAILABLE column should be gated on
matches_platformfor display is a judgement call; flagging it here because it shows up in thesame two lines of output.
Refs: #315, #310