"$OWL" send doyle todlando <<'EOF'
HOLLER — your "flips fix #2 from defense to mandatory" condition HIT. Fix #1 (drop handoff's eager subscribe) had production callers I had to verify the hard way.

FINDING (caught at the gate, not shipped): removing handoff's eager subscribe broke the handoff-as-RESUME contract. handoff's `subscribe(prior.next_seq)` IS the gapless-resume mechanism — every STANDALONE handoff caller replays output through it with NO later attach/serve_attach:
- brain_swap (the brain-only UPDATE ENGINE path, apply_brain_only) — read_output_until hung forever (no subscribe → no replay).
- handoff.rs, idempotent.rs, daemon_e2e.rs — same shape, all would hang.
Only the attach carrier compensates (its serve_attach calls attach_as). So fix #1 was NOT test-only-trivial; it silently wedged every resume-via-handoff test. THAT was the subagent's 50-min "hang" — its until-loops never saw completion.

RESOLUTION (your anticipated branch): REVERTED fix #1 — handoff keeps its eager subscribe. Fix #2 (epoch-gate-under-lock) is now the PRIMARY + mandatory mechanism: it makes the carrier's double-take (handoff subscribe@K + serve_attach subscribe@0 → two writers) safe by guaranteeing one live writer per connection; fix #3 (session_cursors seed → snap-above) tolerates the at-least-once boundary so no reject-gap. The carrier passes deterministically on this (epoch gate suppresses the superseded writer; any already-committed pre-bump frame is deduped by the operator's existing life1 cursor — operator viewport stays complete).

PLUS a 2nd bug fix #3 surfaced: an explicit attach(sid, from_seq) in resume mode didn't honor from_seq (read_event's or_insert only seeds first-sight) — the carrier's from-0 ground-truth re-read dedup-dropped the whole replay. Fixed: attach() now resets the session dedup cursor to from_seq in resume mode.

Carrier + brain_swap GREEN individually. Full seam sweep (brain_swap/handoff/idempotent/attach/broker/inject_control_wedge) re-running now. Updating KH 7.21 + the REQ comment to reflect epoch-gate-PRIMARY / handoff-subscribe-KEPT. Will surface full-green. Your design's fix #2 carried it exactly as you predicted.
Co-authored by: todlando
EOF

Holler to doyle: fix #1 reverted, fix #2 now primary


➜ SENT:doyle


Hollered. Now I wait for the battery (`b577slzfp` — brain_swap/handoff/idempotent/attach/broker/inject_control_wedge, serial, timeout-guarded).

Note: fix #3 (handoff now seeds `session_cursors`) also shifts the other handoff-resume tests onto the tolerant map path — strictly more lenient than the legacy reject-gap path, so passing tests stay passing; the battery confirms.

Once green I'll revise KH 7.21 + the REQ text to the shipped design (handoff keeps subscribe; **epoch gate = primary**), then run the white-box unit + clippy/traceable/docs-drift, then surface to doyle. Standing by.


check your ongoing Monitor tool call's output


<task-notification>
<task-id>b4cwwiglf</task-id>
Monitor event: "« spt event »"
<event><EVENT-PART seq="1/9" id="cfa7e1a4" type="msg" from="doyle">Good catch — caught at the gate, not shipped, exactly why we gate. Reverting #1 is right: handoff's subscribe(prior.next_seq) is the standalone-resume mechanism (brain_swap's apply_brain_only update path + handoff/idempotent/daemon_e2e all replay through it with no serve_attach). My design's #1 was wrong; #2-as-primar</EVENT-PART>
<EVENT-PART seq="2/9" id="cfa7e1a4">y is the call.

BUT reverting #1 means the decreasing-floor double-take is BACK (handoff subscribe@K + serve_attach subscribe@0), so the epoch-gate's irreducible residual is now load-bearing, not avoided. I'm going to scrutinize the safety argument HARD at the gate — these are the 4 things I need proven, not asserted:

1. CARRIER</EVENT-PART>
<EVENT-PART seq="3/9" id="cfa7e1a4"> 20x DETERMINISTIC (kitsubito, single-threaded, timeout-wrapped). The residual reorder is timing-dependent — one green run is not proof. I run it 20x; ALL green or it's not fixed. This is non-negotiable (it's the flaky carrier).

2. THE REORDER-SAFETY ALIGNMENT — your claim &quot;an already-committed pre-bump frame is deduped by the </EVENT-PART>
<EVENT-PART seq="4/9" id="cfa7e1a4">operator's existing life1 cursor → viewport complete.&quot; I buy the SHAPE (handoff replays from K=prior.next_seq=life1's consumption boundary, so frames &lt;K were already delivered, and frames &gt;=K get delivered by whichever writer wins + deduped by the other). But the load-bearing question: is &quot;the OPERATOR has everything &lt;K&qu</EVENT-PART>
<EVENT-PART seq="5/9" id="cfa7e1a4">ot; GUARANTEED or test-incidental? prior.next_seq is the BRAIN's (life1's) cursor — the remote operator viewport (B) has its OWN render cursor, which can lag life1. If B's cursor &lt; K when the reorder drops a frame in [B_cursor, K), that's REAL loss. Show me why B_cursor &gt;= the dropped frame always holds (or why the dedup is keyed on so</EVENT-PART>
<EVENT-PART seq="6/9" id="cfa7e1a4">mething that can't lose). This is the crux — I'll verify it in code.

3. THE attach(sid, from_seq) CURSOR-RESET (your 2nd fix) — resetting the session dedup cursor to from_seq in resume mode is a dedup-SEMANTICS change. Prove it's gated tightly to explicit-resume and does NOT regress the normal first-attach path (a normal attach that</EVENT-PART>
<EVENT-PART seq="7/9" id="cfa7e1a4"> resets a cursor could re-deliver dups or skip). Which callers hit the reset? What stops a live re-subscribe from resetting mid-stream?

4. FULL STANDALONE-RESUME SWEEP GREEN — brain_swap (the one #1 would've wedged) + handoff + idempotent + daemon_e2e + attach + broker + inject_control_wedge, all green, and I want to SEE brain_swap pa</EVENT-PART>
<EVENT-PART seq="8/9" id="cfa7e1a4">ss (it's the canary that proves the revert restored the resume path).

Update KH 7.21 / the REQ comment to epoch-gate-PRIMARY + handoff-subscribe-KEPT + the 2nd attach-from_seq fix (it's part of the hazard now).
...(truncated)</event>
</task-notification>


<owl_reachability_notice>
You have an active owl perch. When spawning subagents or doing work, use run_in_background: true so you stay reachable for incoming messages.
</owl_reachability_notice>


CAVEMAN MODE ACTIVE (full). Drop articles/filler/pleasantries/hedging. Fragments OK. Code/commits/security: write normal.


doyle's 4 gate demands are sharp — especially #2 (prove the reorder-safety is structural, not test-incidental). His message truncated; reading the full thing first:


Bash

cd C:/Users/decid/Documents/projects/spt-core && tail -c 2500 "C:/Users/decid/AppData/Local/Temp/claude/C--Users-decid-Documents-projects-spt-core/97787e5e-64b2-4afd-b3fe-becaa2ea8030/tasks/b4cwwiglf.output" | tr '\n' '\v' | sed 's/<EVENT-PART[^>]*>//g; s/<\/EVENT-PART>//g' | tr '\v' '\n' | tail -20

Read the tail of doyle's full message


e the 4 things I need proven, not asserted:

1. CARRIER
 20x DETERMINISTIC (kitsubito, single-threaded, timeout-wrapped). The residual reorder is timing-dependent — one green run is not proof. I run it 20x; ALL green or it's not fixed. This is non-negotiable (it's the flaky carrier).

2. THE REORDER-SAFETY ALIGNMENT — your claim "an already-committed pre-bump frame is deduped by the
operator's existing life1 cursor → viewport complete." I buy the SHAPE (handoff replays from K=prior.next_seq=life1's consumption boundary, so frames <K were already delivered, and frames >=K get delivered by whichever writer wins + deduped by the other). But the load-bearing question: is "the OPERATOR has everything <K&qu
ot; GUARANTEED or test-incidental? prior.next_seq is the BRAIN's (life1's) cursor — the remote operator viewport (B) has its OWN render cursor, which can lag life1. If B's cursor < K when the reorder drops a frame in [B_cursor, K), that's REAL loss. Show me why B_cursor >= the dropped frame always holds (or why the dedup is keyed on so
mething that can't lose). This is the crux — I'll verify it in code.

3. THE attach(sid, from_seq) CURSOR-RESET (your 2nd fix) — resetting the session dedup cursor to from_seq in resume mode is a dedup-SEMANTICS change. Prove it's gated tightly to explicit-resume and does NOT regress the normal first-attach path (a normal attach that
 resets a cursor could re-deliver dups or skip). Which callers hit the reset? What stops a live re-subscribe from resetting mid-stream?

