Skip to content

Release 0.2.1: cross-process completed flush gate, resume flag passthrough, harness socket isolation#6

Merged
isingh merged 5 commits into
mainfrom
release/0.2.1
Jun 7, 2026
Merged

Release 0.2.1: cross-process completed flush gate, resume flag passthrough, harness socket isolation#6
isingh merged 5 commits into
mainfrom
release/0.2.1

Conversation

@isingh

@isingh isingh commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Patch release. Three fixes — one correctness bug against an advertised guarantee, one CLI parity gap, one test-isolation bug. Also folds in the already-merged-locally spawn passthrough.

completed now guarantees the reply is on disk across processes (dcd53bc)

A stable idle pane can settle before the transcript flush of a large reply. The README's "race-free after completed" guarantee held only for a single in-process observer — but the CLI sendwaitmessages flow crosses three processes whose only shared channel is the on-disk transcript. So a messages/messagesSince call right after a wait that reported completed could read [] while capture showed the full reply. Silent empty read; worst case for an orchestrator.

wait now also requires the reply record on disk before completed: the newest transcript message is assistant (the observer reports lastMessageRole; a claude tool-result is user-role, so a tool turn waits for its FINAL answer). No deadline is introduced — a blind transcript falls back to the pane, and a readable-but-unflushed reply is bounded by the consumer's existing patience, never a library timeout ("time is the policy's"). In-process it's a no-op. Easiest trigger: a long reply.

resume forwards -- <agent flags> like spawn (7ed66b3)

The post--- passthrough had landed on spawn only. Both boot constructors now share one withBootOptions builder + a single extraArgs fold, so they can't drift again. Parse-level regression test locks both verbs.

CLI subprocess tests no longer leak onto the default socket (ca01eb0)

The harness exported TMUX_SOCKET (read by nobody — tmux uses -L, the substrate uses CLAUDEMUX_SOCKET), so harness-spawned CLI processes silently used the default socket and could observe other consumers' sessions on the box.

Test plan

  • Full suite 327 passing / 3 skipped; typecheck + lint clean; npm run build green.
  • New: src/io/wait.test.ts — gate holds while the tail is user, releases on assistant, and never falsely completes (consumer patience bounds it).
  • New: test/cli/passthrough.test.ts — both boot verbs carry the variadic + boot flags.

Notes

Branched off chore/publish-public-default, so this PR also carries the unmerged spawn passthrough (524590a) and chore(npm): default publish access to public (19c4924).

🤖 Generated with Claude Code

isingh and others added 5 commits June 7, 2026 14:54
`spawn` now captures a trailing `[claudeArgs...]` variadic, so everything
after `--` is forwarded verbatim to claude's argv (via the existing
create({extraArgs}) path). Enables, e.g., launching a persona as a full
agent:

  claudemux spawn pm --cwd ./repo --trust-workspace -- \
    --append-system-prompt-file ./prompt.md --allowed-tools Read Grep --model opus

Previously the library accepted extraArgs but the CLI dropped post-`--`
tokens. Verified end-to-end (spawn → the injected system prompt takes
effect). 321 tests pass; build + biome clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The post-`--` passthrough added in 524590a landed on `spawn` only — `resume`
silently dropped agent flags. Extract a single `withBootOptions` builder (cwd /
boot-timeout / trust-workspace + the `--` passthrough help) that both boot
constructors use, and fold the commander variadic into `extraArgs` via one
shared helper, so the two can't drift again. Add a parse-level test that locks
both verbs to the variadic + boot flags.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
buildEnv exported `TMUX_SOCKET`, which nothing reads — tmux selects its server
via `-L`, and the substrate selects its socket from `CLAUDEMUX_SOCKET`. So
harness-spawned `claudemux` processes fell through to the DEFAULT socket and
could observe sessions from any other consumer on the box (surfaced as a flaky
"empty server" list assertion when a concurrent session was live). Export
`CLAUDEMUX_SOCKET` so CLI children land on the harness's private socket.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A stable idle pane can settle before the transcript flush of a large reply, so a
SEPARATE process calling messages()/messagesSince() right after a `wait` that
returned `completed` could read `[]` while the pane showed the full reply. The
"race-free after completed" guarantee held only for a single in-process observer;
the CLI send->wait->messages split crosses three processes whose only shared
channel is the on-disk transcript.

`wait` now also requires the reply record on disk before `completed`: the newest
transcript message is `assistant` (the observer reports `lastMessageRole`; a
claude tool-result is `user`-role, so a tool turn waits for its FINAL answer).
The observer owns the fact, `wait` owns the decision — same split as
lastStopAt -> hookDone. A blind transcript (count 0) falls back to the pane; no
library deadline is added — a readable-but-unflushed reply is bounded by the
consumer's patience ("time is the policy's").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cross-process `completed` flush gate, `resume` agent-flag passthrough, and a
test-harness socket-isolation fix. See CHANGELOG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@isingh isingh merged commit 0d2b0a0 into main Jun 7, 2026
7 checks passed
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