Skip to content

test(adapters): probe psmux workaround premises, not just our reaction - #517

Merged
pbean merged 4 commits into
bmad-code-org:mainfrom
dracic:test/488-psmux-premise-probes
Aug 10, 2026
Merged

test(adapters): probe psmux workaround premises, not just our reaction#517
pbean merged 4 commits into
bmad-code-org:mainfrom
dracic:test/488-psmux-premise-probes

Conversation

@dracic

@dracic dracic commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Closes #488

What

Eight premise probes in the Windows live gate. Each drives raw psmux argv against a throwaway
session and asserts the observed upstream behavior that a workaround in psmux_backend exists
because of — never the backend verb the workaround implements.

The failure semantics are inverted on purpose: a red probe is the intended signal, and its
message names the workaround that has become droppable. That is the manual step from #222's
admission checklist turned into an assertion.

Plus the ablation half: every negative assertion the issue listed was ablated for real — guard
deleted, test run, result recorded, guard restored.

Why it was needed, concretely

Four of the eight premises had already flipped on psmux main (d56d777, 6c76ff9,
33ea109, 8edd1cb/194fac0) and nothing in this repo changed colour.

Every premise was observed before it was asserted

All eight were driven against the installed 3.3.7 build first. Two are sharper than the issue
described:

  • set-option -w does not merely lack per-window storage — it silently lands at session scope
    (show-options -wqv reads empty while the same key at session scope reads the value back).
  • kill-window on an unresolvable target exits 0 and destroys the ACTIVE window. The probe pins
    exactly that: the session survives and the vanished window is precisely the one that was active.

Upstream

Tracing the =-form kill divergence to its cause produced psmux/psmux#558: parse_target
strips the = for routing but PSMUX_TARGET_FULL keeps the raw argument, so the server's
kill-session fallback compares "name" == "=name" and never kills. Verified identical at v3.3.7
and main.

A second candidate (CLI value corruption for ' and non-ASCII whitespace) was traced and
deliberately not filede41886f already fixed it on main via a Unicode-aware
quote_arg_if_needed. Consequence worth flagging for the 3.3.8 admission: those two _transportable
branches become droppable, and the round-trip probe here will go red and say so.

Ablation results

verdict assertions
bite on their own assertion :276, :404, :957
belts — a neighbouring ==/raises fires first :96, :114, :824, :1618
vacuous, repaired :1625last_fallback defaulted false, so the -l leg was unreachable regardless of the early-return guard it claimed to cover
wrong-reason failure, repaired :1647 — reached its assertion only via IndexError from a fixture that ran dry

The issue's list also mislabels :414: it is a positive assertion. The negative one in that test
is :404.

Five further weakly-discriminating negatives outside the issue's scope (they ablate into a
TypeError rather than reaching their assertion) were recorded in the deferred-work ledger rather
than pulled into this change.

Invariants held

  • Zero tokens. Parked windows run pwsh -NoProfile -Command exit 0; no coding CLI is launched.
  • No developer session is ever reachable. Every probe gets its own throwaway session with a
    verified teardown. PSMUX_DATA_DIR isolation is applied only when the installed build
    demonstrably honors it. Bare switch-client -l is not probed at all — it has no target form, so
    under $TMUX it would move the developer's own client.
  • No workaround dropped, no _LAST_UNSUPPORTED bump. This builds the instrument; psmux 3.3.8: adopt as installed floor, re-verify the switch-client/select-window paths, and drop the psmux#497 and other workarounds #222 owns the
    admission.
  • CI untouched — the live gate stays a manual gate.

Verification

  • tests/test_psmux_live.py + tests/test_psmux_backend.py: 154 passed on Windows with psmux 3.3.7
  • full suite: no psmux-related failures
  • trunk check: no issues
  • the version probe's reachability was proven by inverting its regex and observing the failure —
    as first written it was vacuous, since available() applies the same regex and skips the test
    on the very failure the probe exists to catch

