af32c00c
docs+build: record the diff-since deferral; the agent e2e becomes a gate
a73x 2026-08-13 20:17
Commit message
build.zig
| Old | New | ||
|---|---|---|---|
| @@ -639,6 +639,19 @@ pub fn build(b: *std.Build) void { | |||
| 639 | const e2e_step = b.step("e2e", "Run end-to-end test"); | 639 | const e2e_step = b.step("e2e", "Run end-to-end test"); |
| 640 | e2e_step.dependOn(&e2e.step); | 640 | e2e_step.dependOn(&e2e.step); |
| 641 | 641 | ||
| 642 | // The agent surface gets a step of its own rather than a place in e2e: | ||
| 643 | // its nine scenarios spend ~51s mostly waiting on real idle timeouts and | ||
| 644 | // a 20s quiet await, which is a cost the paint-and-convergence suite | ||
| 645 | // should not have to carry on every run. A step is what makes it a gate | ||
| 646 | // at all — M7's rule, paid for twice: an end-to-end property that only | ||
| 647 | // runs when somebody types the script is the shape a regression ships | ||
| 648 | // through. | ||
| 649 | const agent = b.addSystemCommand(&.{"test/agent.sh"}); | ||
| 650 | agent.addArtifactArg(exe); | ||
| 651 | agent.addArtifactArg(muxa_exe); | ||
| 652 | const agent_step = b.step("agent", "Run the agent-surface end-to-end suite"); | ||
| 653 | agent_step.dependOn(&agent.step); | ||
| 654 | |||
| 642 | const soak = b.addSystemCommand(&.{"test/soak.sh"}); | 655 | const soak = b.addSystemCommand(&.{"test/soak.sh"}); |
| 643 | soak.addArtifactArg(exe); | 656 | soak.addArtifactArg(exe); |
| 644 | soak.addArtifactArg(mux_exe); | 657 | soak.addArtifactArg(mux_exe); |
docs/decisions.md
| Old | New | ||
|---|---|---|---|
| @@ -3116,6 +3116,31 @@ single-shot `muxa drive` (`send` + `await` + `capture` composes it). Added | |||
| 3116 | by the reviews: the `.zshenv` shim, bash-preexec coexistence, and the | 3116 | by the reviews: the `.zshenv` shim, bash-preexec coexistence, and the |
| 3117 | shim-directory startup sweep. | 3117 | shim-directory startup sweep. |
| 3118 | 3118 | ||
| 3119 | **`capture --diff-since` was promised and not built, and this is the | ||
| 3120 | record.** The spec names it three times — the verb list, the TUI-driving | ||
| 3121 | composition ("`send` + `status` + `capture --diff-since`"), and the testing | ||
| 3122 | plan — and execution dropped it with no code and no deferral written | ||
| 3123 | anywhere; the whole-branch review is the only reason it is written down | ||
| 3124 | now. `muxa capture` ships as the whole grid, `--vt` or plain. What a future | ||
| 3125 | one owes is more than the flag: `status_reply`'s `seq` carries the RETURN | ||
| 3126 | WATERMARK (`last_return`'s seq, 0 when nothing has returned this session), | ||
| 3127 | which is exactly what an await's `since_seq` wants and useless as the SEQ a | ||
| 3128 | diff quotes — after this milestone the live stream seq is on no reply an | ||
| 3129 | agent can read. So `--diff-since` needs a protocol field of its own, and | ||
| 3130 | must not be built by re-reading a field that already means something else. | ||
| 3131 | |||
| 3132 | **Two smaller narrowings against the spec, recorded rather than left to be | ||
| 3133 | rediscovered.** (1) The **fish** injection arm is unit-tested only: | ||
| 3134 | `prepare` writes `fish/vendor_conf.d` and prepends `XDG_DATA_DIRS`, and | ||
| 3135 | that is pinned, but no test anywhere runs fish — there is none on this box. | ||
| 3136 | zsh and bash are both driven live against a real session. (2) The spec's | ||
| 3137 | **version-skew test** — `muxa status` against an old-protocol daemon | ||
| 3138 | reports the structured error — was not written. The behaviour is real and | ||
| 3139 | not unpinned (a daemon that drops the frame and a daemon that never answers | ||
| 3140 | are the same wait and the same `{"error":"status: no reply"}`, which the | ||
| 3141 | dead-daemon paths do exercise), but the named fixture, an actual old | ||
| 3142 | binary, does not exist. | ||
| 3143 | |||
| 3119 | **Paid in a separate commit, and only after the e2e pinned the spellings:** | 3144 | **Paid in a separate commit, and only after the e2e pinned the spellings:** |
| 3120 | `parseQuicAddr`/`resolveHost` now live in `quic.zig` as one owner for the | 3145 | `parseQuicAddr`/`resolveHost` now live in `quic.zig` as one owner for the |
| 3121 | dial-address grammar, taking an allocator (`client.zig`'s copy hardcoded | 3146 | dial-address grammar, taking an allocator (`client.zig`'s copy hardcoded |
docs/roadmap.md
| Old | New | ||
|---|---|---|---|
| @@ -271,6 +271,19 @@ sweep. The `parseQuicAddr`/`resolveHost` dedup that review endorsed is | |||
| 271 | **paid**, not deferred — one owner in `quic.zig`, landed after the e2e had | 271 | **paid**, not deferred — one owner in `quic.zig`, landed after the e2e had |
| 272 | pinned the spellings. | 272 | pinned the spellings. |
| 273 | 273 | ||
| 274 | **Dropped in execution, not decided — the one item here that nobody chose:** | ||
| 275 | `muxa capture --diff-since SEQ`. The spec promises it three times and no | ||
| 276 | code was written; the whole-branch review found it. A future one needs a | ||
| 277 | protocol field of its own for the live stream seq, because `status_reply`'s | ||
| 278 | seq now carries the return watermark — right for awaits, wrong for a diff | ||
| 279 | to quote (decisions.md). Two coverage narrowings ride with it: the **fish** | ||
| 280 | injection arm is unit-tested only (no fish on this box; zsh and bash are | ||
| 281 | driven live), and the spec's **version-skew fixture** was never built (the | ||
| 282 | behaviour is pinned through the dead-daemon paths, an old binary is not). | ||
| 283 | And `muxa capture` is **the one verb with no automated coverage at all** — | ||
| 284 | `test/agent.sh` drives run, await, send and status; capture is where | ||
| 285 | `--diff-since` would land, so the test and the flag are owed together. | ||
| 286 | |||
| 274 | ## M16 candidates — and still outranked by trial feedback | 287 | ## M16 candidates — and still outranked by trial feedback |
| 275 | 288 | ||
| 276 | What remains is what was ranked behind M13 and M14 and survived M15, | 289 | What remains is what was ranked behind M13 and M14 and survived M15, |