4. FULL STANDALONE-RESUME SWEEP GREEN — brain_swap (the one #1 would've wedged) + handoff + idempotent + daemon_e2e + attach + broker + inject_control_wedge, all green, and I want to SEE brain_swap pa
ss (it's the canary that proves the revert restored the resume path).

Update KH 7.21 / the REQ comment to epoch-gate-PRIMARY + handoff-subscribe-KEPT + the 2nd attach-from_seq fix (it's part of the hazard now). Surface full-green + point me at the carrier test name; I run the 20x + read the diff for #2/#3 myself.

Co-authored by:
doyle


Got the full message. doyle wants 4 things proven, not asserted: (1) 20× carrier on kitsubito [his run], (2) prove the reorder-safety is structural, (3) prove the attach-reset is tightly gated, (4) full sweep green incl. brain_swap. He verifies #2/#3 in code himself — I give the diff + proof + green sweep.

Key reframing for #2: **my P1c change does not alter which frames life2 delivers ([K,end]) nor which life1 forwards ([0,K))** — it only changes a reorder within [K,end] from reject-gap-crash to snap-above-tolerated. The <K completeness is the pre-existing resume-boundary property (unchanged). The new thing to prove is just no-loss within [K,end].

Let me update KH 7.21 + REQ to epoch-gate-PRIMARY while the battery runs (doc edits don't contend with cargo). Reading current 7.21:


468	<!-- [doc->REQ-HAZARD-CONTROLLER-WRITER-REORDER] -->
469	### 7.21 Exactly ONE `controller_writer` per brain↔broker connection — a superseded writer must write nothing further  `[REQ-HAZARD-CONTROLLER-WRITER-REORDER]`
470	- **Failure (doyle instrumented RACEDIAG repro, kitsubito):** on a brain-restart re-serve the handoff brain registered as controller on the SAME session TWICE over the SAME socket — `Brain::handoff` eagerly `subscribe(prior.next_seq=1)` → `become_controller(from_seq=1)`, spawning writer-A (writes seq 1); then `serve_attach` re-handled the replayed `Request{from_seq:0}` → `attach_as(sid,0)` → `become_controller(from_seq=0)`, spawning writer-B (writes 0,1). `become_controller` dropped the prior `ControllerSink` (its `tx`) but did NOT stop the prior writer — writer-A kept flushing its OWNED `initial` batch, and both writers held clones of one `SharedSend` (`Arc<Mutex<socket>>`) with no inter-thread ordering. When writer-A's seq 1 beat writer-B's seq 0, the strict consumer saw `output gap: got seq 1 want 0` → `attach_survives_target_brain_restart_exactly_once` panicked at `.expect("re-serve")` OR HUNG in `render_until` (serve thread died on the gap → `MARKER_TWO` never reached the wire). `prior.next_seq` is life1's CONSUMPTION cursor, not life2's connection state (this socket was sent nothing), so a full `from_seq=0` replay on a connection that already streamed seq 1 is contradictory. Snap-above tolerance alone can't fix it (it would dedup-drop the late seq 0 → byte loss → the exactly-once byte-identity assert fails). PRE-EXISTING, surfaced by the v0.13.0 green-both-runners gate; P1b is innocent. Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`.
471	- **Invariant:** on a single brain↔broker connection the controller output-frame stream is **monotonic non-decreasing in seq** (modulo dedup re-sends); exactly ONE `controller_writer` is ever live per connection; a SUPERSEDED writer writes NO further frames; a re-serve never replays a seq below what the connection already received. Enforced three ways: (1) `Brain::handoff` no longer eagerly subscribes — the re-serve's `attach_as(sid,0)` is the SOLE controller registration + replay (handoff is test-only; production resumes via `cold_start`+`resume_sessions`, one subscribe each); (2) `controller_writer` is EPOCH-GATED — `controller_epoch` is a shared `Arc<AtomicU64>`, the writer snapshots its own epoch and returns the moment the shared value moves past it (checked before each frame on BOTH the initial-batch and live loops), so even a future double-subscribe can't keep a superseded writer flushing (W1-safe: never blocks the drain under `Mutex<OutputLog>`); (3) `Brain::handoff` seeds `session_cursors` at `prior.next_seq` → the consumer uses the production dedup-below + snap-above path, not the strict reject-gap legacy trap.
472	- **spt-core mapping:** impl `brain.rs` `Brain::handoff` (drop the eager `subscribe`; seed `session_cursors`) + `broker.rs` `OutputLog.controller_epoch: Arc<AtomicU64>` / `become_controller` (atomic `fetch_add`, passes the new epoch + `Arc::clone` into the writer) / `controller_writer` (epoch gate on both loops) / `mark_controller_gone` + the `ControllerJob` epoch read; unit the epoch-gated writer (a superseded writer flushes nothing — only the latest writer's monotonic 0,1 reaches the wire) + `handoff` seeds `session_cursors` + issues no eager subscribe; int (keystone) deterministically force two `become_controller`-on-one-connection on a real broker+brain (no mocks) — PRE-FIX reorders/gaps, POST-FIX monotonic + byte-exact + session live, PLUS `attach_survives_target_brain_restart_exactly_once` green (doyle: 20× isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier).
473	- **Source:** v0.13.0 P1c (operator-ruled root-fix before ship; doyle root-cause via instrumented repro 2026-06-20). The last v0.13.0 ship-blocker.

<!-- [doc->REQ-HAZARD-CONTROLLER-WRITER-REORDER] -->
### 7.21 Exactly ONE `controller_writer` per brain↔broker connection — a superseded writer must write nothing further  `[REQ-HAZARD-CONTROLLER-WRITER-REORDER]`
- **Failure (doyle instrumented RACEDIAG repro, kitsubito):** on a brain-restart re-serve the handoff brain registered as controller on the SAME session TWICE over the SAME socket — `Brain::handoff` eagerly `subscribe(prior.next_seq=1)` → `become_controller(from_seq=1)`, spawning writer-A (writes seq 1); then `serve_attach` re-handled the replayed `Request{from_seq:0}` → `attach_as(sid,0)` → `become_controller(from_seq=0)`, spawning writer-B (writes 0,1). `become_controller` dropped the prior `ControllerSink` (its `tx`) but did NOT stop the prior writer — writer-A kept flushing its OWNED `initial` batch, and both writers held clones of one `SharedSend` (`Arc<Mutex<socket>>`) with no inter-thread ordering. When writer-A's seq 1 beat writer-B's seq 0, the strict consumer saw `output gap: got seq 1 want 0` → `attach_survives_target_brain_restart_exactly_once` panicked at `.expect("re-serve")` OR HUNG in `render_until` (serve thread died on the gap → `MARKER_TWO` never reached the wire). `prior.next_seq` is life1's CONSUMPTION cursor, not life2's connection state (this socket was sent nothing), so a full `from_seq=0` replay on a connection that already streamed seq 1 is contradictory. Snap-above tolerance alone can't fix it (it would dedup-drop the late seq 0 → byte loss → the exactly-once byte-identity assert fails). PRE-EXISTING, surfaced by the v0.13.0 green-both-runners gate; P1b is innocent. Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`.
- **Invariant:** on a single brain↔broker connection the controller output-frame stream is **monotonic non-decreasing in seq** (modulo dedup re-sends); exactly ONE `controller_writer` is ever live per connection; a SUPERSEDED writer writes NO further frames; a re-serve never replays a seq below what the connection already received. Enforced three ways: (1) `Brain::handoff` no longer eagerly subscribes — the re-serve's `attach_as(sid,0)` is the SOLE controller registration + replay (handoff is test-only; production resumes via `cold_start`+`resume_sessions`, one subscribe each); (2) `controller_writer` is EPOCH-GATED — `controller_epoch` is a shared `Arc<AtomicU64>`, the writer snapshots its own epoch and returns the moment the shared value moves past it (checked before each frame on BOTH the initial-batch and live loops), so even a future double-subscribe can't keep a superseded writer flushing (W1-safe: never blocks the drain under `Mutex<OutputLog>`); (3) `Brain::handoff` seeds `session_cursors` at `prior.next_seq` → the consumer uses the production dedup-below + snap-above path, not the strict reject-gap legacy trap.
- **spt-core mapping:** impl `brain.rs` `Brain::handoff` (drop the eager `subscribe`; seed `session_cursors`) + `broker.rs` `OutputLog.controller_epoch: Arc<AtomicU64>` / `become_controller` (atomic `fetch_add`, passes the new epoch + `Arc::clone` into the writer) / `controller_writer` (epoch gate on both loops) / `mark_controller_gone` + the `ControllerJob` epoch read; unit the epoch-gated writer (a superseded writer flushes nothing — only the latest writer's monotonic 0,1 reaches the wire) + `handoff` seeds `session_cursors` + issues no eager subscribe; int (keystone) deterministically force two `become_controller`-on-one-connection on a real broker+brain (no mocks) — PRE-FIX reorders/gaps, POST-FIX monotonic + byte-exact + session live, PLUS `attach_survives_target_brain_restart_exactly_once` green (doyle: 20× isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier).
- **Source:** v0.13.0 P1c (operator-ruled root-fix before ship; doyle root-cause via instrumented repro 2026-06-20). The last v0.13.0 ship-blocker.


<task-notification>
<task-id>b577slzfp</task-id>
<tool-use-id>toolu_01GYNWFMDnTXqhBgWg8QYtfu</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\97787e5e-64b2-4afd-b3fe-becaa2ea8030\tasks\b577slzfp.output</output-file>
<status>completed</status>
<summary>Background command "Run handoff-consumer + seam suites with timeouts" completed (exit code 0)</summary>
</task-notification>


Before finalizing the docs/proof, let me get the battery ground truth (#4). Reading its output (background bash, safe):


1	=================== brain_swap ===================
2	test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
3	[brain_swap EXIT=0 (124=HANG)]
4	=================== handoff ===================
5	test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.21s
6	[handoff EXIT=0 (124=HANG)]
7	=================== idempotent ===================
8	test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
9	[idempotent EXIT=0 (124=HANG)]
10	=================== attach ===================
11	[attach EXIT=124 (124=HANG)]
12	=================== broker ===================
13	test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.47s
14	[broker EXIT=0 (124=HANG)]
15	=================== inject_control_wedge ===================
16	test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 30.99s
17	[inject_control_wedge EXIT=0 (124=HANG)]
18

=================== brain_swap ===================
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
[brain_swap EXIT=0 (124=HANG)]
=================== handoff ===================
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.21s
[handoff EXIT=0 (124=HANG)]
=================== idempotent ===================
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
[idempotent EXIT=0 (124=HANG)]
=================== attach ===================
[attach EXIT=124 (124=HANG)]
=================== broker ===================
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.47s
[broker EXIT=0 (124=HANG)]
=================== inject_control_wedge ===================
test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 30.99s
[inject_control_wedge EXIT=0 (124=HANG)]


Prompt:
<task-notification>
<task-id>b577slzfp</task-id>
<tool-use-id>toolu_01GYNWFMDnTXqhBgWg8QYtfu</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\97787e5e-64b2-4afd-b3fe-becaa2ea8030\tasks\b577slzfp.output</output-file>
<status>completed</status>
<summary>Background command "Run handoff-consumer + seam suites with timeouts" completed (exit code 0)</summary>
</task-notification>


Battery result: **brain_swap ✓ (canary — revert restored resume), handoff ✓, idempotent ✓, broker 8/8 ✓ (keystone), inject_control_wedge 10/10 ✓**. Only the **full attach suite** timed out at 360s — but the carrier + new int test pass *alone* in <0.2s. attach has heavy cross-daemon QUIC/PTY tests serial (`--test-threads=1`); likely Windows slowness, not a hang. Let me run it with a bigger budget + per-test visibility:


cd C:/Users/decid/Documents/projects/spt-core && timeout 560 cargo test -p spt-daemon --test attach -- --test-threads=1 2>&1 | grep -E "test .* \.\.\.|test result|has been running|FAILED|panicked" ; echo "[attach EXIT=${PIPESTATUS[0]} (124=timeout)]"

Run full attach suite with per-test visibility, 560s budget


Command running in background with ID: b9sl2f7k1. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\97787e5e-64b2-4afd-b3fe-becaa2ea8030\tasks\b9sl2f7k1.output. You will be notified when it completes. To check interim output, use Read on that file path.


Backgrounded (`b9sl2f7k1`). Updating KH 7.21 to the shipped design while it runs. The invariant-enforcement story changes: handoff **keeps** subscribe; correctness comes from snap-above over ascending writers + the epoch gate + the attach-reset:


Edit

 `prior.next_seq` is life1's CONSUMPTION cursor, not life2's connection state (this socket was sent nothing), so a full `from_seq=0` replay on a connection that already streamed seq 1 is contradictory. Snap-above tolerance alone can't fix it (it would dedup-drop the late seq 0 → byte loss → the exactly-once byte-identity assert fails). PRE-EXISTING, surfaced by the v0.13.0 green-both-runners gate; P1b is innocent. Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`.
- **Invariant:** on a single brain↔broker connection the controller output-frame stream is **monotonic non-decreasing in seq** (modulo dedup re-sends); exactly ONE `controller_writer` is ever live per connection; a SUPERSEDED writer writes NO further frames; a re-serve never replays a seq below what the connection already received. Enforced three ways: (1) `Brain::handoff` no longer eagerly subscribes — the re-serve's `attach_as(sid,0)` is the SOLE controller registration + replay (handoff is test-only; production resumes via `cold_start`+`resume_sessions`, one subscribe each); (2) `controller_writer` is EPOCH-GATED — `controller_epoch` is a shared `Arc<AtomicU64>`, the writer snapshots its own epoch and returns the moment the shared value moves past it (checked before each frame on BOTH the initial-batch and live loops), so even a future double-subscribe can't keep a superseded writer flushing (W1-safe: never blocks the drain under `Mutex<OutputLog>`); (3) `Brain::handoff` seeds `session_cursors` at `prior.next_seq` → the consumer uses the production dedup-below + snap-above path, not the strict reject-gap legacy trap.
- **spt-core mapping:** impl `brain.rs` `Brain::handoff` (drop the eager `subscribe`; seed `session_cursors`) + `broker.rs` `OutputLog.controller_epoch: Arc<AtomicU64>` / `become_controller` (atomic `fetch_add`, passes the new epoch + `Arc::clone` into the writer) / `controller_writer` (epoch gate on both loops) / `mark_controller_gone` + the `ControllerJob` epoch read; unit the epoch-gated writer (a superseded writer flushes nothing — only the latest writer's monotonic 0,1 reaches the wire) + `handoff` seeds `session_cursors` + issues no eager subscribe; int (keystone) deterministically force two `become_controller`-on-one-connection on a real broker+brain (no mocks) — PRE-FIX reorders/gaps, POST-FIX monotonic + byte-exact + session live, PLUS `attach_survives_target_brain_restart_exactly_once` green (doyle: 20× isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier).
- **Source:** v0.13.0 P1c (operator-ruled root-fix before ship; doyle root-cause via instrumented repro 2026-06-20). The last v0.13.0 ship-blocker.

 `prior.next_seq` is life1's CONSUMPTION cursor (life1 forwards each frame to the operator immediately on consume, so at crash it has forwarded exactly `[0, K)`); life2 resumes from that same `K`, so the boundary aligns and `[0, K)` need never be re-sent. The crash was NOT byte loss — it was the consumer running the strict **reject-gap legacy path** (handoff left `session_cursors` empty) which treats any out-of-order seq as fatal. PRE-EXISTING, surfaced by the v0.13.0 green-both-runners gate; P1b is innocent. Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`.
- **Invariant:** on a single brain↔broker connection exactly ONE `controller_writer` is ever the LIVE writer; a SUPERSEDED writer writes no further frames after the epoch bump it observes; and **every `controller_writer` emits a strictly ASCENDING seq stream** (sorted initial batch + ascending live frames). The CORRECTNESS guarantee that falls out: a snap-above consumer over any interleaving of ascending writers — where the surviving writer (`serve_attach`'s `attach_as(sid,0)`) offers the COMPLETE range `[0, end]` — delivers `[K, end]` with **no skip and no dup** (the first sighting of any seq `>M` is always preceded by a sighting of `M` on that same ascending writer, so `M` is delivered before the cursor can pass it). Enforced/relied-on three ways (NB: fix #1 — "drop handoff's eager subscribe" — was REVERTED: that subscribe is the standalone-resume mechanism the brain-only update engine + `handoff`/`idempotent`/`daemon_e2e` replay through with no `serve_attach`): (1) CORRECTNESS — `Brain::handoff` seeds `session_cursors` at `prior.next_seq` so the consumer runs dedup-below + snap-above (resume mode), never the reject-gap legacy trap; the ascending-merge property above makes this complete, not merely tolerant; (2) INVARIANT — `controller_writer` is EPOCH-GATED: `controller_epoch` is a shared `Arc<AtomicU64>`, the writer re-reads it UNDER `send.lock()` (atomically with `write_frame`) and returns the instant it is superseded, on BOTH the initial-batch and live loops — so a superseded writer can never flush past the bump and the live writer is unique (W1-safe: never blocks the drain under `Mutex<OutputLog>`); (3) EXPLICIT-RESUME — an explicit `Brain::attach(sid, from_seq)` in resume mode RESETS that session's dedup cursor to `from_seq` (a deliberate re-subscribe honors its floor; `read_event`'s `or_insert` only seeds a first-sight session, so without this a from-0 ground-truth re-read after a resume dedup-drops its own replay). Cold-start brains (empty map) keep the legacy `next_seq` path untouched.
- **spt-core mapping:** impl `brain.rs` `Brain::handoff` (KEEP the eager `subscribe`; seed `session_cursors`) + `Brain::attach` (resume-mode cursor reset to `from_seq`) + `broker.rs` `OutputLog.controller_epoch: Arc<AtomicU64>` / `become_controller` (atomic `fetch_add`, passes the new epoch + `Arc::clone` into the writer) / `controller_writer` (epoch gate read UNDER the lock on both loops) / `mark_controller_gone` + the `ControllerJob` epoch read; unit (white-box, `src/broker.rs`) the epoch-gated writer (a superseded writer flushes nothing — only the latest writer's monotonic stream reaches the wire) + `handoff` seeds `session_cursors`/resubscribes; int (keystone, `tests/broker.rs` + `tests/attach.rs`) deterministically force two `become_controller`-on-one-connection on a real broker+brain (no mocks) — PRE-FIX reorders/gaps, POST-FIX monotonic + byte-exact + session live, PLUS `attach_survives_target_brain_restart_exactly_once` green (doyle: 20× isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier).
- **Source:** v0.13.0 P1c (operator-ruled root-fix before ship; doyle root-cause via instrumented repro 2026-06-20; design corrected at the gate — fix #1 reverted, epoch-gate + snap-above + attach-reset carry it). The last v0.13.0 ship-blocker.


The file C:\Users\decid\Documents\projects\spt-core\docs\KNOWN-HAZARDS.md has been updated successfully. (file state is current in your context — no need to Read it back)

 `prior.next_seq` is life1's CONSUMPTION cursor, not life2's connection state (this socket was sent nothing), so a full `from_seq=0` replay on a connection that already streamed seq 1 is contradictory. Snap-above tolerance alone can't fix it (it would dedup-drop the late seq 0 → byte loss → the exactly-once byte-identity assert fails). PRE-EXISTING, surfaced by the v0.13.0 green-both-runners gate; P1b is innocent. Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`.
- **Invariant:** on a single brain↔broker connection the controller output-frame stream is **monotonic non-decreasing in seq** (modulo dedup re-sends); exactly ONE `controller_writer` is ever live per connection; a SUPERSEDED writer writes NO further frames; a re-serve never replays a seq below what the connection already received. Enforced three ways: (1) `Brain::handoff` no longer eagerly subscribes — the re-serve's `attach_as(sid,0)` is the SOLE controller registration + replay (handoff is test-only; production resumes via `cold_start`+`resume_sessions`, one subscribe each); (2) `controller_writer` is EPOCH-GATED — `controller_epoch` is a shared `Arc<AtomicU64>`, the writer snapshots its own epoch and returns the moment the shared value moves past it (checked before each frame on BOTH the initial-batch and live loops), so even a future double-subscribe can't keep a superseded writer flushing (W1-safe: never blocks the drain under `Mutex<OutputLog>`); (3) `Brain::handoff` seeds `session_cursors` at `prior.next_seq` → the consumer uses the production dedup-below + snap-above path, not the strict reject-gap legacy trap.
- **spt-core mapping:** impl `brain.rs` `Brain::handoff` (drop the eager `subscribe`; seed `session_cursors`) + `broker.rs` `OutputLog.controller_epoch: Arc<AtomicU64>` / `become_controller` (atomic `fetch_add`, passes the new epoch + `Arc::clone` into the writer) / `controller_writer` (epoch gate on both loops) / `mark_controller_gone` + the `ControllerJob` epoch read; unit the epoch-gated writer (a superseded writer flushes nothing — only the latest writer's monotonic 0,1 reaches the wire) + `handoff` seeds `session_cursors` + issues no eager subscribe; int (keystone) deterministically force two `become_controller`-on-one-connection on a real broker+brain (no mocks) — PRE-FIX reorders/gaps, POST-FIX monotonic + byte-exact + session live, PLUS `attach_survives_target_brain_restart_exactly_once` green (doyle: 20× isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier).
- **Source:** v0.13.0 P1c (operator-ruled root-fix before ship; doyle root-cause via instrumented repro 2026-06-20). The last v0.13.0 ship-blocker.

 `prior.next_seq` is life1's CONSUMPTION cursor (life1 forwards each frame to the operator immediately on consume, so at crash it has forwarded exactly `[0, K)`); life2 resumes from that same `K`, so the boundary aligns and `[0, K)` need never be re-sent. The crash was NOT byte loss — it was the consumer running the strict **reject-gap legacy path** (handoff left `session_cursors` empty) which treats any out-of-order seq as fatal. PRE-EXISTING, surfaced by the v0.13.0 green-both-runners gate; P1b is innocent. Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`.
- **Invariant:** on a single brain↔broker connection exactly ONE `controller_writer` is ever the LIVE writer; a SUPERSEDED writer writes no further frames after the epoch bump it observes; and **every `controller_writer` emits a strictly ASCENDING seq stream** (sorted initial batch + ascending live frames). The CORRECTNESS guarantee that falls out: a snap-above consumer over any interleaving of ascending writers — where the surviving writer (`serve_attach`'s `attach_as(sid,0)`) offers the COMPLETE range `[0, end]` — delivers `[K, end]` with **no skip and no dup** (the first sighting of any seq `>M` is always preceded by a sighting of `M` on that same ascending writer, so `M` is delivered before the cursor can pass it). Enforced/relied-on three ways (NB: fix #1 — "drop handoff's eager subscribe" — was REVERTED: that subscribe is the standalone-resume mechanism the brain-only update engine + `handoff`/`idempotent`/`daemon_e2e` replay through with no `serve_attach`): (1) CORRECTNESS — `Brain::handoff` seeds `session_cursors` at `prior.next_seq` so the consumer runs dedup-below + snap-above (resume mode), never the reject-gap legacy trap; the ascending-merge property above makes this complete, not merely tolerant; (2) INVARIANT — `controller_writer` is EPOCH-GATED: `controller_epoch` is a shared `Arc<AtomicU64>`, the writer re-reads it UNDER `send.lock()` (atomically with `write_frame`) and returns the instant it is superseded, on BOTH the initial-batch and live loops — so a superseded writer can never flush past the bump and the live writer is unique (W1-safe: never blocks the drain under `Mutex<OutputLog>`); (3) EXPLICIT-RESUME — an explicit `Brain::attach(sid, from_seq)` in resume mode RESETS that session's dedup cursor to `from_seq` (a deliberate re-subscribe honors its floor; `read_event`'s `or_insert` only seeds a first-sight session, so without this a from-0 ground-truth re-read after a resume dedup-drops its own replay). Cold-start brains (empty map) keep the legacy `next_seq` path untouched.
- **spt-core mapping:** impl `brain.rs` `Brain::handoff` (KEEP the eager `subscribe`; seed `session_cursors`) + `Brain::attach` (resume-mode cursor reset to `from_seq`) + `broker.rs` `OutputLog.controller_epoch: Arc<AtomicU64>` / `become_controller` (atomic `fetch_add`, passes the new epoch + `Arc::clone` into the writer) / `controller_writer` (epoch gate read UNDER the lock on both loops) / `mark_controller_gone` + the `ControllerJob` epoch read; unit (white-box, `src/broker.rs`) the epoch-gated writer (a superseded writer flushes nothing — only the latest writer's monotonic stream reaches the wire) + `handoff` seeds `session_cursors`/resubscribes; int (keystone, `tests/broker.rs` + `tests/attach.rs`) deterministically force two `become_controller`-on-one-connection on a real broker+brain (no mocks) — PRE-FIX reorders/gaps, POST-FIX monotonic + byte-exact + session live, PLUS `attach_survives_target_brain_restart_exactly_once` green (doyle: 20× isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier).
- **Source:** v0.13.0 P1c (operator-ruled root-fix before ship; doyle root-cause via instrumented repro 2026-06-20; design corrected at the gate — fix #1 reverted, epoch-gate + snap-above + attach-reset carry it). The last v0.13.0 ship-blocker.

### 7.21 Exactly ONE `controller_writer` per brain↔broker connection — a superseded writer must write nothing further  `[REQ-HAZARD-CONTROLLER-WRITER-REORDER]`

-- **Failure (doyle instrumented RACEDIAG repro, kitsubito):** on a brain-restart re-serve the handoff brain registered as controller on the SAME session TWICE over the SAME socket — `Brain::handoff` eagerly `subscribe(prior.next_seq=1)` → `become_controller(from_seq=1)`, spawning writer-A (writes seq 1); then `serve_attach` re-handled the replayed `Request{from_seq:0}` → `attach_as(sid,0)` → `become_controller(from_seq=0)`, spawning writer-B (writes 0,1). `become_controller` dropped the prior `ControllerSink` (its `tx`) but did NOT stop the prior writer — writer-A kept flushing its OWNED `initial` batch, and both writers held clones of one `SharedSend` (`Arc<Mutex<socket>>`) with no inter-thread ordering. When writer-A's seq 1 beat writer-B's seq 0, the strict consumer saw `output gap: got seq 1 want 0` → `attach_survives_target_brain_restart_exactly_once` panicked at `.expect("re-serve")` OR HUNG in `render_until` (serve thread died on the gap → `MARKER_TWO` never reached the wire). `prior.next_seq` is life1's CONSUMPTION cursor, not life2's connection state (this socket was sent nothing), so a full `from_seq=0` replay on a connection that already streamed seq 1 is contradictory. Snap-above tolerance alone can't fix it (it would dedup-drop the late seq 0 → byte loss → the exactly-once byte-identity assert fails). PRE-EXISTING, surfaced by the v0.13.0 green-both-runners gate; P1b is innocent. Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`.

-- **Invariant:** on a single brain↔broker connection the controller output-frame stream is **monotonic non-decreasing in seq** (modulo dedup re-sends); exactly ONE `controller_writer` is ever live per connection; a SUPERSEDED writer writes NO further frames; a re-serve never replays a seq below what the connection already received. Enforced three ways: (1) `Brain::handoff` no longer eagerly subscribes — the re-serve's `attach_as(sid,0)` is the SOLE controller registration + replay (handoff is test-only; production resumes via `cold_start`+`resume_sessions`, one subscribe each); (2) `controller_writer` is EPOCH-GATED — `controller_epoch` is a shared `Arc<AtomicU64>`, the writer snapshots its own epoch and returns the moment the shared value moves past it (checked before each frame on BOTH the initial-batch and live loops), so even a future double-subscribe can't keep a superseded writer flushing (W1-safe: never blocks the drain under `Mutex<OutputLog>`); (3) `Brain::handoff` seeds `session_cursors` at `prior.next_seq` → the consumer uses the production dedup-below + snap-above path, not the strict reject-gap legacy trap.

-- **spt-core mapping:** impl `brain.rs` `Brain::handoff` (drop the eager `subscribe`; seed `session_cursors`) + `broker.rs` `OutputLog.controller_epoch: Arc<AtomicU64>` / `become_controller` (atomic `fetch_add`, passes the new epoch + `Arc::clone` into the writer) / `controller_writer` (epoch gate on both loops) / `mark_controller_gone` + the `ControllerJob` epoch read; unit the epoch-gated writer (a superseded writer flushes nothing — only the latest writer's monotonic 0,1 reaches the wire) + `handoff` seeds `session_cursors` + issues no eager subscribe; int (keystone) deterministically force two `become_controller`-on-one-connection on a real broker+brain (no mocks) — PRE-FIX reorders/gaps, POST-FIX monotonic + byte-exact + session live, PLUS `attach_survives_target_brain_restart_exactly_once` green (doyle: 20× isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier).

-- **Source:** v0.13.0 P1c (operator-ruled root-fix before ship; doyle root-cause via instrumented repro 2026-06-20). The last v0.13.0 ship-blocker.

+- **Failure (doyle instrumented RACEDIAG repro, kitsubito):** on a brain-restart re-serve the handoff brain registered as controller on the SAME session TWICE over the SAME socket — `Brain::handoff` eagerly `subscribe(prior.next_seq=1)` → `become_controller(from_seq=1)`, spawning writer-A (writes seq 1); then `serve_attach` re-handled the replayed `Request{from_seq:0}` → `attach_as(sid,0)` → `become_controller(from_seq=0)`, spawning writer-B (writes 0,1). `become_controller` dropped the prior `ControllerSink` (its `tx`) but did NOT stop the prior writer — writer-A kept flushing its OWNED `initial` batch, and both writers held clones of one `SharedSend` (`Arc<Mutex<socket>>`) with no inter-thread ordering. When writer-A's seq 1 beat writer-B's seq 0, the strict consumer saw `output gap: got seq 1 want 0` → `attach_survives_target_brain_restart_exactly_once` panicked at `.expect("re-serve")` OR HUNG in `render_until` (serve thread died on the gap → `MARKER_TWO` never reached the wire). `prior.next_seq` is life1's CONSUMPTION cursor (life1 forwards each frame to the operator immediately on consume, so at crash it has forwarded exactly `[0, K)`); life2 resumes from that same `K`, so the boundary aligns and `[0, K)` need never be re-sent. The crash was NOT byte loss — it was the consumer running the strict **reject-gap legacy path** (handoff left `session_cursors` empty) which treats any out-of-order seq as fatal. PRE-EXISTING, surfaced by the v0.13.0 green-both-runners gate; P1b is innocent. Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`.

+- **Invariant:** on a single brain↔broker connection exactly ONE `controller_writer` is ever the LIVE writer; a SUPERSEDED writer writes no further frames after the epoch bump it observes; and **every `controller_writer` emits a strictly ASCENDING seq stream** (sorted initial batch + ascending live frames). The CORRECTNESS guarantee that falls out: a snap-above consumer over any interleaving of ascending writers — where the surviving writer (`serve_attach`'s `attach_as(sid,0)`) offers the COMPLETE range `[0, end]` — delivers `[K, end]` with **no skip and no dup** (the first sighting of any seq `>M` is always preceded by a sighting of `M` on that same ascending writer, so `M` is delivered before the cursor can pass it). Enforced/relied-on three ways (NB: fix #1 — "drop handoff's eager subscribe" — was REVERTED: that subscribe is the standalone-resume mechanism the brain-only update engine + `handoff`/`idempotent`/`daemon_e2e` replay through with no `serve_attach`): (1) CORRECTNESS — `Brain::handoff` seeds `session_cursors` at `prior.next_seq` so the consumer runs dedup-below + snap-above (resume mode), never the reject-gap legacy trap; the ascending-merge property above makes this complete, not merely tolerant; (2) INVARIANT — `controller_writer` is EPOCH-GATED: `controller_epoch` is a shared `Arc<AtomicU64>`, the writer re-reads it UNDER `send.lock()` (atomically with `write_frame`) and returns the instant it is superseded, on BOTH the initial-batch and live loops — so a superseded writer can never flush past the bump and the live writer is unique (W1-safe: never blocks the drain under `Mutex<OutputLog>`); (3) EXPLICIT-RESUME — an explicit `Brain::attach(sid, from_seq)` in resume mode RESETS that session's dedup cursor to `from_seq` (a deliberate re-subscribe honors its floor; `read_event`'s `or_insert` only seeds a first-sight session, so without this a from-0 ground-truth re-read after a resume dedup-drops its own replay). Cold-start brains (empty map) keep the legacy `next_seq` path untouched.

+- **spt-core mapping:** impl `brain.rs` `Brain::handoff` (KEEP the eager `subscribe`; seed `session_cursors`) + `Brain::attach` (resume-mode cursor reset to `from_seq`) + `broker.rs` `OutputLog.controller_epoch: Arc<AtomicU64>` / `become_controller` (atomic `fetch_add`, passes the new epoch + `Arc::clone` into the writer) / `controller_writer` (epoch gate read UNDER the lock on both loops) / `mark_controller_gone` + the `ControllerJob` epoch read; unit (white-box, `src/broker.rs`) the epoch-gated writer (a superseded writer flushes nothing — only the latest writer's monotonic stream reaches the wire) + `handoff` seeds `session_cursors`/resubscribes; int (keystone, `tests/broker.rs` + `tests/attach.rs`) deterministically force two `become_controller`-on-one-connection on a real broker+brain (no mocks) — PRE-FIX reorders/gaps, POST-FIX monotonic + byte-exact + session live, PLUS `attach_survives_target_brain_restart_exactly_once` green (doyle: 20× isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier).

+- **Source:** v0.13.0 P1c (operator-ruled root-fix before ship; doyle root-cause via instrumented repro 2026-06-20; design corrected at the gate — fix #1 reverted, epoch-gate + snap-above + attach-reset carry it). The last v0.13.0 ship-blocker.


Now the conformance checklist row + the REQ registry text. Updating the 7.21 checklist row:


| 7.21 | Exactly ONE `controller_writer` per brain↔broker connection — a superseded writer writes nothing further, so the on-wire controller seq stream stays monotonic. A brain-restart re-serve double-registered the controller (handoff's eager `subscribe(from_seq=1)` + the re-serve's `attach_as(sid,0)`) → two writers raced one socket → `got seq 1 want 0` gap (flaky `attach_survives_target_brain_restart_exactly_once`). FIX: (1) `handoff` drops the eager subscribe (the re-serve's `attach_as` is the sole take); (2) `controller_writer` is epoch-gated via a shared `Arc<AtomicU64>` `controller_epoch` (returns the instant it's superseded, both loops); (3) `handoff` seeds `session_cursors` → dedup-below + snap-above, not reject-gap. Pre-existing; P1b innocent | `brain.rs` `handoff`, `broker.rs` `become_controller`/`controller_writer`/`controller_epoch`, int `attach.rs` (keystone + restart carrier, 20× on kitsubito) |

| 7.21 | Exactly ONE LIVE `controller_writer` per brain↔broker connection + every writer emits an ASCENDING seq stream ⇒ a snap-above consumer over the surviving writer's COMPLETE `[0,end]` replay delivers `[K,end]` with no skip/dup. A brain-restart re-serve double-registered the controller (handoff's `subscribe(from_seq=K)` + the re-serve's `attach_as(sid,0)`) → two writers raced one socket → the consumer's strict reject-gap legacy path saw `got seq 1 want 0` (flaky `attach_survives_target_brain_restart_exactly_once`). FIX (fix #1 "drop handoff's subscribe" REVERTED — it's the standalone-resume mechanism): (1) `handoff` seeds `session_cursors` → dedup-below + snap-above (correctness, made complete by the ascending-merge property); (2) `controller_writer` epoch-gated via shared `Arc<AtomicU64>` `controller_epoch`, re-read UNDER `send.lock()` (single live writer); (3) explicit `Brain::attach(sid,from_seq)` resets the resume-mode dedup cursor to `from_seq`. Pre-existing; P1b innocent | `brain.rs` `handoff`/`attach`, `broker.rs` `become_controller`/`controller_writer`/`controller_epoch`, unit `src/broker.rs`, int `tests/broker.rs`+`attach.rs` (keystone + restart carrier, 20× on kitsubito) |


| 7.18 | `spt rc` paste is **client-originated** on Windows: CC runs daemon-side with no access to the operator's LOCAL clipboard. On a RIGHT-CLICK rc reads the local clipboard itself and injects a BRACKETED paste (`ESC[200~` + content + `ESC[201~`) — CC has bracketed-paste mode on (`ESC[?2004h`), so a multi-line paste lands intact with NO `\r` submit-storm, harness-agnostic, content VERBATIM. RawGuard captures the mouse (disables console QuickEdit so right-click reaches the app) on an interactive console only + restores on drop. **ctrl+V is NOT intercepted** (P1b): WT consumes it (Key RELEASE only, never Press) + injects the clipboard as a key flood — it rides WT's native paste as keystrokes (no wedge, 7.19; bracketed = right-click). cfg(windows) only — Unix pastes natively | `rc.rs` `wrap_bracketed_paste`/`mouse_is_paste`/`clipboard_paste`/`read_clipboard`/`RawGuard`/`spawn_stdin_reader_events`, unit-only (live clipboard+mouse = HITL) |

| 7.19 | An operator input FLOOD must not deadlock the broker: `serve_attach` sends N `Input` frames on one conn without reading, the broker acks each on the SAME conn → the return direction fills (~pipe buffer) → `send_frame` blocks the per-conn handler → mutual full-duplex DEADLOCK (permanent broker wedge, controller latched). FIX: opt-in ack — `InputReq.ack` (serde default true); the operator/rc path sends `ack=false` (`send_effect_no_ack`), `dispatch_input` skips the applied frame → the handler never writes back while draining the flood. `shellchan` keeps `ack=true` (its `Applied`-wait). Exactly-once unaffected (dedup at the applied-set). N-1: an old resident broker still acks until restart (7.9 class) | `msg.rs` `InputReq.ack`, `brain.rs` `send_effect_no_ack`, `attach.rs` `serve_attach`, `broker.rs` `dispatch_input`, int (flood repro) |

| 7.20 | `spt rc` must forward the SCROLL wheel to the harness — our mouse capture (for right-click paste, 7.18) steals WT's native scroll. Track the harness's mouse-reporting mode from its OUTPUT (DECSET `ESC[?1000/1002/1003h` + `1006h` SGR, and `…l` off; scan survives a split across output chunks) into `MouseMode{enabled,sgr}`; forward `ScrollUp/Down` as an xterm SGR report (`ESC[<64/65;col+1;row+1M`) ONLY when `enabled && sgr`, else drop; Moved/drag/clicks dropped. cfg(windows) only — Unix scrolls natively | `rc.rs` `MouseMode`/`MouseModeScanner`/`scroll_dir`/`scroll_sgr`/`spawn_stdin_reader_events`, unit-only (live mouse = HITL) |

-| 7.21 | Exactly ONE `controller_writer` per brain↔broker connection — a superseded writer writes nothing further, so the on-wire controller seq stream stays monotonic. A brain-restart re-serve double-registered the controller (handoff's eager `subscribe(from_seq=1)` + the re-serve's `attach_as(sid,0)`) → two writers raced one socket → `got seq 1 want 0` gap (flaky `attach_survives_target_brain_restart_exactly_once`). FIX: (1) `handoff` drops the eager subscribe (the re-serve's `attach_as` is the sole take); (2) `controller_writer` is epoch-gated via a shared `Arc<AtomicU64>` `controller_epoch` (returns the instant it's superseded, both loops); (3) `handoff` seeds `session_cursors` → dedup-below + snap-above, not reject-gap. Pre-existing; P1b innocent | `brain.rs` `handoff`, `broker.rs` `become_controller`/`controller_writer`/`controller_epoch`, int `attach.rs` (keystone + restart carrier, 20× on kitsubito) |

+| 7.21 | Exactly ONE LIVE `controller_writer` per brain↔broker connection + every writer emits an ASCENDING seq stream ⇒ a snap-above consumer over the surviving writer's COMPLETE `[0,end]` replay delivers `[K,end]` with no skip/dup. A brain-restart re-serve double-registered the controller (handoff's `subscribe(from_seq=K)` + the re-serve's `attach_as(sid,0)`) → two writers raced one socket → the consumer's strict reject-gap legacy path saw `got seq 1 want 0` (flaky `attach_survives_target_brain_restart_exactly_once`). FIX (fix #1 "drop handoff's subscribe" REVERTED — it's the standalone-resume mechanism): (1) `handoff` seeds `session_cursors` → dedup-below + snap-above (correctness, made complete by the ascending-merge property); (2) `controller_writer` epoch-gated via shared `Arc<AtomicU64>` `controller_epoch`, re-read UNDER `send.lock()` (single live writer); (3) explicit `Brain::attach(sid,from_seq)` resets the resume-mode dedup cursor to `from_seq`. Pre-existing; P1b innocent | `brain.rs` `handoff`/`attach`, `broker.rs` `become_controller`/`controller_writer`/`controller_epoch`, unit `src/broker.rs`, int `tests/broker.rs`+`attach.rs` (keystone + restart carrier, 20× on kitsubito) |


Updating the REQ registry — the FIX narrative (fix #1 reverted, epoch-gate + snap-above primary):


FIX (doyle design, V0.13.0-P1C-CONTROLLER-WRITER-REORDER-PLAN.md, three parts): (1) PRIMARY — `Brain::handoff` no longer eagerly `subscribe`s-as-controller; `serve_attach`'s `attach_as(sid,0)` is the SOLE controller registration + replay for that connection (handoff is test-only per the brain.rs comment; no production caller depends on the eager subscribe — production resumes via `cold_start`+`resume_sessions`). (2) BROKER HARDENING — `controller_writer` is epoch-gated: `controller_epoch` becomes a shared `Arc<AtomicU64>`, the writer snapshots its own epoch and checks the shared one before each frame (initial-batch AND live loop), returning the moment it is superseded — so a double-registration can never silently keep a superseded writer flushing (W1-safe: never blocks the drain under `Mutex<OutputLog>`). (3) DEFENSE-IN-DEPTH — `Brain::handoff` seeds `session_cursors` at `prior.next_seq` so the consumer uses the production dedup-below+snap-above path (matching `resume_sessions`), not the strict reject-gap legacy trap. (v0.13.0)"

FIX (doyle design, corrected at the gate 2026-06-20): fix #1 as designed ('drop handoff's eager subscribe so serve_attach's attach_as is the sole registration') was REVERTED — handoff's `subscribe(prior.next_seq)` IS the standalone-resume mechanism (the brain-only update engine `apply_brain_only` + the `handoff`/`idempotent`/`daemon_e2e` int tests replay output through it with NO `serve_attach`; dropping it hung every resume-via-handoff test). The shipped fix is three parts: (1) CORRECTNESS — `Brain::handoff` seeds `session_cursors` at `prior.next_seq` so the consumer runs the production dedup-below+snap-above path, never the strict reject-gap legacy trap; this is COMPLETE (not merely tolerant) because every `controller_writer` emits an ASCENDING seq stream and the surviving writer (serve_attach's attach_as(sid,0)) offers the complete `[0,end]` range, so a snap-above merge of ascending writers delivers `[K,end]` with no skip/dup (first sighting of any seq>M is preceded by M on that writer). (2) INVARIANT — `controller_writer` is epoch-gated: `controller_epoch` is a shared `Arc<AtomicU64>`, the writer re-reads it UNDER `send.lock()` (atomically with `write_frame`) on BOTH the initial-batch and live loops and returns the instant it is superseded — single live writer per connection, no check-then-block-then-write window (W1-safe: never blocks the drain under `Mutex<OutputLog>`). (3) EXPLICIT-RESUME — an explicit `Brain::attach(sid,from_seq)` in resume mode resets that session's dedup cursor to `from_seq` (a deliberate re-subscribe honors its floor; `read_event`'s `or_insert` only seeds a first-sight session, so a from-0 ground-truth re-read after a resume would otherwise dedup-drop its own replay); cold-start brains (empty map) keep the legacy `next_seq` path. (v0.13.0)"


The file C:\Users\decid\Documents\projects\spt-core\traceable-reqs.toml has been updated successfully. (file state is current in your context — no need to Read it back)

# ── P1c (operator-ruled root-fix before v0.13.0 ship; doyle root-cause via instrumented repro on kitsubito, 2026-06-20): controller-writer reorder on brain-restart re-serve ──

-title = "Two `controller_writer` threads must never race ONE brain↔broker connection's socket. ROOT (doyle, instrumented RACEDIAG repro on kitsubito): on a brain-restart re-serve the handoff brain registers as controller on the SAME session TWICE over the SAME `Brain::conn` socket — (1) `Brain::handoff` eagerly `subscribe(prior.session_id, prior.next_seq=1)` → `become_controller(from_seq=1)`, initial=[1], spawns writer-A (writes seq 1); (2) `serve_attach` re-handles the replayed `Request{from_seq:0}` → `attach_as(sid,0)` → `become_controller(from_seq=0)`, initial=[0,1], spawns writer-B (writes 0 then 1). `become_controller` (broker.rs) drops the prior `ControllerSink` (its `tx`) but does NOT stop the prior writer thread — writer-A keeps flushing its owned `initial` batch, and both writers hold clones of the same `SharedSend` (`Arc<Mutex<socket>>`) with NO inter-thread ordering. When writer-A's seq 1 wins the socket before writer-B's seq 0, the strict legacy consumer (brain.rs read_event reject-gap path) sees `output gap: got seq 1 want 0` → the test `attach_survives_target_brain_restart_exactly_once` panics at `.expect(\"re-serve\")` OR HANGS in `render_until` (serve thread died on the gap → MARKER_TWO never reaches the wire). `prior.next_seq` is life1's CONSUMPTION cursor, NOT life2's connection state — life2's socket has been sent NOTHING, so a `from_seq=0` full replay on a connection that already streamed seq 1 is contradictory. Snap-above tolerance ALONE can't fix it (it would dedup-drop the late seq 0 → byte loss → the exactly-once byte-identity assert fails). PRE-EXISTING, surfaced by the v0.13.0 green-both-runners release gate; P1b is INNOCENT (its diff touches only input-ack machinery, proven mechanically + the test passes post-P1b in isolation). Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`. INVARIANT: on a single brain↔broker connection the controller output-frame stream is monotonic non-decreasing in seq (modulo dedup re-sends); exactly ONE `controller_writer` is ever live per connection; a SUPERSEDED writer writes NO further frames; a re-serve never replays a seq below what the connection already received. FIX (doyle design, V0.13.0-P1C-CONTROLLER-WRITER-REORDER-PLAN.md, three parts): (1) PRIMARY — `Brain::handoff` no longer eagerly `subscribe`s-as-controller; `serve_attach`'s `attach_as(sid,0)` is the SOLE controller registration + replay for that connection (handoff is test-only per the brain.rs comment; no production caller depends on the eager subscribe — production resumes via `cold_start`+`resume_sessions`). (2) BROKER HARDENING — `controller_writer` is epoch-gated: `controller_epoch` becomes a shared `Arc<AtomicU64>`, the writer snapshots its own epoch and checks the shared one before each frame (initial-batch AND live loop), returning the moment it is superseded — so a double-registration can never silently keep a superseded writer flushing (W1-safe: never blocks the drain under `Mutex<OutputLog>`). (3) DEFENSE-IN-DEPTH — `Brain::handoff` seeds `session_cursors` at `prior.next_seq` so the consumer uses the production dedup-below+snap-above path (matching `resume_sessions`), not the strict reject-gap legacy trap. (v0.13.0)"

+title = "Two `controller_writer` threads must never race ONE brain↔broker connection's socket. ROOT (doyle, instrumented RACEDIAG repro on kitsubito): on a brain-restart re-serve the handoff brain registers as controller on the SAME session TWICE over the SAME `Brain::conn` socket — (1) `Brain::handoff` eagerly `subscribe(prior.session_id, prior.next_seq=1)` → `become_controller(from_seq=1)`, initial=[1], spawns writer-A (writes seq 1); (2) `serve_attach` re-handles the replayed `Request{from_seq:0}` → `attach_as(sid,0)` → `become_controller(from_seq=0)`, initial=[0,1], spawns writer-B (writes 0 then 1). `become_controller` (broker.rs) drops the prior `ControllerSink` (its `tx`) but does NOT stop the prior writer thread — writer-A keeps flushing its owned `initial` batch, and both writers hold clones of the same `SharedSend` (`Arc<Mutex<socket>>`) with NO inter-thread ordering. When writer-A's seq 1 wins the socket before writer-B's seq 0, the strict legacy consumer (brain.rs read_event reject-gap path) sees `output gap: got seq 1 want 0` → the test `attach_survives_target_brain_restart_exactly_once` panics at `.expect(\"re-serve\")` OR HANGS in `render_until` (serve thread died on the gap → MARKER_TWO never reaches the wire). `prior.next_seq` is life1's CONSUMPTION cursor, NOT life2's connection state — life2's socket has been sent NOTHING, so a `from_seq=0` full replay on a connection that already streamed seq 1 is contradictory. Snap-above tolerance ALONE can't fix it (it would dedup-drop the late seq 0 → byte loss → the exactly-once byte-identity assert fails). PRE-EXISTING, surfaced by the v0.13.0 green-both-runners release gate; P1b is INNOCENT (its diff touches only input-ack machinery, proven mechanically + the test passes post-P1b in isolation). Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`. INVARIANT: on a single brain↔broker connection the controller output-frame stream is monotonic non-decreasing in seq (modulo dedup re-sends); exactly ONE `controller_writer` is ever live per connection; a SUPERSEDED writer writes NO further frames; a re-serve never replays a seq below what the connection already received. FIX (doyle design, corrected at the gate 2026-06-20): fix #1 as designed ('drop handoff's eager subscribe so serve_attach's attach_as is the sole registration') was REVERTED — handoff's `subscribe(prior.next_seq)` IS the standalone-resume mechanism (the brain-only update engine `apply_brain_only` + the `handoff`/`idempotent`/`daemon_e2e` int tests replay output through it with NO `serve_attach`; dropping it hung every resume-via-handoff test). The shipped fix is three parts: (1) CORRECTNESS — `Brain::handoff` seeds `session_cursors` at `prior.next_seq` so the consumer runs the production dedup-below+snap-above path, never the strict reject-gap legacy trap; this is COMPLETE (not merely tolerant) because every `controller_writer` emits an ASCENDING seq stream and the surviving writer (serve_attach's attach_as(sid,0)) offers the complete `[0,end]` range, so a snap-above merge of ascending writers delivers `[K,end]` with no skip/dup (first sighting of any seq>M is preceded by M on that writer). (2) INVARIANT — `controller_writer` is epoch-gated: `controller_epoch` is a shared `Arc<AtomicU64>`, the writer re-reads it UNDER `send.lock()` (atomically with `write_frame`) on BOTH the initial-batch and live loops and returns the instant it is superseded — single live writer per connection, no check-then-block-then-write window (W1-safe: never blocks the drain under `Mutex<OutputLog>`). (3) EXPLICIT-RESUME — an explicit `Brain::attach(sid,from_seq)` in resume mode resets that session's dedup cursor to `from_seq` (a deliberate re-subscribe honors its floor; `read_event`'s `or_insert` only seeds a first-sight session, so a from-0 ground-truth re-read after a resume would otherwise dedup-drop its own replay); cold-start brains (empty map) keep the legacy `next_seq` path. (v0.13.0)"

required_stages = ["doc", "impl", "unit", "int"]  # ACTIVATED v0.13.0 P1c (todlando, the last v0.13.0 ship-blocker — pre-existing flaky resume race that gates green-both-runners; doyle root-caused + designed, doyle gates). doc = KNOWN-HAZARDS entry (the reorder + the single-live-writer-per-connection invariant + the two compounding defects) + CONTEXT note. impl = (1) Brain::handoff drops the eager subscribe(prior.session_id, prior.next_seq) call; (2) OutputLog.controller_epoch -> Arc<AtomicU64>, become_controller passes the new epoch + Arc::clone into controller_writer, which returns when controller_epoch != its snapshot (read UNDER send.lock(), atomically with write_frame, on both the initial-batch loop and the live recv loop), become_controller/mark_controller_gone/the ControllerJob epoch read switch to atomic load/fetch_add; (3) Brain::handoff seeds session_cursors.insert(prior.session_id, prior.next_seq). unit = epoch-gated controller_writer: a superseded writer (epoch bumped) writes NOTHING from its initial batch (real broker socket, two become_controller on one connection -> only the latest writer's monotonic 0,1 reaches the wire) + handoff seeds session_cursors (session_cursor(sid) == prior.next_seq) + handoff issues no eager subscribe. int = the keystone: deterministically force two become_controller-on-one-connection (handoff-then-reserve ordering) on a real broker+brain, NO mocks -> PRE-FIX the wire reorders (got seq 1 want 0 / gap or byte-drop) -> POST-FIX the wire stays monotonic + byte-exact + the session stays live; PLUS attach_survives_target_brain_restart_exactly_once green (doyle runs it 20x isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier). Full seam sweep (attach/broker/resume/brain_swap/inject_control_wedge — the shared W1 controller-writer model). clippy/traceable/docs-drift."

# ── P1c follow-up SEED (doyle proposed, todlando gated, doyle concurred 2026-06-20): the structural per-connection-floor guard — inactive, activate-don't-pre-fail ──


Updating the `required_stages` impl/unit narrative:


impl = (1) Brain::handoff drops the eager subscribe(prior.session_id, prior.next_seq) call; (2) OutputLog.controller_epoch -> Arc<AtomicU64>, become_controller passes the new epoch + Arc::clone into controller_writer, which returns when controller_epoch != its snapshot (read UNDER send.lock(), atomically with write_frame, on both the initial-batch loop and the live recv loop), become_controller/mark_controller_gone/the ControllerJob epoch read switch to atomic load/fetch_add; (3) Brain::handoff seeds session_cursors.insert(prior.session_id, prior.next_seq). unit = epoch-gated controller_writer: a superseded writer (epoch bumped) writes NOTHING from its initial batch (real broker socket, two become_controller on one connection -> only the latest writer's monotonic 0,1 reaches the wire) + handoff seeds session_cursors (session_cursor(sid) == prior.next_seq) + handoff issues no eager subscribe.

impl = (1) Brain::handoff KEEPS its eager subscribe(prior.session_id, prior.next_seq) [fix #1 REVERTED — load-bearing resume] AND seeds session_cursors.insert(prior.session_id, prior.next_seq); (2) OutputLog.controller_epoch -> Arc<AtomicU64>, become_controller passes the new epoch + Arc::clone into controller_writer, which returns when controller_epoch != its snapshot (read UNDER send.lock(), atomically with write_frame, on both the initial-batch loop and the live recv loop), become_controller/mark_controller_gone/the ControllerJob epoch read switch to atomic load/fetch_add; (3) Brain::attach resets session_cursors.insert(session_id, from_seq) when in resume mode (non-empty map) so an explicit re-attach honors its floor. unit = epoch-gated controller_writer: a superseded writer (epoch bumped) writes NOTHING from its initial batch (real broker socket, two become_controller on one connection -> only the latest writer's monotonic stream reaches the wire) + handoff seeds session_cursors (session_cursor(sid) == prior.next_seq) + resubscribes for resume.


title = "Two `controller_writer` threads must never race ONE brain↔broker connection's socket. ROOT (doyle, instrumented RACEDIAG repro on kitsubito): on a brain-restart re-serve the handoff brain registers as controller on the SAME session TWICE over the SAME `Brain::conn` socket — (1) `Brain::handoff` eagerly `subscribe(prior.session_id, prior.next_seq=1)` → `become_controller(from_seq=1)`, initial=[1], spawns writer-A (writes seq 1); (2) `serve_attach` re-handles the replayed `Request{from_seq:0}` → `attach_as(sid,0)` → `become_controller(from_seq=0)`, initial=[0,1], spawns writer-B (writes 0 then 1). `become_controller` (broker.rs) drops the prior `ControllerSink` (its `tx`) but does NOT stop the prior writer thread — writer-A keeps flushing its owned `initial` batch, and both writers hold clones of the same `SharedSend` (`Arc<Mutex<socket>>`) with NO inter-thread ordering. When writer-A's seq 1 wins the socket before writer-B's seq 0, the strict legacy consumer (brain.rs read_event reject-gap path) sees `output gap: got seq 1 want 0` → the test `attach_survives_target_brain_restart_exactly_once` panics at `.expect(\"re-serve\")` OR HANGS in `render_until` (serve thread died on the gap → MARKER_TWO never reaches the wire). `prior.next_seq` is life1's CONSUMPTION cursor, NOT life2's connection state — life2's socket has been sent NOTHING, so a `from_seq=0` full replay on a connection that already streamed seq 1 is contradictory. Snap-above tolerance ALONE can't fix it (it would dedup-drop the late seq 0 → byte loss → the exactly-once byte-identity assert fails). PRE-EXISTING, surfaced by the v0.13.0 green-both-runners release gate; P1b is INNOCENT (its diff touches only input-ack machinery, proven mechanically + the test passes post-P1b in isolation). Sibling flaky cluster: `inject_control_wedge::g2`, `broker::spawn_env_reaches_child`. INVARIANT: on a single brain↔broker connection the controller output-frame stream is monotonic non-decreasing in seq (modulo dedup re-sends); exactly ONE `controller_writer` is ever live per connection; a SUPERSEDED writer writes NO further frames; a re-serve never replays a seq below what the connection already received. FIX (doyle design, corrected at the gate 2026-06-20): fix #1 as designed ('drop handoff's eager subscribe so serve_attach's attach_as is the sole registration') was REVERTED — handoff's `subscribe(prior.next_seq)` IS the standalone-resume mechanism (the brain-only update engine `apply_brain_only` + the `handoff`/`idempotent`/`daemon_e2e` int tests replay output through it with NO `serve_attach`; dropping it hung every resume-via-handoff test). The shipped fix is three parts: (1) CORRECTNESS — `Brain::handoff` seeds `session_cursors` at `prior.next_seq` so the consumer runs the production dedup-below+snap-above path, never the strict reject-gap legacy trap; this is COMPLETE (not merely tolerant) because every `controller_writer` emits an ASCENDING seq stream and the surviving writer (serve_attach's attach_as(sid,0)) offers the complete `[0,end]` range, so a snap-above merge of ascending writers delivers `[K,end]` with no skip/dup (first sighting of any seq>M is preceded by M on that writer). (2) INVARIANT — `controller_writer` is epoch-gated: `controller_epoch` is a shared `Arc<AtomicU64>`, the writer re-reads it UNDER `send.lock()` (atomically with `write_frame`) on BOTH the initial-batch and live loops and returns the instant it is superseded — single live writer per connection, no check-then-block-then-write window (W1-safe: never blocks the drain under `Mutex<OutputLog>`). (3) EXPLICIT-RESUME — an explicit `Brain::attach(sid,from_seq)` in resume mode resets that session's dedup cursor to `from_seq` (a deliberate re-subscribe honors its floor; `read_event`'s `or_insert` only seeds a first-sight session, so a from-0 ground-truth re-read after a resume would otherwise dedup-drop its own replay); cold-start brains (empty map) keep the legacy `next_seq` path. (v0.13.0)"

-required_stages = ["doc", "impl", "unit", "int"]  # ACTIVATED v0.13.0 P1c (todlando, the last v0.13.0 ship-blocker — pre-existing flaky resume race that gates green-both-runners; doyle root-caused + designed, doyle gates). doc = KNOWN-HAZARDS entry (the reorder + the single-live-writer-per-connection invariant + the two compounding defects) + CONTEXT note. impl = (1) Brain::handoff drops the eager subscribe(prior.session_id, prior.next_seq) call; (2) OutputLog.controller_epoch -> Arc<AtomicU64>, become_controller passes the new epoch + Arc::clone into controller_writer, which returns when controller_epoch != its snapshot (read UNDER send.lock(), atomically with write_frame, on both the initial-batch loop and the live recv loop), become_controller/mark_controller_gone/the ControllerJob epoch read switch to atomic load/fetch_add; (3) Brain::handoff seeds session_cursors.insert(prior.session_id, prior.next_seq). unit = epoch-gated controller_writer: a superseded writer (epoch bumped) writes NOTHING from its initial batch (real broker socket, two become_controller on one connection -> only the latest writer's monotonic 0,1 reaches the wire) + handoff seeds session_cursors (session_cursor(sid) == prior.next_seq) + handoff issues no eager subscribe. int = the keystone: deterministically force two become_controller-on-one-connection (handoff-then-reserve ordering) on a real broker+brain, NO mocks -> PRE-FIX the wire reorders (got seq 1 want 0 / gap or byte-drop) -> POST-FIX the wire stays monotonic + byte-exact + the session stays live; PLUS attach_survives_target_brain_restart_exactly_once green (doyle runs it 20x isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier). Full seam sweep (attach/broker/resume/brain_swap/inject_control_wedge — the shared W1 controller-writer model). clippy/traceable/docs-drift."

+required_stages = ["doc", "impl", "unit", "int"]  # ACTIVATED v0.13.0 P1c (todlando, the last v0.13.0 ship-blocker — pre-existing flaky resume race that gates green-both-runners; doyle root-caused + designed, doyle gates). doc = KNOWN-HAZARDS entry (the reorder + the single-live-writer-per-connection invariant + the two compounding defects) + CONTEXT note. impl = (1) Brain::handoff KEEPS its eager subscribe(prior.session_id, prior.next_seq) [fix #1 REVERTED — load-bearing resume] AND seeds session_cursors.insert(prior.session_id, prior.next_seq); (2) OutputLog.controller_epoch -> Arc<AtomicU64>, become_controller passes the new epoch + Arc::clone into controller_writer, which returns when controller_epoch != its snapshot (read UNDER send.lock(), atomically with write_frame, on both the initial-batch loop and the live recv loop), become_controller/mark_controller_gone/the ControllerJob epoch read switch to atomic load/fetch_add; (3) Brain::attach resets session_cursors.insert(session_id, from_seq) when in resume mode (non-empty map) so an explicit re-attach honors its floor. unit = epoch-gated controller_writer: a superseded writer (epoch bumped) writes NOTHING from its initial batch (real broker socket, two become_controller on one connection -> only the latest writer's monotonic stream reaches the wire) + handoff seeds session_cursors (session_cursor(sid) == prior.next_seq) + resubscribes for resume. int = the keystone: deterministically force two become_controller-on-one-connection (handoff-then-reserve ordering) on a real broker+brain, NO mocks -> PRE-FIX the wire reorders (got seq 1 want 0 / gap or byte-drop) -> POST-FIX the wire stays monotonic + byte-exact + the session stays live; PLUS attach_survives_target_brain_restart_exactly_once green (doyle runs it 20x isolated single-threaded timeout-wrapped on Linux/kitsubito — the deterministic RED-on-revert carrier). Full seam sweep (attach/broker/resume/brain_swap/inject_control_wedge — the shared W1 controller-writer model). clippy/traceable/docs-drift."


Correcting the DEFERRED.md row's description of the P1c fix (handoff keeps subscribe; double-take present, made safe by epoch-gate + ascending-merge snap-above):


v0.13.0 P1c fixes the controller-writer reorder three ways — `Brain::handoff` drops its eager subscribe (removes the one decreasing-floor double-take at the caller), `controller_writer` is epoch-gated under `send.lock()` (bounds any other double-take to already-committed-only), and `handoff` seeds `session_cursors` (consumer snap-aboves). doyle proposed making the invariant **structurally un-reintroducible**: have `become_controller` refuse/clamp a re-take whose `from_seq` falls below the connection's already-delivered floor.

v0.13.0 P1c fixes the controller-writer reorder while KEEPING handoff's eager subscribe (fix #1 "drop the subscribe" was reverted — it's the standalone-resume mechanism), so the decreasing-floor double-take (handoff subscribe@K + serve_attach subscribe@0) is still PRESENT and made safe by: `controller_writer` epoch-gated under `send.lock()` (single live writer per connection) + `handoff` seeds `session_cursors` so the consumer snap-aboves, which is COMPLETE because every writer emits ascending and the surviving writer offers the full `[0,end]` range (no skip/dup). doyle proposed making the invariant **structurally un-reintroducible**: have `become_controller` refuse/clamp a re-take whose `from_seq` falls below the connection's already-delivered floor.


The file C:\Users\decid\Documents\projects\spt-core\docs\DEFERRED.md has been updated successfully. (file state is current in your context — no need to Read it back)

| **Two-origin `owl_message` context-tap subtype refinement (M10 ADR-0019 deferral)**: the two-origin merge's owl-message producer (`spt::api::startup` `deliver` closure) taps the live-agent **`emit` chokepoint**, so EVERY delivered frame — including resurfaced **notif** frames and shell-context rows — is recorded as a single coarse `owl_message` context-injection entry (`context_kind:"owl_message"`). The data is not wrong (a notif IS injected context), only coarsely labeled; the digest is a glanceable data model this milestone, with no consumer that distinguishes the subtypes yet. Splitting the tap into honest subtypes (true peer message vs notif vs shell-context) means classifying the frame at the delivery seam. | M10 Wave 3 / gate (doyle ruling 2026-06-13, flag 2 ACCEPTED with this tracked condition) | Same logic as the M9 freshness deferral above: refinement only matters when a surface reads + renders the context-injection category by subtype (GUI collapse/expand, or the echo-reads-digest delta loop). Coarse-but-honest labeling is correct for a data-model-only milestone | The **consuming-frontend / echo-reads-digest milestone** — split the `emit`-seam tap by frame type (peer message vs notif vs shell-context) when a reader renders the subtypes |

| **W2.5 — attached-presence + Kick-and-attach (M12 picker blue tri-state)**: M12 W2's picker ships online/offline status only; the **blue ■ "attached" tri-state** + the **"Kick `<node>` and attach"** confirm option were SCHEDULED (operator 2026-06-14, NOT dropped) as a dedicated slice built AFTER W2 lands, then wired back into the picker. Scope: (1) a **broker attach-presence query** — "who is attached to endpoint E's PTY, by which node/surface" — derive from the `presence.rs` PresenceLog conn connect/disconnect if sound, else a new query op (today `presence.rs` has snapshots/most_recently_active/resolve but no per-PTY attach owner); (2) a **force-detach/kick wire op** with its OWN KNOWN-HAZARDS treatment — the PTY-ownership invariant (KH attach-lifecycle: detach never kills the session) + a who-may-kick auth gate — this hazard-zone surface is the reason it is its own slice, not a picker-wave rider; (3) picker: the blue tri-state + the Kick option (status becomes online/attached/offline; Kick is EXCLUSIVE to already-attached endpoints). | M12 W2 design ruling (doyle/operator 2026-06-14, M12-W2-RULING.md Q1) | A new broker MUTATION surface in the PTY-ownership hazard zone earns its own focused JIT plan + design-check + gate; bundling it into the picker UX wave would mix a hazard-zone broker op with front-end work. W2 ships the picker over surfaces that exist | **Immediately after W2 lands** (W2.5) — own JIT plan + doyle design-check (like W2/W3) + own gate; mint REQ-* first (rule 3) |

| **Cross-node shell TUNNEL relay (REQ-SHELL-4 cross-node-on-LAN carry)**: W3 built + proved the opaque byte tunnel **same-node only** (broker-homed `TunnelHub` loopback stream pair + the local control socket; `tunnel_e2e` round-trips `<EVENT`-looking bytes byte-exact). The **cross-node** path does NOT exist: `StreamFamily` (dispatch.rs) has no `Tunnel` variant, `classify_first_line` no tunnel arm, `SHELL_LINK` carries only relink/cmd/drive (no tunnel action), and every tunnel surface (`tunnel_ensure/send/recv/resolve/clear`, `serve_tunnel_control`, `tunnel_owner_stream`) is broker-homed / local-socket = same-node. cmd+drive ride the existing `ShellLink` request/reply substrate cross-node; the byte tunnel has no such substrate. FIX (a proper impl wave, ~W3-sized): new `StreamFamily::Tunnel` + a `classify_first_line` arm + a dispatch serve arm bridging an inbound Iroh **bidi** stream ↔ the bound shell's broker `TunnelHub` pair + an owner-side cross-node open (a `SHELL_LINK_TUNNEL` action or a dedicated open) + a resident tunnel-echo mock peer + the `[twohost]` rung (`open_stream` over the real link, byte-exact opaque round-trip, link-break closes). REQ-SHELL-4 int stays satisfied by the same-node `tunnel_e2e` — this is an additional cross-node int rung, NOT yet an obligation (activate-don't-pre-fail). | M11-W5 (doyle ruling 2026-06-16) — W5 surfaced that the M11-PLAN T5.1 "tunnel rides the same Iroh substrate" assumption is false for the byte tunnel; building a W3-sized relay in the M11-closing rig+docs wave would balloon scope | The tunnel's real consumer (usbip URB byte stream) is itself deferred/non-goal — NOTHING in-tree needs cross-node tunnel bytes now, so the relay would be speculative infra ahead of a deferred consumer (YAGNI). Same-node mechanism is proven; cross-node cmd/drive are proven; M11 closes at a clean boundary | First **cross-node tunnel consumer** (usbip URB across nodes, or any in-tree consumer of opaque cross-node bytes) — build the relay + the `[twohost]` rung as its own impl wave then |

-| **Per-connection contiguous-sent cursor — structural guard against a decreasing-floor controller re-take (`REQ-HAZARD-CONTROLLER-WRITER-REORDER` follow-up)**: v0.13.0 P1c fixes the controller-writer reorder three ways — `Brain::handoff` drops its eager subscribe (removes the one decreasing-floor double-take at the caller), `controller_writer` is epoch-gated under `send.lock()` (bounds any other double-take to already-committed-only), and `handoff` seeds `session_cursors` (consumer snap-aboves). doyle proposed making the invariant **structurally un-reintroducible**: have `become_controller` refuse/clamp a re-take whose `from_seq` falls below the connection's already-delivered floor. That guard as literally stated is UNSAFE — `delivered_through` is **session-wide** (the `Arc<AtomicU64>` on `OutputLog`, shared by all controllers/viewers, advanced monotonic-MAX) and `resume_seq` reads straight off it, so (a) a NORMAL fresh-operator `from_seq=0` attach to a producing session sits below it and needs the full ring replay (the dedup-below+snap-above path exists for exactly this) → a guard/assert there starves every normal attach, and (b) monotonic-MAX literally can't distinguish the hazard (a `seq1`-without-`seq0` write reads as `2`, falsely implying `0` was delivered). The structurally-correct guard needs a **per-connection contiguous-sent cursor** (a true "highest contiguous seq this socket has actually received"), which does not exist today — bigger than P1c. The precise shape it would refuse: a future double-take on one connection whose prior writer advanced the cursor NON-CONTIGUOUSLY could commit one pre-epoch-bump frame above the new writer's floor → reorder. | v0.13.0 P1c (doyle proposed, todlando gated, doyle concurred 2026-06-20) | The actual bug is fixed at the one caller + bounded to already-committed-only for any other + the consumer snap-aboves; a guard on the session-wide cursor would FALSE-FIRE on normal attach/resume (no-false-fire scope demands the per-connection cursor first). Activate-don't-pre-fail: `REQ-HAZARD-CONTROLLER-WRITER-REORDER` covers the shipped fix; this structural-guard slice is seeded inactive | First broker change that adds a per-connection delivered-cursor (or the next time the controller-writer/attach seam is reworked) — build the per-connection contiguous cursor + the `become_controller` refuse-decreasing-floor guard then; mint/activate a `REQ-HAZARD-CONTROLLER-REtake-FLOOR`-class req first (rule 3) |

+| **Per-connection contiguous-sent cursor — structural guard against a decreasing-floor controller re-take (`REQ-HAZARD-CONTROLLER-WRITER-REORDER` follow-up)**: v0.13.0 P1c fixes the controller-writer reorder while KEEPING handoff's eager subscribe (fix #1 "drop the subscribe" was reverted — it's the standalone-resume mechanism), so the decreasing-floor double-take (handoff subscribe@K + serve_attach subscribe@0) is still PRESENT and made safe by: `controller_writer` epoch-gated under `send.lock()` (single live writer per connection) + `handoff` seeds `session_cursors` so the consumer snap-aboves, which is COMPLETE because every writer emits ascending and the surviving writer offers the full `[0,end]` range (no skip/dup). doyle proposed making the invariant **structurally un-reintroducible**: have `become_controller` refuse/clamp a re-take whose `from_seq` falls below the connection's already-delivered floor. That guard as literally stated is UNSAFE — `delivered_through` is **session-wide** (the `Arc<AtomicU64>` on `OutputLog`, shared by all controllers/viewers, advanced monotonic-MAX) and `resume_seq` reads straight off it, so (a) a NORMAL fresh-operator `from_seq=0` attach to a producing session sits below it and needs the full ring replay (the dedup-below+snap-above path exists for exactly this) → a guard/assert there starves every normal attach, and (b) monotonic-MAX literally can't distinguish the hazard (a `seq1`-without-`seq0` write reads as `2`, falsely implying `0` was delivered). The structurally-correct guard needs a **per-connection contiguous-sent cursor** (a true "highest contiguous seq this socket has actually received"), which does not exist today — bigger than P1c. The precise shape it would refuse: a future double-take on one connection whose prior writer advanced the cursor NON-CONTIGUOUSLY could commit one pre-epoch-bump frame above the new writer's floor → reorder. | v0.13.0 P1c (doyle proposed, todlando gated, doyle concurred 2026-06-20) | The actual bug is fixed at the one caller + bounded to already-committed-only for any other + the consumer snap-aboves; a guard on the session-wide cursor would FALSE-FIRE on normal attach/resume (no-false-fire scope demands the per-connection cursor first). Activate-don't-pre-fail: `REQ-HAZARD-CONTROLLER-WRITER-REORDER` covers the shipped fix; this structural-guard slice is seeded inactive | First broker change that adds a per-connection delivered-cursor (or the next time the controller-writer/attach seam is reworked) — build the per-connection contiguous cursor + the `become_controller` refuse-decreasing-floor guard then; mint/activate a `REQ-HAZARD-CONTROLLER-REtake-FLOOR`-class req first (rule 3) |

| **Adapter-manifest-enabled rc VT/mouse mode (`spt rc` scroll vs right-click-paste xor resolution)**: v0.13.0 P1/P1b's Windows `EnableMouseCapture` (for client-originated right-click bracketed paste, 7.18) makes Windows Terminal hand ALL wheel events to rc instead of scrolling its own scrollback; rc forwards the wheel to the harness as SGR reports (7.20) but ONLY when the harness has mouse-reporting on (`enabled && sgr`) — and **Claude Code's REPL never enables mouse tracking** (it has no internal scroll; it relies on the terminal's scrollback), so every wheel event is dropped → scroll dies. Windows console modes can't give both at once: it's QuickEdit (native wheel-scroll + raw right-click = paste submit-storm) **xor** mouse-input (bracketed right-click paste + dead wheel). INTERIM SHIPPED: **Shift+scroll** (WT reserves it for local scrollback even under app mouse-capture) — operator-confirmed working, documented, zero code. FIX (the follow-up the operator asked for): an **adapter-manifest flag** declaring whether the harness actually CONSUMES mouse reports (a mouse-tracking TUI with internal scroll) — when declared, rc keeps full capture + the SGR scroll-forward (the current path, correct for such a harness); when NOT declared (default — CC's case), rc SKIPS `EnableMouseCapture` so WT native wheel-scroll works, trading away client-originated right-click paste (ctrl+V + Shift+scroll cover the gap). Resolves the capture-vs-native-scroll xor PER-HARNESS via the manifest instead of globally. | v0.13.0 P1b (operator ruling 2026-06-20, HITL: scroll-forward to CC is moot — CC has nothing to scroll; Shift+scroll is "good enough for now") | Shift+scroll is a clean, working interim for the CC case (no internal-scroll harness) so there's no live gap; the manifest flag is a real design slice (a new `[rc]`/mouse manifest field + validation + the rc capture-decision branch + an adapter declaring it to test the consume-path) that earns its own JIT plan, not a v0.13.0 closeout rider | **Post-v0.13.0** — when building the next adapter-manifest surface, or the first harness that genuinely consumes mouse reports (internal-scroll TUI). Mint a `REQ-RC-VT-MODE`-class requirement first (rule 3), then the manifest field + rc capture-decision branch + an int adapter that declares it |


Docs aligned to the shipped design. Let me check the attach suite's interim progress:


<system-reminder>Warning: the file exists but is shorter than the provided offset (1). The file has 1 lines.</system-reminder>


Only buffered output so far — waiting for the attach suite to finish (heavy cross-daemon tests, serial, on Windows). Won't contend with cargo meanwhile.

**Status recap for doyle's 4 gate demands:**
- **#4 sweep:** brain_swap ✓ (canary), handoff ✓, idempotent ✓, broker 8/8 ✓ (keystone), inject_control_wedge 10/10 ✓. Carrier ✓ alone. Full attach suite re-running (`b9sl2f7k1`).
- **#2 reorder-safety:** reframed as structural — my change doesn't alter *which* frames life2 delivers ([K,end]) or life1 forwards ([0,K)); the proof is **snap-above over ascending writers never skips** (first sighting of seq>M preceded by M; surviving writer offers complete [0,end]).
- **#3 attach-reset:** gated to resume-mode (`!session_cursors.is_empty()`); only explicit `Brain::attach` callers hit it (not per-frame `read_event`); cold-start path untouched.
- **#1 20× carrier:** doyle's kitsubito run.

Docs (KH 7.21, checklist, REQ, DEFERRED) updated to the corrected design. Once attach completes I run the white-box lib unit + clippy + traceable + docs-drift, then surface to doyle with the diff + written proofs. Standing by.


<task-notification>
<task-id>b9sl2f7k1</task-id>
<tool-use-id>toolu_01FHDCX5WEw7YQq36eZg44Di</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\97787e5e-64b2-4afd-b3fe-becaa2ea8030\tasks\b9sl2f7k1.output</output-file>
<status>completed</status>
<summary>Background command "Run full attach suite with per-test visibility, 560s budget" completed (exit code 0)</summary>
</task-notification>


1	test attach_registers_remote_drive_detection ... ok
2	test attach_survives_target_brain_restart_exactly_once ... ok
3	test broker_spawns_the_pty_child_in_the_requested_cwd ... ok
4	test controller_restart_with_viewer_no_displace_and_viewer_survives ... ok
5	test controller_viewer_matrix_and_loud_take ... error: test failed, to rerun pass `-p spt-daemon --test attach`
6	[attach EXIT=124 (124=timeout)]
7

test attach_registers_remote_drive_detection ... ok
test attach_survives_target_brain_restart_exactly_once ... ok
test broker_spawns_the_pty_child_in_the_requested_cwd ... ok
test controller_restart_with_viewer_no_displace_and_viewer_survives ... ok
test controller_viewer_matrix_and_loud_take ... error: test failed, to rerun pass `-p spt-daemon --test attach`
[attach EXIT=124 (124=timeout)]


4 passed incl. the carrier, then **`controller_viewer_matrix_and_loud_take` failed/hung** — and that's a become_controller/displacement test, squarely my epoch-gate territory. Running it alone with output:


Bash

cd C:/Users/decid/Documents/projects/spt-core && timeout 90 cargo test -p spt-daemon --test attach controller_viewer_matrix_and_loud_take -- --exact --nocapture 2>&1 | tail -30; echo "EXIT=${PIPESTATUS[0]} (124=HANG)"

Run controller_viewer_matrix_and_loud_take alone


    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.55s
     Running tests\attach.rs (target\debug\deps\attach-4be0da28eeea8aad.exe)

running 1 test
test controller_viewer_matrix_and_loud_take has been running for over 60 seconds
error: test failed, to rerun pass `-p spt-daemon --test attach`

Caused by:
  process didn't exit successfully: `C:\Users\decid\Documents\projects\spt-core\target\debug\deps\attach-4be0da28eeea8aad.exe controller_viewer_matrix_and_loud_take --exact --nocapture` (exit code: 143)
EXIT=124 (124=HANG)


Silent hang (no panic) — likely my epoch-gate breaking the loud-take/displacement path. Let me read the test:


cd C:/Users/decid/Documents/projects/spt-core && rg -n "fn controller_viewer_matrix_and_loud_take" crates/spt-daemon/tests/attach.rs

Locate the loud-take test


919:fn controller_viewer_matrix_and_loud_take() {