Summary by CodeRabbit

  • Bug Fixes

    • Improved fallback switching so successful client moves no longer trigger unnecessary fallback behavior.
    • Corrected handling for scripted attachment and switching scenarios.
  • Tests

    • Expanded live checks for session targeting, window selection, option handling, client commands, and pipe-pane behavior.
    • Added coverage for unresolved targets and option-value transport edge cases.
  • Documentation

    • Documented verified compatibility with supported psmux behavior and recorded updated validation details in the changelog.

Every psmux workaround was pinned only by tests asserting how the backend
reacts; nothing observed the upstream behavior each one exists because of, so
a fixed divergence changed no test's colour. Four premises had already flipped
on psmux main and nothing here noticed.

Add eight premise probes to the Windows live gate. Each drives raw psmux argv
against a throwaway session and asserts the observed upstream behavior, with a
failure message naming the workaround that has become droppable. The failure
semantics are inverted on purpose: a red probe is the signal, not a break.

Every premise was observed on the installed 3.3.7 build before its assertion
was written, and two turned out sharper than assumed. `set-option -w` does not
merely lack per-window storage, it silently lands at session scope; and an
unresolvable `kill-window` target exits 0 while destroying the ACTIVE window.
The `=`-form kill divergence was traced to its cause and filed upstream as
psmux/psmux#558.

Also ablate the backend's negative assertions — delete the guard, run the test,
confirm it fails, revert. Two did not bite: one was vacuous, because
`last_fallback` defaults false and left the fallback leg unreachable regardless
of the guard it claimed to cover; the other reached its assertion only via an
IndexError from a fixture that ran dry.

Zero-token contract unchanged, and the live gate stays a manual gate.

Closes bmad-code-org#488

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@pbean, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ac94a399-8b64-43d8-a537-a55172a367da

📥 Commits

Reviewing files that changed from the base of the PR and between 4045e0e and 3130900.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • tests/test_psmux_live.py

Walkthrough

The change adds isolated live probes for raw psmux behavior, documents the upstream version basis, and updates switch-client tests to exercise fallback handling without vacuous assertions.

Changes

psmux premise validation

Layer / File(s) Summary
Live probe infrastructure
tests/test_psmux_live.py
The live gate adds sanitized environments, isolated sessions, timing utilities, PowerShell quoting support, and teardown checks for leaked sessions.
Live premise probes
tests/test_psmux_live.py, src/bmad_loop/adapters/psmux_backend.py, CHANGELOG.md
The suite probes version output, target resolution, window selection, option scope, client commands, option transport, pipe-pane arguments, and unresolved kill-window behavior. Documentation records source tag v3.3.7 and the new probe coverage.
Switch fallback assertions
tests/test_psmux_backend.py
Switch-client tests pass last_fallback=True, script both switch paths, and verify that successful targeted switching skips the fallback command.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Possibly related PRs

Poem

A rabbit probes psmux with care,
Parks clean sessions everywhere.
Flags and targets show their trail,
Fallback tests now guard the rail.
Hop—the live facts prevail!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies tests that probe psmux workaround premises, which matches the primary change.
Linked Issues check ✅ Passed The changes add the eight requested live premise probes, preserve isolation and zero-token behavior, and repair the listed backend assertions through ablation.
Out of Scope Changes check ✅ Passed The changelog, documentation, and test updates directly support the linked issue objectives; no unrelated code changes are shown.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch test/488-psmux-premise-probes
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Maintainer-side review fixes on the bmad-code-org#488 probe block, live gate only.

A spaced tmp path now skips the pipe-pane probe alongside `$` and a backtick.
psmux's quote re-parse splits a spaced path (a `C:\Users\John Doe` profile is
enough), so the sidecar never spawns and the probe would red permanently while
its message blamed a transient spawn race. pipe_pane's docstring already lists
a spaced path as an untested ceiling; skipping is honest about that.

The `psmux_data_root` fixture verifies its own teardown in both the isolated
and the default registry view. It is the one session here that can land in the
developer's real registry — a build ignoring PSMUX_DATA_DIR is the branch the
fixture exists to detect — and its kill was bare best-effort.

`switch-client` and its attached-count read run with `$TMUX`/`$TMUX_PANE`
scrubbed. The premise is "no client to move", and an inherited `$TMUX` says
otherwise when pytest itself runs inside psmux. At 3.3.7 the verb is inert so
nothing moves, but on the effect-reporting build this probe exists to catch it
would drag the developer's client into the throwaway session and stay green
through the very premise flip.

The `probe` teardown also catches TimeoutExpired: `_plain_has_session` goes
through raw `_run`, which propagates a timeout even under `check=False`, so a
hung psmux escaped the teardown instead of reporting the leak.

Setup and scaffolding assertions carry a `probe setup: ` prefix so an instrument
failure is never read as a premise flip; the premise assertions, whose messages
name a droppable workaround, keep their bare form. `_mint_probe_window` gains
the qualified-id guard the prune test applies to its own mints, and the kill
probe's ordering comment now states the real safety property — every probe owns
its session — rather than a file order xdist does not preserve.
@pbean

pbean commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Reviewed and pushed maintainer-side fixes as 4045e0e — all in tests/test_psmux_live.py; psmux_backend.py, test_psmux_backend.py and the CHANGELOG entry are untouched (the entry stays accurate). Nice work: the inverted failure semantics and the "an unobserved premise must fail, never pass" guard in the pipe-pane probe are the right shape, and the two premises that turned out sharper than assumed (-w landing at session scope, the =-form kill traced to psmux/psmux#558) are exactly what this gate is for.

Changes

  1. Spaced tmp path skips the pipe-pane probe (test_premise_pipe_pane_strips_dash_flag_tokens). Added " " to the ("$", "`") refusal tuple and extended the skip reason. psmux's quote re-parse splits a spaced path — a C:\Users\John Doe profile is enough — so the sidecar never spawns, and the probe would red permanently while its message blamed the transient pipe-pane strips every dash-flag token from the piped command — pwsh -EncodedCommand sinks can never start (3.3.7) psmux/psmux#482 spawn race. pipe_pane's own docstring already lists a spaced path as an untested ceiling, so skipping is the honest reading; a red there is not.

  2. psmux_data_root now has a leak-verified teardown, mirroring the probe fixture's. This is the one session in the module that can land in a developer's real registry — a build that ignores PSMUX_DATA_DIR is precisely the branch the fixture exists to detect — and it had only a bare best-effort kill. The check runs in both views (the isolated env and the default registry) and fails loud with the session name and "kill it manually" on a leak or on any probe error.

  3. probe setup: prefix on the scaffolding assertions, so an instrument-failure red is distinguishable from a premise red (the module docstring promises each message names the droppable workaround, and these name none). Applied at: _raw_new_session (both), _mint_probe_window, _active_window (both), both fixture teardowns, the select-window starting-focus and both index-resolution asserts, the attached-count asserts, the roundtrip show/unset asserts, the pipe-pane attach/trigger and "sidecar never ran" asserts, and the kill probe's parked-windows precondition. The premise assertions keep their bare form. One docstring sentence states the convention.

  4. switch-client probe runs with $TMUX/$TMUX_PANE scrubbed (and its #{session_attached} read, for consistency). The premise is "no client to move", and an inherited $TMUX says otherwise: when pytest itself runs inside psmux there is a client — yours. At 3.3.7 the verb is inert so nothing moves, target routing is port-file based, and rc is dispatch-only 0, so the probe stays green today either way. But on the effect-reporting build this probe exists to catch, the switch would drag your client into the throwaway session and stay green through the very premise flip. A small local scrub rather than _new_session_env — that helper strips CLAUDE_CODE_* and sets PSMUX_ALLOW_NESTING, neither of which this call needs — and it copies os.environ, so the fixture's PSMUX_DATA_DIR still routes both verbs to the registry the probe session lives in.

  5. probe teardown also catches subprocess.TimeoutExpired. _plain_has_session goes through raw _run, and _run propagates a timeout even under check=False (its docstring says so), so today a hung psmux raises out of the teardown instead of reporting the leak.

  6. Two micro-fixes: _mint_probe_window asserts the derived id against [^:]+:@\d+ before returning — the same qualified-id guard the prune test applies to its mints, so a degraded mint fails at the mint instead of surfacing frames later as a bare rsplit IndexError; and the kill probe's "therefore last" comment now states the real safety property (every probe owns its own session) rather than a file order nothing enforces under xdist — it stays last for reader flow only.

Non-blocking, accepted as-is

  • F6_pwsh_quote is a private import and the only new POSIX coupling this PR adds: a rename upstream in psmux_backend would break collection on POSIX, where the module is skipped and nobody would see it coming. Accepted: the alternative is duplicating the quoting rule in the test, which is worse — a divergent copy would silently stop matching what pipe_pane actually ships.
  • F7 — the default-last_fallback True-path coverage gap you found by ablation is subsumed by what landed; no separate test needed.

Two small notes on the brief, for your call

  • The client-verbs probe has one display-message read, not two, so the scrub covers that call plus switch-client.
  • Three asserts in test_premise_window_scoped_option_write_lands_at_session_scope are arguably instrument-failure sites too (set-option -w no longer even accepts a window target, and the two read-rc checks at -w and session scope) but were not in the prefix list, so I left them bare — they read as premise preconditions there. Say the word if you want them prefixed.

Verification

uv run pytest -q green (4752 passed, 38 skipped, 5 xfailed) with all 9 live tests skippedsys.platform == "win32" gates the module, so nothing here was executed against a real psmux on my side. uv run pyright clean; trunk check --all --no-fix clean across 246 files (trunk, not ruff format).

I did ablate the new leak guard rather than trust it: with a fake psmux whose has-session always exits 0, the fixture errors with probe setup: data-probe session bmad-loop-data-probe-… survived teardown; kill it manually; with a fake whose has-session exits 1, that assert stays silent and the next guard down the chain fires instead. The temporary platform-gate edit that made those runs possible was reverted before the commit (file byte-identical to pre-ablation).

Ask

Could you re-run the live gate on your psmux 3.3.7 rig? Specifically: confirm the env-scrubbed switch-client probe stays green — that is the one change with a live behavioral surface, and the prediction is that stripping $TMUX changes nothing at 3.3.7 because the verb is inert and routing is port-file based. If it reds, the premise is more interesting than the fix. Also worth one run from a session started inside psmux, since that is the case the scrub is for. Holding off on @codex review and on merge until then.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_psmux_live.py`:
- Around line 207-217: Move the teardown kill command into the existing try
blocks in both fixtures, so subprocess.TimeoutExpired from the kill is caught by
the same exception handler as the leak probes. Preserve the current behavior of
setting leaked to True for OSError, TmuxError, or timeout failures and asserting
the session was removed.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b2704561-efcb-4563-bdfc-57c0af03b185

📥 Commits

Reviewing files that changed from the base of the PR and between 8e9ed10 and 4045e0e.

📒 Files selected for processing (1)
  • tests/test_psmux_live.py

Comment thread tests/test_psmux_live.py
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: 4045e0e3e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

CodeRabbit review of 4045e0e: in `psmux_data_root` the teardown kill ran
outside the try, so a `subprocess.TimeoutExpired` from the kill itself left the
fixture before the new leak check could run.

Valid, and it is the same defect the leak guard was added to close, one line
earlier. That fixture cannot use `kill_session` because it needs `env=` for
`PSMUX_DATA_DIR`, and raw `_run` propagates a timeout even under `check=False`
— so the kill moves inside the try. Observed both ways against a fake psmux
whose `kill-session` outlasts the 30s `_run` timeout: before, the fixture died
with a bare `TimeoutExpired` naming no session; after, it reports `probe setup:
data-probe session … survived teardown; kill it manually`. A kill that hung is
exactly when the session is most likely still standing.

The same review flagged the `probe` fixture's `mux.kill_session(session)` as
needing the same move. It does not: `PsmuxMultiplexer.kill_session` already
swallows `subprocess.SubprocessError`, and `TimeoutExpired` is a subclass, so
nothing escapes. Left alone, with the asymmetry recorded next to the catch it
would otherwise be re-raised against.
@pbean

pbean commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Bot round on 4045e0e — addressed in 8d984e9

CodeRabbit (1 actionable, Minor): the teardown kill in psmux_data_root ran outside the try, so a TimeoutExpired from the kill itself escaped before the new leak check could run. Valid — applied. It is the same defect the leak guard exists to close, one line earlier: that fixture needs env= for PSMUX_DATA_DIR, so it must use raw _run, and raw _run propagates a timeout even under check=False. Observed both ways against a fake psmux whose kill-session outlasts the 30s _run timeout:

  • before — subprocess.TimeoutExpired: Command '['psmux', 'kill-session', '-t', 'bmad-loop-data-probe-…']' timed out after 30 seconds (no session name, no instruction)
  • after — probe setup: data-probe session bmad-loop-data-probe-… survived teardown; kill it manually

The same comment said it "also applies to" the probe fixture's mux.kill_session(session). Declined: PsmuxMultiplexer.kill_session (psmux_backend.py:219-227) already catches (subprocess.SubprocessError, OSError) and TimeoutExpired is a SubprocessError subclass, so nothing escapes there — the move would be a no-op. Recorded as a comment beside the catch so it does not read as an oversight next time. Reasoning is in the review thread.

Codex auto-reviewed 4045e0e and found no major issues (this repo has Codex set to auto-review, so it ran without my asking — I had said I would hold off). Greptile is inert on this PR: "Your trial has ended", which is a permanent non-answer, not a pass.

Correction to my verification claim above

⚠️ GitHub CI has not run on either of my commits. The green CI on this PR is from 8e9ed10 only — there is no workflow run for 4045e0e or 8d984e9, and no action_required run queued for this branch either (other branches in this repo do have runs awaiting approval, so the gating is real). ci.yml has no workflow_dispatch, so I cannot trigger one. My "clean" claim rests on local runs: uv run pytest -q -n auto (4752 passed, 38 skipped, 5 xfailed, live module skipped), uv run pyright (0 errors), trunk check --all --no-fix (246 files clean) — re-run in full after 8d984e9. Someone should get CI to run on the real head before this merges; worth checking the PR page for an "awaiting approval" banner I cannot see through the API.

Unchanged

Everything in my previous comment still stands, including the two accepted non-blocking notes (F6 _pwsh_quote coupling, F7 subsumed coverage) and the two brief discrepancies flagged for your call. The ask is also unchanged: @dracic, please re-run the live gate on your psmux 3.3.7 rig and confirm the env-scrubbed switch-client probe stays green, ideally including one run from a shell started inside psmux. Still not merging, and still holding the manual @codex review pass until after your live run.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@pbean

pbean commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 8d984e9778

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Resolves the CHANGELOG conflict that left the PR unmergeable, which is why no
`pull_request` CI run existed for the branch head: GitHub could not build
refs/pull/517/merge, so the workflow was never created.

Both sides had prepended a new entry to the same `### Added` position — bmad-code-org#488's
psmux premise probes here, bmad-code-org#502's `gate:` deferred-work entry on main. Keep
both, newest first, which is the convention each side independently followed.
No other file conflicted: the merged tree differs from main only in this PR's
own four files.
@pbean

pbean commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Conflict resolved — CI is green on the real head

3130900 merges main into the branch. CHANGELOG.md was the only conflict: both sides had prepended an entry to the same position in ### Added#488's psmux probes here, #502's gate: entry on main. Both kept, newest first, which is the convention each side independently followed. Merge commit rather than a rebase, so @dracic's commit is not rewritten on his fork.

Correcting my previous comment. I said CI might be gated on fork-workflow approval. That was wrong. pull_request workflows run against refs/pull/517/merge, and while the branch conflicted GitHub could not build that ref — so no run was created at all, not even an action_required one, which is what misled me. The tell I should have checked first was mergeable: CONFLICTING / mergeStateStatus: DIRTY. After the merge push, refs/pull/517/merge resolves and CI fired within seconds:

All 10 checks SUCCESS on 3130900 — test py3.11/3.12/3.13/3.14, test windows py3.11/py3.14, version-sync, lint (trunk), typecheck (pyright), CodeRabbit. The two Windows jobs matter here: they are the only ones where this module is collected rather than skipped at platform level, so they exercise the _pwsh_quote import path that F6 flags as this PR's one POSIX coupling.

Read as a trial merge, the merged tree differs from main in exactly this PR's four files — nothing else came along. Locally: uv run pyright clean, trunk check --all --no-fix clean (247 files), suite green apart from tests/test_module_skills_sync.py, which reds only because my gitignored .claude/skills/ fork is stale against the canonical skill #502 updated — that test pytest.skips when those trees are absent, which is the CI condition, and the PR diff touches neither side. Not this PR's, and CI agrees.

Bot state

  • CodeRabbit — the one finding is fixed in 8d984e9 and CodeRabbit has confirmed both halves, including re-reading kill_session itself to verify that the probe fixture needed no change. Thread marked addressed; no open findings.
  • Codex — clean, but ⚠️ on 8d984e9: the review was requested at 20:05 and the merge landed ~20:11, so the current head 3130900 has not been through Codex. The only thing it adds is the CHANGELOG resolution, but the gate is "zero comments on the head that merges", so one more @codex review now would close it properly.
  • Greptile — inert on this PR ("Your trial has ended"): a non-answer, not a pass.

Unchanged

@dracic, the ask still stands: re-run the live gate on your psmux 3.3.7 rig and confirm the env-scrubbed switch-client probe stays green, ideally including one run from a shell started inside psmux, since that is the case the scrub exists for. Not merging.

@pbean
pbean merged commit aa1ae23 into bmad-code-org:main Aug 10, 2026
10 checks passed
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: 3130900827

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

dracic commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

@pbean live gate re-run complete on the Windows psmux rig.

  • Installed build: tmux 3.3.7 / psmux 3.3.7 (05cc5d4 2026-07-20).
  • Outside psmux (TMUX unset): 9 passed in 143.78s.
  • From a throwaway shell started inside psmux: 9 passed in 64.31s. This includes test_premise_client_verbs_exit_zero_with_no_client_to_move, so the env-scrubbed switch-client probe stayed green in the inherited-$TMUX case.
  • Teardown checks found no surviving bmad-loop-test-*, bmad-loop-data-probe-*, runner, or debug session.
  • Zero-token contract held: only the live-test parked PowerShell windows ran; no coding CLI was launched.

One wrapper-only false alarm was diagnosed before reporting: I initially used unquoted @gate_* option names in an outer PowerShell polling harness, so PowerShell treated them as splatting expressions and the marker was never written/read. A separate throwaway debug session with quoted option names reported TMUX_PRESENT=True, SET_EXIT=0, and quoted_marker=inside, then tore down cleanly. The pytest pane capture independently showed the successful 9/9 inside-psmux run; this was not a repo or live-gate failure.

No code changes were needed.

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.

psmux live gate pins no divergence PREMISE, only our reaction to it — CI cannot signal that a workaround became droppable

2 participants