=== broker.rs test tags + fns ===
922:// ── v0.13.0 P1c — REQ-HAZARD-CONTROLLER-WRITER-REORDER ────────────────────────
923-// THE INT KEYSTONE: deterministically drive the two-`become_controller`-on-ONE-
--
1146:// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
1147-#[test]
=== attach.rs test tags + fns ===
1163:// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
1164-// v0.13.0 P1c — the handoff side of the fix (defects A + the defense-in-depth
--
1232:         a fatal `output gap` (REQ-HAZARD-CONTROLLER-WRITER-REORDER fix #3)"
1233-    );


Let me confirm the unit tag location (white-box test should be in-crate `src/broker.rs`):


Bash

cd C:/Users/decid/Documents/projects/spt-core && echo "=== all REORDER tags by stage ===" && rg -n "(unit|int|impl|doc)->REQ-HAZARD-CONTROLLER-WRITER-REORDER" crates/ docs/ && echo "=== src/broker.rs context ===" && rg -n "REQ-HAZARD-CONTROLLER-WRITER-REORDER" crates/spt-daemon/src/broker.rs -A1

Locate unit/int/impl tags across the tree


=== all REORDER tags by stage ===
docs/KNOWN-HAZARDS.md:468:<!-- [doc->REQ-HAZARD-CONTROLLER-WRITER-REORDER] -->
crates/spt-daemon\tests\broker.rs:1146:// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
crates/spt-daemon\tests\attach.rs:1163:// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
crates/spt-daemon\src\brain.rs:333:    // [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
crates/spt-daemon\src\broker.rs:715:// [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
crates/spt-daemon\src\broker.rs:2623:    // [unit->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
=== src/broker.rs context ===
217:    /// writer per connection, [`REQ-HAZARD-CONTROLLER-WRITER-REORDER`]).
218-    controller_epoch: Arc<AtomicU64>,
--
356:    /// [`REQ-HAZARD-CONTROLLER-WRITER-REORDER`]). Stamps `driven_by` to the new
357-    /// controller's identity.
--
715:// [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
716-fn controller_writer(
--
2541:    // ── v0.13.0 P1c — REQ-HAZARD-CONTROLLER-WRITER-REORDER: the epoch-gated
2542-    //    single-live-writer-per-connection kernel. WHITE-BOX unit: build a real
--
2594:    /// EPOCH-GATE KEYSTONE (REQ-HAZARD-CONTROLLER-WRITER-REORDER). Build an
2595-    /// `OutputLog`, append seq 0 + seq 1 into the ring, then call
--
2623:    // [unit->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
2624-    #[test]


All four stages tagged: doc (KH:468), impl (brain:333, broker:715), unit (src/broker.rs:2623 white-box), int (tests/broker.rs:1146, tests/attach.rs:1163). Work product is complete in the tree.

The subagent's wait is stalled (~52 min — far longer than these suites need). I'll run the gates myself. First checking nothing's mid-compile to avoid `target/` contention:


tasklist 2>/dev/null | grep -iE "cargo|rustc|spt-daemon" | head || echo "(no cargo/rustc running)"

Check for in-flight cargo/rustc processes


cargo.exe                    85916 Console                    1     27,708 K
cargo.exe                   169164 Console                    1     26,996 K
cargo.exe                   150640 Console                    1     27,068 K


3 cargo processes running (~52 min) with no active rustc — a possible **hang** (and hang is exactly this bug's failure mode: `render_until` waiting forever). Let me see what they're running:


PowerShell

Get-CimInstance Win32_Process -Filter "Name='cargo.exe'" | Select-Object ProcessId,CreationDate,CommandLine | Format-List; "=== test binaries ==="; Get-CimInstance Win32_Process -Filter "Name like '%spt%' or Name like '%attach%' or Name like '%broker%'" | Select-Object ProcessId,Name,CreationDate | Format-List

Get cargo command lines and creation times


ProcessId    : 85916
CreationDate : 6/20/2026 4:31:40 PM
CommandLine  : "C:\Users\decid\.rustup\toolchains\stable-x86_64-pc-windows-msvc\bin\cargo.exe" test -p spt-daemon --test
               inject_control_wedge

ProcessId    : 169164
CreationDate : 6/20/2026 4:31:49 PM
CommandLine  : "C:\Users\decid\.rustup\toolchains\stable-x86_64-pc-windows-msvc\bin\cargo.exe" test -p spt-daemon --test attach
               -- --test-threads=1

ProcessId    : 150640
CreationDate : 6/20/2026 4:31:58 PM
CommandLine  : "C:\Users\decid\.rustup\toolchains\stable-x86_64-pc-windows-msvc\bin\cargo.exe" test -p spt-daemon --test
               brain_swap -- --test-threads=1

=== test binaries ===

ProcessId    : 5552
Name         : logioptionsplus_appbroker.exe
CreationDate : 6/10/2026 2:20:44 PM

ProcessId    : 16508
Name         : RuntimeBroker.exe
CreationDate : 6/10/2026 2:20:44 PM

ProcessId    : 18492
Name         : RuntimeBroker.exe
CreationDate : 6/10/2026 2:20:47 PM

ProcessId    : 52644
Name         : UserOOBEBroker.exe
CreationDate : 6/13/2026 7:38:01 PM

ProcessId    : 237828
Name         : RuntimeBroker.exe
CreationDate : 6/13/2026 9:29:35 PM

ProcessId    : 36948
Name         : RuntimeBroker.exe
CreationDate : 6/13/2026 9:32:34 PM

ProcessId    : 111500
Name         : RuntimeBroker.exe
CreationDate : 6/14/2026 12:03:28 AM

ProcessId    : 110580
Name         : RuntimeBroker.exe
CreationDate : 6/14/2026 12:06:59 AM

ProcessId    : 179068
Name         : spt.exe
CreationDate : 6/20/2026 3:33:46 AM

ProcessId    : 163632
Name         : spt.exe
CreationDate : 6/20/2026 3:33:46 AM

ProcessId    : 147992
Name         : claude-spt-psyche.exe
CreationDate : 6/20/2026 3:51:21 AM

ProcessId    : 20804
Name         : spt.exe
CreationDate : 6/20/2026 4:56:50 AM

ProcessId    : 73488
Name         : spt.exe
CreationDate : 6/20/2026 4:56:50 AM

ProcessId    : 29368
Name         : attach-4be0da28eeea8aad.exe
CreationDate : 6/20/2026 4:31:53 PM

ProcessId    : 240464
Name         : spt.exe
CreationDate : 6/20/2026 4:40:53 PM


check your ongoing Monitor tool call's output


Found it: `attach-4be0da28eeea8aad.exe` (PID 29368) running since **4:31:53 PM** — ~50 min. That's a **hang** (these suites finish in seconds–minutes; hang is this bug's failure mode). The subagent's `until` loops never see completion → it waits forever. The 3 cargo runs (attach, inject_control_wedge, brain_swap) are wedged on it.

I'm taking over. Killing **only** the test processes from 4:31 PM (sparing my live daemon/psyche from this morning):


# Kill ONLY the test processes started at 4:31PM+ (cargo test runs + the hung attach test binary). Spare AM-dated daemon/psyche.
$pids = 85916,169164,150640,29368
foreach ($p in $pids) { try { Stop-Process -Id $p -Force -ErrorAction Stop; "killed $p" } catch { "already gone: $p" } }
"=== test-spawned spt.exe (4:31PM+) ==="
Get-CimInstance Win32_Process -Filter "Name='spt.exe'" | Where-Object { $_.CreationDate -gt (Get-Date '2026-06-20 16:31:00') } | ForEach-Object { "spt PID $($_.ProcessId) @ $($_.CreationDate)"; try { Stop-Process -Id $_.ProcessId -Force -ErrorAction Stop; "  killed" } catch { "  gone" } }
"=== remaining cargo/rustc ==="
Get-CimInstance Win32_Process -Filter "Name='cargo.exe' or Name='rustc.exe'" | Select-Object ProcessId,Name | Format-Table -Auto

Kill hung test processes, spare live daemon


killed 85916
killed 169164
killed 150640
killed 29368
=== test-spawned spt.exe (4:31PM+) ===
spt PID 95996 @ 06/20/2026 16:41:32
  killed
=== remaining cargo/rustc ===

ProcessId Name
--------- ----
   227084 cargo.exe
   177688 cargo.exe
   135976 cargo.exe


<task-notification>
<task-id>bkmaglndp</task-id>
<tool-use-id>toolu_01GCtQeVT4WBUXu9mfFxNSfU</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\bkmaglndp.output</output-file>
<status>completed</status>
<summary>Background command "Single-threaded attach + broker" completed (exit code 0)</summary>
</task-notification>


<task-notification>
<task-id>b1ywu1y9v</task-id>
<summary>Monitor event: "single-threaded attach+broker results"</summary>
<event>=== ATTACH (st) ===
test attach_survives_target_brain_restart_exactly_once ... ATTACH_EXIT=127
=== BROKER (st) ===
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.49s
BROKER_EXIT=0</event>
</task-notification>


<task-notification>
<task-id>b1ywu1y9v</task-id>
<tool-use-id>toolu_013GszYuE5DzHQmAP6fFmnyH</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\b1ywu1y9v.output</output-file>
<status>completed</status>
<summary>Monitor "single-threaded attach+broker results" stream ended</summary>
</task-notification>


<task-notification>
<task-id>ae3c1f56da67aea47</task-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\97787e5e-64b2-4afd-b3fe-becaa2ea8030\tasks\ae3c1f56da67aea47.output</output-file>
<status>killed</status>
<summary>Agent "Write P1c controller-writer reorder tests" came to rest (stopped by user)</summary>
<note>A task-notification fires each time this agent comes to rest with no live background children of its own. The user can send it another message and resume it, so the same task-id may notify more than once.</note>
</task-notification>


More cargo respawned — the subagent (or its loops) is relaunching. I must stop the subagent first. Halting it:


<owl_messages>
<owl_message from="todlando-w187" priority="info">[WORKING_PERCH_NOTICE] Subagent working perch created.
Perch: todlando-w187
Agent type: spt-test-engineer
To message it: $OWL send todlando-w187 todlando</owl_message>
</owl_messages>

[OWL SYSTEM] Informational owl messages above — no acknowledgment needed. Continue your current task.


Successfully stopped task: ae3c1f56da67aea47 (Write P1c controller-writer reorder tests)


Subagent stopped. Now kill residual cargo + any orphan test binaries, then run the attach suite myself with a hard timeout to pinpoint the hang:


Get-CimInstance Win32_Process | Where-Object { $_.Name -in 'cargo.exe','rustc.exe' -or ($_.Name -match 'attach-|broker-|brain_swap-|inject_control' -and $_.Name -match '\.exe$') } | ForEach-Object { "kill $($_.Name) $($_.ProcessId)"; try { Stop-Process -Id $_.ProcessId -Force -ErrorAction Stop } catch {} }
Start-Sleep -Milliseconds 500
"=== remaining test/cargo procs ==="
Get-CimInstance Win32_Process | Where-Object { $_.Name -in 'cargo.exe','rustc.exe' -or $_.Name -match 'attach-[0-9a-f]+\.exe' } | Select-Object ProcessId,Name | Format-Table -Auto
"done"

Clean residual cargo and test binaries


=== remaining test/cargo procs ===
done


Prompt:
<task-notification>
<task-id>ae3c1f56da67aea47</task-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\97787e5e-64b2-4afd-b3fe-becaa2ea8030\tasks\ae3c1f56da67aea47.output</output-file>
<status>killed</status>
<summary>Agent "Write P1c controller-writer reorder tests" came to rest (stopped by user)</summary>
<note>A task-notification fires each time this agent comes to rest with no live background children of its own. The user can send it another message and resume it, so the same task-id may notify more than once.</note>
</task-notification>


Clean. The hang is in the **attach** test crate. Let me build + list its tests (fast), then bisect with a timeout to pinpoint the hanger:


Bash

cd C:/Users/decid/Documents/projects/spt-core && timeout 300 cargo test -p spt-daemon --test attach -- --list 2>&1 | grep -iE "controller|reorder|restart|become|: test" | head -40; echo "EXIT=${PIPESTATUS[0]}"

Build and list attach test names


attach_registers_remote_drive_detection: test
attach_survives_target_brain_restart_exactly_once: test
broker_spawns_the_pty_child_in_the_requested_cwd: test
controller_restart_with_viewer_no_displace_and_viewer_survives: test
controller_viewer_matrix_and_loud_take: test
handoff_seeds_resume_cursor_and_issues_no_eager_subscribe: test
local_attach_via_loopback_conn_rides_the_same_pump: test
loopback_attach_to_a_prepopulated_ring_delivers_without_deadlock: test
loopback_self_dial_is_refused_local_uses_fallback_transport: test
remote_attach_drives_a_real_pty_cross_daemon: test
resize_is_controller_exclusive: test
same_origin_re_subscribe_does_not_displace: test
spt_hosted_bringup_then_cross_node_attach_drives_the_pty: test
wedged_viewer_does_not_stall_controller: test
EXIT=0


Build OK. New int test = `handoff_seeds_resume_cursor_and_issues_no_eager_subscribe`. Running the suspects individually with timeouts:


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

Run new int keystone with timeout


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

running 1 test
test handoff_seeds_resume_cursor_and_issues_no_eager_subscribe ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 13 filtered out; finished in 0.03s

EXIT=0 (124=timeout/HANG)


New keystone passes (0.03s). Now the carrier:


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

Run restart carrier test with timeout


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

running 1 test
test attach_survives_target_brain_restart_exactly_once has been running for over 60 seconds

thread 'attach_survives_target_brain_restart_exactly_once' (99156) panicked at crates\spt-daemon\tests\attach.rs:757:10:
local replay: Custom { kind: UnexpectedEof, error: "session exited before the expected output arrived" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test attach_survives_target_brain_restart_exactly_once ... FAILED

failures:

failures:
    attach_survives_target_brain_restart_exactly_once

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 13 filtered out; finished in 119.43s

error: test failed, to rerun pass `-p spt-daemon --test attach`
EXIT=124 (124=timeout/HANG)


Carrier **fails post-fix** — but at **attach.rs:757** (the local-replay ground-truth check: "session exited before the expected output arrived"), **not** the reorder spots (722/729). Different symptom. I need to know if my fix caused this or it's pre-existing. First, read the failing region:


740	    let (outcome, mut life2) = server.join().expect("serve thread");
741	    assert_eq!(outcome, AttachServeOutcome::Detached);
742
743	    // Exactly-once, stated against ground truth: replay the session's OWN
744	    // output log locally from seq 0 with the same stop rule — the remote
745	    // viewport must be BYTE-IDENTICAL through the first dead-window marker
746	    // (an echoing child legitimately repeats a typed marker; what must never
747	    // differ is wire vs local). A dup or gap from the restart/replay would
748	    // break the prefix equality. Compared as prefixes-through-the-needle
749	    // because each side's *overshoot* past the marker is honest chunking
750	    // nondeterminism: both stop rules check "buffer contains needle" only
751	    // between event batches, and how many trailing records one batch carries
752	    // differs between the QUIC wire and the local IPC frames.
753	    life2.attach(sid, 0).expect("local ground-truth attach");
754	    let mut local: Vec<u8> = Vec::new();
755	    life2
756	        .read_output_until(b"MARKER_TWO", &mut local)
757	        .expect("local replay");
758	    assert_eq!(
759	        prefix_through(&viewport, b"MARKER_TWO"),
760	        prefix_through(&local, b"MARKER_TWO"),
761	        "remote viewport byte-identical to the local output log across the restart"
762	    );
763	    assert!(count(&local, b"MARKER_ONE") >= 1 && count(&local, b"MARKER_TWO") >= 1);
764
765	    life2.kill_session().expect("cleanup kill");
766	}
767
768	// [unit->REQ-REACH-1] remote-drive detection is a daemon fact: serving a
769	// net-attach stamps the endpoint perch's `driven_by` with the
770	// handshake-proven origin node (what the agent's `spt api driven-by` query
771	// reads), and the marker clears when the viewport ends — the endpoint reads
772	// locally driven again.
773	#[test]
774	fn attach_registers_remote_drive_detection() {
775	    init_home();
776	    let dir = tempfile::tempdir().expect("tempdir");
777	    let (name_a, name_b) = (unique_name(), unique_name());
778	    let _broker_a = net_broker(&name_a, &dir.path().join("a"));
779	    let _broker_b = net_broker(&name_b, &dir.path().join("b"));
780
781	    // The driven endpoint has a real perch on A (unique id: the shared test
782	    // home outlives this test).
783	    let endpoint = format!(
784	        "ling-d5c-{}-{}",
785	        std::process::id(),
786	        SEQ.fetch_add(1, Ordering::Relaxed)
787	    );
788	    let perch_path =
789	        spt_store::perch::resolve_perch_path(&endpoint, spt_store::perch::ParentHint::Infer);
790	    std::fs::create_dir_all(&perch_path).expect("perch dir");
791	    let rec =
792	        spt_store::info::InfoJson::new(&endpoint, "now", std::process::id(), "sess", "live_agent");
793	    spt_store::info::write_info(&perch_path, &rec).expect("info.json");
794
795	    let mut target = connect_retry(&name_a);
796	    // Spawn the session LABELED with this endpoint: driven_by is now broker-owned
797	    // (single writer, REQ-RCVIEW-1) and keyed on the session's endpoint label —
798	    // which in production equals the serve gate's endpoint (both resolved from
799	    // the spawn). So the labeled spawn is the faithful shape.

    let (outcome, mut life2) = server.join().expect("serve thread");
    assert_eq!(outcome, AttachServeOutcome::Detached);

    // Exactly-once, stated against ground truth: replay the session's OWN
    // output log locally from seq 0 with the same stop rule — the remote
    // viewport must be BYTE-IDENTICAL through the first dead-window marker
    // (an echoing child legitimately repeats a typed marker; what must never
    // differ is wire vs local). A dup or gap from the restart/replay would
    // break the prefix equality. Compared as prefixes-through-the-needle
    // because each side's *overshoot* past the marker is honest chunking
    // nondeterminism: both stop rules check "buffer contains needle" only
    // between event batches, and how many trailing records one batch carries
    // differs between the QUIC wire and the local IPC frames.
    life2.attach(sid, 0).expect("local ground-truth attach");
    let mut local: Vec<u8> = Vec::new();
    life2
        .read_output_until(b"MARKER_TWO", &mut local)
        .expect("local replay");
    assert_eq!(
        prefix_through(&viewport, b"MARKER_TWO"),
        prefix_through(&local, b"MARKER_TWO"),
        "remote viewport byte-identical to the local output log across the restart"
    );
    assert!(count(&local, b"MARKER_ONE") >= 1 && count(&local, b"MARKER_TWO") >= 1);

    life2.kill_session().expect("cleanup kill");
}

// [unit->REQ-REACH-1] remote-drive detection is a daemon fact: serving a
// net-attach stamps the endpoint perch's `driven_by` with the
// handshake-proven origin node (what the agent's `spt api driven-by` query
// reads), and the marker clears when the viewport ends — the endpoint reads
// locally driven again.
#[test]
fn attach_registers_remote_drive_detection() {
    init_home();
    let dir = tempfile::tempdir().expect("tempdir");
    let (name_a, name_b) = (unique_name(), unique_name());
    let _broker_a = net_broker(&name_a, &dir.path().join("a"));
    let _broker_b = net_broker(&name_b, &dir.path().join("b"));

    // The driven endpoint has a real perch on A (unique id: the shared test
    // home outlives this test).
    let endpoint = format!(
        "ling-d5c-{}-{}",
        std::process::id(),
        SEQ.fetch_add(1, Ordering::Relaxed)
    );
    let perch_path =
        spt_store::perch::resolve_perch_path(&endpoint, spt_store::perch::ParentHint::Infer);
    std::fs::create_dir_all(&perch_path).expect("perch dir");
    let rec =
        spt_store::info::InfoJson::new(&endpoint, "now", std::process::id(), "sess", "live_agent");
    spt_store::info::write_info(&perch_path, &rec).expect("info.json");

    let mut target = connect_retry(&name_a);
    // Spawn the session LABELED with this endpoint: driven_by is now broker-owned
    // (single writer, REQ-RCVIEW-1) and keyed on the session's endpoint label —
    // which in production equals the serve gate's endpoint (both resolved from
    // the spawn). So the labeled spawn is the faithful shape.


Line 753-757 is the tell: after the re-serve, the test does a **second** `life2.attach(sid, 0)` for a from-0 ground-truth replay. My **fix #3** seeded `session_cursors[sid]` at the handoff cursor — so this from-0 replay now dedup-drops the pre-cursor history (incl. MARKER_ONE) instead of replaying it. That's a likely regression from fix #3. Let me confirm: check `Brain::attach` (does it reset the cursor?) and whether the subagent adjusted this region.


cd C:/Users/decid/Documents/projects/spt-core && echo "=== Brain::attach def ===" && rg -n "fn attach\b" crates/spt-daemon/src/brain.rs && echo "=== git diff attach.rs carrier region (700-766) ===" && git diff -U2 crates/spt-daemon/tests/attach.rs | sed -n '1,80p'

Inspect Brain::attach and subagent's diff to the carrier


=== Brain::attach def ===
793:    pub fn attach(&mut self, session_id: u64, from_seq: u64) -> io::Result<()> {
=== git diff attach.rs carrier region (700-766) ===
diff --git a/crates/spt-daemon/tests/attach.rs b/crates/spt-daemon/tests/attach.rs
index acdf313..f84f9e1 100644
--- a/crates/spt-daemon/tests/attach.rs
+++ b/crates/spt-daemon/tests/attach.rs
@@ -26,5 +26,5 @@ use std::time::Duration;

 use spt_daemon::attach::{request_attach, send_attach_input, serve_attach, AttachServeOutcome};
-use spt_daemon::brain::{Brain, BrokerEvent};
+use spt_daemon::brain::{Brain, BrainState, BrokerEvent};
 use spt_daemon::msg::{decode_bytes, SpawnReq};
 use spt_daemon::nethost::{NetConfig, NetHost};
@@ -1160,2 +1160,103 @@ fn controller_restart_with_viewer_no_displace_and_viewer_survives() {
     );
 }
+
+// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
+// v0.13.0 P1c — the handoff side of the fix (defects A + the defense-in-depth
+// seed). `Brain::handoff` must (1) NOT eagerly subscribe-as-controller (so the
+// re-serve's `attach_as(sid,0)` is the SOLE controller registration on this
+// connection — no stale `from_seq=prior.next_seq` registration that would spawn a
+// second writer to race the re-serve's writer; fix #1), and (2) seed
+// `session_cursors` at `prior.next_seq` so the consumer runs the production
+// dedup-below + snap-above path (resume mode), never the strict reject-gap legacy
+// path that turns any at-least-once boundary reorder into a fatal `output gap`
+// (fix #3).
+//
+// We assert this against a REAL bound broker + a REAL session (so `handoff`
+// connects + handshakes for real). The behavioral end-to-end proof that the
+// no-eager-subscribe change actually eliminates the two-writer race lives in the
+// broker int keystone (`controller_writer_reorder_*`) and the restart carrier
+// (`attach_survives_target_brain_restart_exactly_once`); HERE we lock the two
+// load-bearing post-conditions of `handoff` itself, deterministically.
+#[test]
+fn handoff_seeds_resume_cursor_and_issues_no_eager_subscribe() {
+    init_home();
+    let dir = tempfile::tempdir().expect("tempdir");
+    let name = unique_name();
+    // A non-net broker is sufficient — handoff is pure brain-IPC (connect +
+    // handshake + local cursor rehydrate); no QUIC needed.
+    let broker = Broker::bind_in(&name, dir.path().join("effects.log")).expect("bind broker");
+    let serve = Arc::clone(&broker);
+    thread::spawn(move || {
+        let _ = serve.serve();
+    });
+
+    // A driver brain spawns the session and reads exactly ONE output chunk, so its
+    // consumption cursor (`next_seq`) sits at 1 while the broker's ring holds more
+    // — the worst-case stale floor the bug hinged on (`prior.next_seq` is the
+    // CONSUMPTION cursor, not the successor connection's delivered state).
+    let mut driver = connect_retry(&name);
+    let sid = driver.spawn_session(echo_spawn_req()).expect("spawn echo");
+    driver.send_effect(1, b"SEED_ONE\r").expect("seed input");
+    // Read one Output event to advance the driver's next_seq to 1.
+    loop {
+        match driver.read_event().expect("driver event") {
+            BrokerEvent::Output { .. } => break,
+            BrokerEvent::Error { message } => panic!("driver broker error: {message}"),
+            _ => {}
+        }
+    }
+    let state: BrainState = driver.snapshot();
+    let prior_next_seq = state.next_seq;
+    let prior_generation = state.generation;
+    assert!(
+        prior_next_seq >= 1,
+        "driver must have consumed at least seq 0 so the resume cursor is non-trivial \
+         (got next_seq={prior_next_seq})"
+    );
+    drop(driver); // the "crash" — broker, session, output log all survive
+
+    // THE HANDOFF. Post-fix this connects + handshakes + rehydrates local state but
+    // sends NO subscribe frame; the successor's controller registration only
+    // happens later via an explicit `attach_as`/`attach` (not exercised here — we
+    // assert handoff's own post-conditions).
+    let succ = Brain::handoff(&name, state, 2).expect("handoff");
+
+    // (fix #3) The resume cursor for this session is seeded at exactly the prior
+    // consumption point — so `read_event` routes it through the dedup-below +
+    // snap-above path (resume mode), never the reject-gap legacy trap.
+    assert_eq!(


Confirmed mechanism: the subagent added its own passing int test but didn't reconcile the **carrier's** from-0 ground-truth re-attach (line 753) with fix #3. After `serve_attach`, life2's seeded `session_cursors[sid]` has advanced past MARKER_TWO; the second `attach(sid, 0)` then dedup-drops the entire replay → MARKER_TWO never arrives → stall→fail.

The correct fix: an **explicit** `attach`/`attach_as(sid, from_seq)` in resume mode must reset that session's cursor to `from_seq` (honor the requested floor) — matching how `resume_sessions` seeds per-subscribe. Reading the attach paths to place it:


781	                }
782	                _ => return Ok(BrokerEvent::Other(env)),
783	            }
784	        }
785	    }
786
787	    /// Attach this (freshly-connected) brain to an **existing** broker session's
788	    /// output from `from_seq`, e.g. a dedicated digest-feed subscriber that did
789	    /// not spawn the session itself. Sets the resume cursor + session, then
790	    /// subscribes (the broker replays from `from_seq`, then streams live). Unlike
791	    /// [`Brain::handoff`] this does not touch the generation — it is a *second*
792	    /// reader of a session another brain drives, not a logic handoff.
793	    pub fn attach(&mut self, session_id: u64, from_seq: u64) -> io::Result<()> {
794	        self.session_id = Some(session_id);
795	        self.next_seq = from_seq;
796	        // A resume-mode brain (non-empty map) routes this session's output through
797	        // the per-session map via `read_event`'s first-sight `or_insert` seed
798	        // (D4-2b); a legacy brain (empty map) uses the `next_seq` set above.
799	        self.subscribe(session_id, from_seq)
800	    }
801
802	    /// Attach under the W2.5 controller/viewer model (REQ-RCVIEW-1): send a
803	    /// role-aware subscribe with `intent` + the operator identity `by` (the
804	    /// handshake-proven origin for a remote attach). The broker resolves the role
805	    /// and replies a [`BrokerEvent::Subscribed`] the caller (a [`serve_attach`]
806	    /// loop) reads to learn whether it became controller / viewer / was refused.

                }
                _ => return Ok(BrokerEvent::Other(env)),
            }
        }
    }

    /// Attach this (freshly-connected) brain to an **existing** broker session's
    /// output from `from_seq`, e.g. a dedicated digest-feed subscriber that did
    /// not spawn the session itself. Sets the resume cursor + session, then
    /// subscribes (the broker replays from `from_seq`, then streams live). Unlike
    /// [`Brain::handoff`] this does not touch the generation — it is a *second*
    /// reader of a session another brain drives, not a logic handoff.
    pub fn attach(&mut self, session_id: u64, from_seq: u64) -> io::Result<()> {
        self.session_id = Some(session_id);
        self.next_seq = from_seq;
        // A resume-mode brain (non-empty map) routes this session's output through
        // the per-session map via `read_event`'s first-sight `or_insert` seed
        // (D4-2b); a legacy brain (empty map) uses the `next_seq` set above.
        self.subscribe(session_id, from_seq)
    }

    /// Attach under the W2.5 controller/viewer model (REQ-RCVIEW-1): send a
    /// role-aware subscribe with `intent` + the operator identity `by` (the
    /// handshake-proven origin for a remote attach). The broker resolves the role
    /// and replies a [`BrokerEvent::Subscribed`] the caller (a [`serve_attach`]
    /// loop) reads to learn whether it became controller / viewer / was refused.


Confirmed root cause: my **fix #3** seeded life2's `session_cursors`, routing it into resume-mode (map) reads. The carrier's deliberate from-0 ground-truth re-read at line 753 uses `attach(sid, 0)`, but `read_event`'s `or_insert` only seeds a *first-sight* session — the already-advanced cursor then dedup-drops the entire replay. Pre-fix this worked via the legacy `next_seq` path.

Correct, minimal fix in **production** code: an explicit `attach(sid, from_seq)` in resume mode must reset that session's dedup cursor to the requested floor (the re-serve's `attach_as` keeps the seeded cursor — fix #3 stays intact there):


Edit

    pub fn attach(&mut self, session_id: u64, from_seq: u64) -> io::Result<()> {
        self.session_id = Some(session_id);
        self.next_seq = from_seq;
        // A resume-mode brain (non-empty map) routes this session's output through
        // the per-session map via `read_event`'s first-sight `or_insert` seed
        // (D4-2b); a legacy brain (empty map) uses the `next_seq` set above.
        self.subscribe(session_id, from_seq)
    }

    pub fn attach(&mut self, session_id: u64, from_seq: u64) -> io::Result<()> {
        self.session_id = Some(session_id);
        self.next_seq = from_seq;
        // A resume-mode brain (non-empty map) routes this session's output through
        // the per-session map via `read_event`'s first-sight `or_insert` seed
        // (D4-2b); a legacy brain (empty map) uses the `next_seq` set above.
        //
        // P1c: `or_insert` only seeds a FIRST-sight session. An EXPLICIT re-attach
        // of an already-tracked session (e.g. a from-0 ground-truth re-read after
        // a resume, or any deliberate re-subscribe from a different floor) must
        // RESET this session's dedup cursor to `from_seq` — otherwise a prior
        // seed/advance dedup-drops the very replay the caller asked for. Only in
        // resume mode (the seeded map); a legacy brain keeps the `next_seq` path.
        // [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
        if !self.session_cursors.is_empty() {
            self.session_cursors.insert(session_id, from_seq);
        }
        self.subscribe(session_id, from_seq)
    }


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

    pub fn attach(&mut self, session_id: u64, from_seq: u64) -> io::Result<()> {
        self.session_id = Some(session_id);
        self.next_seq = from_seq;
        // A resume-mode brain (non-empty map) routes this session's output through
        // the per-session map via `read_event`'s first-sight `or_insert` seed
        // (D4-2b); a legacy brain (empty map) uses the `next_seq` set above.
        self.subscribe(session_id, from_seq)
    }

    pub fn attach(&mut self, session_id: u64, from_seq: u64) -> io::Result<()> {
        self.session_id = Some(session_id);
        self.next_seq = from_seq;
        // A resume-mode brain (non-empty map) routes this session's output through
        // the per-session map via `read_event`'s first-sight `or_insert` seed
        // (D4-2b); a legacy brain (empty map) uses the `next_seq` set above.
        //
        // P1c: `or_insert` only seeds a FIRST-sight session. An EXPLICIT re-attach
        // of an already-tracked session (e.g. a from-0 ground-truth re-read after
        // a resume, or any deliberate re-subscribe from a different floor) must
        // RESET this session's dedup cursor to `from_seq` — otherwise a prior
        // seed/advance dedup-drops the very replay the caller asked for. Only in
        // resume mode (the seeded map); a legacy brain keeps the `next_seq` path.
        // [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
        if !self.session_cursors.is_empty() {
            self.session_cursors.insert(session_id, from_seq);
        }
        self.subscribe(session_id, from_seq)
    }

+        // P1c: `or_insert` only seeds a FIRST-sight session. An EXPLICIT re-attach

+        // of an already-tracked session (e.g. a from-0 ground-truth re-read after

+        // a resume, or any deliberate re-subscribe from a different floor) must

+        // RESET this session's dedup cursor to `from_seq` — otherwise a prior

+        // seed/advance dedup-drops the very replay the caller asked for. Only in

+        // resume mode (the seeded map); a legacy brain keeps the `next_seq` path.

+        // [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]

+        if !self.session_cursors.is_empty() {

+            self.session_cursors.insert(session_id, from_seq);


Now run the carrier with a timeout to confirm it's green:


Bash

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

Re-run carrier after the attach cursor-reset fix


   Compiling spt-daemon v0.12.1 (C:\Users\decid\Documents\projects\spt-core\crates\spt-daemon)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 5.34s
     Running tests\attach.rs (target\debug\deps\attach-4be0da28eeea8aad.exe)

running 1 test
test attach_survives_target_brain_restart_exactly_once ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 13 filtered out; finished in 0.17s

EXIT=0 (124=HANG)


Carrier green (0.17s) — the cursor-reset fix is correct. Now the full seam sweep + the white-box unit, each timeout-guarded so a hang can't eat the run:


cd C:/Users/decid/Documents/projects/spt-core
for suite in attach broker brain_swap inject_control_wedge; do
  echo "=================== $suite ==================="
  timeout 300 cargo test -p spt-daemon --test $suite -- --test-threads=1 2>&1 | tail -4
  echo "[$suite EXIT=${PIPESTATUS[0]} (124=HANG)]"
done

Run attach/broker/brain_swap/inject_control_wedge suites


Command running in background with ID: b0ctfq4bb. 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\b0ctfq4bb.output. You will be notified when it completes. To check interim output, use Read on that file path.


Backgrounded (4 suites sequential, ~minutes). Will notify on completion.

**Critical catch:** the carrier was failing post-fix — not a flake. My **fix #3** (seeding `session_cursors` on handoff) regressed the carrier's from-0 ground-truth re-read: `read_event`'s `or_insert` only seeds first-sight, so the already-advanced cursor dedup-dropped the whole replay → stall→fail. The subagent's `until`-loops never saw completion → the 50-min "hang" + its stall. Stopped the subagent, killed the wedged test procs.

**Fix:** explicit `attach(sid, from_seq)` in resume mode now resets that session's dedup cursor to the requested floor (production-correct; the re-serve's `attach_as` keeps the seeded cursor, so fix #3 stays intact). Carrier now passes in 0.17s.

Now verifying no collateral: attach/broker/brain_swap/inject_control_wedge running (`b0ctfq4bb`). Then lib unit (white-box keystone), resume/netbroker, clippy, traceable, docs-drift. Will surface to doyle only once the **whole** sweep is green. Reachable.


<task-notification>
<task-id>b0ctfq4bb</task-id>
<tool-use-id>toolu_01F4KyftqdY5YnS2bAAPyacd</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\b0ctfq4bb.output</output-file>
<status>completed</status>
<summary>Background command "Run attach/broker/brain_swap/inject_control_wedge suites" completed (exit code 0)</summary>
</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.


1	=================== attach ===================
2
3	Caused by:
4	  process didn't exit successfully: `C:\Users\decid\Documents\projects\spt-core\target\debug\deps\attach-4be0da28eeea8aad.exe --test-threads=1` (exit code: 143)
5	note: test exited abnormally; to see the full output pass --no-capture to the harness.
6	[attach EXIT=124 (124=HANG)]
7	=================== broker ===================
8	test wall_b_endpoint_run_env_then_send_reaches_pty ... ok
9
10	test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.47s
11
12	[broker EXIT=0 (124=HANG)]
13	=================== brain_swap ===================
14
15	Caused by:
16	  process didn't exit successfully: `C:\Users\decid\Documents\projects\spt-core\target\debug\deps\brain_swap-0109f0583b5f4568.exe --test-threads=1` (exit code: 143)
17	note: test exited abnormally; to see the full output pass --no-capture to the harness.
18	[brain_swap EXIT=124 (124=HANG)]
19	=================== inject_control_wedge ===================
20
21	Caused by:
22	  process didn't exit successfully: `C:\Users\decid\Documents\projects\spt-core\target\debug\deps\inject_control_wedge-728b905f7a39c795.exe --test-threads=1` (exit code: 143)
23	note: test exited abnormally; to see the full output pass --no-capture to the harness.
24	[inject_control_wedge EXIT=124 (124=HANG)]
25

=================== attach ===================

Caused by:
  process didn't exit successfully: `C:\Users\decid\Documents\projects\spt-core\target\debug\deps\attach-4be0da28eeea8aad.exe --test-threads=1` (exit code: 143)
note: test exited abnormally; to see the full output pass --no-capture to the harness.
[attach EXIT=124 (124=HANG)]
=================== broker ===================
test wall_b_endpoint_run_env_then_send_reaches_pty ... ok

test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.47s

[broker EXIT=0 (124=HANG)]
=================== brain_swap ===================

Caused by:
  process didn't exit successfully: `C:\Users\decid\Documents\projects\spt-core\target\debug\deps\brain_swap-0109f0583b5f4568.exe --test-threads=1` (exit code: 143)
note: test exited abnormally; to see the full output pass --no-capture to the harness.
[brain_swap EXIT=124 (124=HANG)]
=================== inject_control_wedge ===================

Caused by:
  process didn't exit successfully: `C:\Users\decid\Documents\projects\spt-core\target\debug\deps\inject_control_wedge-728b905f7a39c795.exe --test-threads=1` (exit code: 143)
note: test exited abnormally; to see the full output pass --no-capture to the harness.
[inject_control_wedge EXIT=124 (124=HANG)]


Mixed: **broker 8/8 green** (incl. the int keystone), but attach/brain_swap/inject_control_wedge **timed out** (143=SIGTERM from timeout). Yet the carrier passed *alone* in 0.17s. That points to either another test hanging or — more likely — **orphaned test brokers/sockets** from the subagent's 52-min thrash colliding with new runs (the known socket-bind flake class). Checking for orphans:


PowerShell

"=== test-era processes (4:25PM+ today) — potential orphans ==="
Get-CimInstance Win32_Process | Where-Object { $_.Name -match 'spt|attach-|broker-|brain_swap-|inject_|daemon' -and $_.Name -match '\.exe$' -and $_.CreationDate -gt (Get-Date '2026-06-20 16:25:00') } | Select-Object ProcessId,Name,CreationDate | Sort-Object CreationDate | Format-Table -Auto
"=== my LIVE daemon/psyche (AM — MUST KEEP) ==="
Get-CimInstance Win32_Process | Where-Object { $_.Name -match 'spt|psyche' -and $_.Name -match '\.exe$' -and $_.CreationDate -lt (Get-Date '2026-06-20 16:25:00') } | Select-Object ProcessId,Name,CreationDate | Sort-Object CreationDate | Format-Table -Auto

List test-era orphans vs live daemon


=== test-era processes (4:25PM+ today) — potential orphans ===

ProcessId Name                  CreationDate
--------- ----                  ------------
   244648 claude-spt-psyche.exe 6/20/2026 4:41:41 PM
   207768 spt.exe               6/20/2026 5:03:51 PM

=== my LIVE daemon/psyche (AM — MUST KEEP) ===

ProcessId Name    CreationDate
--------- ----    ------------
   179068 spt.exe 6/20/2026 3:33:46 AM
   163632 spt.exe 6/20/2026 3:33:46 AM
    20804 spt.exe 6/20/2026 4:56:50 AM
    73488 spt.exe 6/20/2026 4:56:50 AM


Test binaries are gone (no socket-holding orphans) — so these suites genuinely stall on a specific test. The carrier passed alone, so it's *other* tests. `brain_swap` hanging is the key signal (it exercises handoff — my fix #1/#3 territory; not in doyle's known-flaky list). Let me bisect it test-by-test:


Bash

cd C:/Users/decid/Documents/projects/spt-core && timeout 120 cargo test -p spt-daemon --test brain_swap -- --list 2>&1 | grep ": test$"

List brain_swap test names


brain_only_update_swaps_logic_with_zero_endpoint_interruption: test


Single test: `brain_only_update_swaps_logic_with_zero_endpoint_interruption` — squarely the handoff path. Running with `--nocapture` to see where it stalls:


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

Run brain_swap test with nocapture


    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.46s
     Running tests\brain_swap.rs (target\debug\deps\brain_swap-0109f0583b5f4568.exe)

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

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


brain_swap hangs silently (no panic — an internal read blocks). It's the handoff path. Reading the test:


1	//! C0 E2E — the M3c keystone: a **brain-only self-update** swaps the brain logic
2	//! through the update engine with **zero hosted-endpoint interruption**
3	//! (REQ-UPD-3, absolute for the brain-only class — ADR-0004 §A).
4	//!
5	//! This rides the same broker/brain substrate the B2 handoff test proves, but
6	//! drives the swap through the *update engine* (`plan_update` → `apply_brain_only`)
7	//! rather than calling `Brain::handoff` directly — the engine *triggers* a
8	//! handoff, it does not re-implement one (`M3c-PLAN.md` §C0, clean-room posture).
9	//!
10	//! Shape: one echo child runs under a broker PTY for the whole test. The outgoing
11	//! brain injects a marker it never reads, then the engine applies a brain-only
12	//! update: the new brain re-attaches via the supplied relaunch closure (which
13	//! stands for "exec the verified new binary → `Brain::handoff`") and must find
14	//! that marker in the *replayed* buffer — proving the broker buffered output
15	//! produced while no brain was attached. Throughout, the child's pid is unchanged
16	//! and exactly one session is hosted: the endpoint never noticed the swap.
17	//!
18	//! **Filename note:** this file is `brain_swap.rs`, NOT `update.rs`, on purpose.
19	//! Windows' installer-detection heuristic (UAC) forces elevation for any
20	//! executable whose name contains `update`/`setup`/`install`/`patch`; a test
21	//! binary `update-<hash>.exe` then fails to launch with `os error 740` (requires
22	//! elevation). Do not rename this to match the module under test.
23	//!
24	//! **REQ-UPD-3 `int` re-pointed (restoration D7-1).** This test proves the
25	//! *in-process* brain-only swap shape (the engine's `apply_brain_only` over an
26	//! in-thread `Brain::handoff` closure) — valuable engine-mechanics coverage, but
27	//! NOT process-level survival. The REQ-UPD-3 `int` evidence (no endpoint drops
28	//! across a brain-only update) now lives in `crates/spt/tests/brain_survive.rs`,
29	//! which swaps a real on-disk binary and respawns the real `spt daemon brain`
30	//! child process (ADR-0018 V5). This file keeps exercising the engine path; it is
31	//! no longer the REQ-UPD-3 int tag.
32
33	use std::sync::atomic::{AtomicU32, Ordering};
34	use std::sync::Arc;
35	use std::thread;
36	use std::time::Duration;
37
38	use spt_daemon::brain::{Brain, BrainState, BrokerEvent};
39	use spt_daemon::msg::SpawnReq;
40	use spt_daemon::update::{apply_brain_only, plan_update, BrokerAbi, ReleaseSpec, UpdateClass};
41	use spt_daemon::Broker;
42
43	static SEQ: AtomicU32 = AtomicU32::new(0);
44	fn unique_name() -> String {
45	    let n = SEQ.fetch_add(1, Ordering::Relaxed);
46	    format!("spt-daemon-c0-{}-{}.sock", std::process::id(), n)
47	}
48
49	fn echo_spawn_req() -> SpawnReq {
50	    #[cfg(unix)]
51	    let (program, args) = ("cat".to_string(), Vec::<String>::new());
52	    #[cfg(windows)]
53	    let (program, args) = ("findstr".to_string(), vec![".".to_string()]);
54	    SpawnReq {
55	        program,
56	        args,
57	        rows: 24,
58	        cols: 80,
59	        endpoint: String::new(),
60	        cwd: None,
61	        env: Default::default(),
62	        translation_binary: None,
63	    }
64	}
65
66	fn cold_retry(name: &str, now_ms: u64) -> Brain {
67	    for _ in 0..300 {
68	        if let Ok(b) = Brain::cold_start(name, now_ms) {
69	            return b;
70	        }
71	        thread::sleep(Duration::from_millis(10));
72	    }
73	    panic!("brain cold-start could not connect");
74	}
75
76	/// The relaunch closure C0's engine drives: it stands for "the verified new
77	/// binary's brain re-attaches over the existing substrate." Retries the connect
78	/// (the broker may not have freed the prior brain's slot the instant we drop it),
79	/// mirroring how a freshly-exec'd brain process races the broker on startup.
80	fn handoff_relaunch(name: &str, prior: BrainState, now_ms: u64) -> std::io::Result<Brain> {
81	    let mut last = None;
82	    for _ in 0..300 {
83	        match Brain::handoff(name, prior.clone(), now_ms) {
84	            Ok(b) => return Ok(b),
85	            Err(e) => last = Some(e),
86	        }
87	        thread::sleep(Duration::from_millis(10));
88	    }
89	    Err(last.unwrap_or_else(|| std::io::Error::other("relaunch never connected")))
90	}
91
92	#[test]
93	fn brain_only_update_swaps_logic_with_zero_endpoint_interruption() {
94	    let name = unique_name();
95	    let broker = Broker::bind(&name).expect("bind broker");
96
97	    // The broker is the stable kernel: it outlives every brain generation.
98	    let serve_broker = Arc::clone(&broker);
99	    thread::spawn(move || {
100	        let _ = serve_broker.serve();
101	    });
102
103	    // Generation 0: cold-start the brain, spawn the long-lived hosted endpoint,
104	    // record its pid — the thing REQ-UPD-3 forbids us from disturbing.
105	    let mut now = 1_000_000u64;
106	    let mut brain = cold_retry(&name, now);
107	    let sid = brain
108	        .spawn_session(echo_spawn_req())
109	        .expect("spawn session");
110	    let child_pid = broker.session_pid(sid);
111	    assert_eq!(brain.generation(), 0);
112
113	    // The engine classifies the release against the RUNNING broker. A pure logic
114	    // release (same held-resource ABI, a brain the running broker already hosts)
115	    // ⇒ brain-only: the routine, endpoint-preserving case.
116	    let running = BrokerAbi::current();
117	    let release = ReleaseSpec {
118	        brain_ipc_version: running.ipc_version,
119	        broker_resource_abi: running.resource_abi,
120	    };
121	    let plan = plan_update(&running, release);
122	    assert_eq!(
123	        plan.class,
124	        UpdateClass::BrainOnly,
125	        "a pure-logic release is brain-only"
126	    );
127
128	    // The outgoing brain hands a marker to its successor and then is swapped out
129	    // WITHOUT reading it — only a gapless re-attach can recover it from the
130	    // broker's replay buffer.
131	    brain
132	        .send_input(b"UPDATED_MARKER_DONE\r")
133	        .expect("inject marker for successor");
134
135	    // Apply the brain-only update through the engine. This is the swap: snapshot
136	    // → drop the outgoing brain (the crash boundary the broker tolerates) →
137	    // relaunch the new brain over the substrate. The engine touches no endpoint.
138	    now += 1; // wall clock advances so the new generation gets a fresh gen_start
139	    let mut brain = apply_brain_only(&plan, brain, |state| handoff_relaunch(&name, state, now))
140	        .expect("brain-only update must apply");
141
142	    // ── REQ-UPD-3: the hosted endpoint never noticed the swap. ──
143	    assert_eq!(
144	        broker.session_count(),
145	        1,
146	        "exactly one session across the update"
147	    );
148	    assert_eq!(
149	        broker.session_pid(sid),
150	        child_pid,
151	        "the hosted child's pid is unchanged"
152	    );
153
154	    // The new brain is a fresh generation with a fresh gen_start (the swap really
155	    // happened — it is not the same brain object).
156	    assert_eq!(brain.generation(), 1, "the brain logic generation advanced");
157	    assert_eq!(
158	        brain.gen_start_ms(),
159	        now,
160	        "fresh gen_start on the swapped-in brain (2.4)"
161	    );
162
163	    // Gapless resume: the marker the pre-update brain injected (and never read)
164	    // arrives via the broker's replayed buffer — output produced across the swap
165	    // window was not lost.
166	    let mut buf = Vec::new();
167	    brain
168	        .read_output_until(b"UPDATED_MARKER_DONE", &mut buf)
169	        .expect("the swapped-in brain must replay output gaplessly across the update");
170
171	    // The post-update brain still fully drives the same endpoint: kill it and see
172	    // the exit event + reaping — the session was live and owned, not a husk.
173	    brain.kill_session().expect("kill session");
174	    loop {
175	        if let BrokerEvent::Exit { session_id, .. } = brain.read_event().expect("read until exit") {
176	            assert_eq!(session_id, sid);
177	            break;
178	        }
179	    }
180	    drop(brain);
181
182	    let mut reaped = false;
183	    for _ in 0..200 {
184	        if broker.session_count() == 0 {
185	            reaped = true;
186	            break;
187	        }
188	        thread::sleep(Duration::from_millis(10));
189	    }
190	    assert!(reaped, "the killed session is reaped from the broker table");
191	}
192

//! C0 E2E — the M3c keystone: a **brain-only self-update** swaps the brain logic
//! through the update engine with **zero hosted-endpoint interruption**
//! (REQ-UPD-3, absolute for the brain-only class — ADR-0004 §A).
//!
//! This rides the same broker/brain substrate the B2 handoff test proves, but
//! drives the swap through the *update engine* (`plan_update` → `apply_brain_only`)
//! rather than calling `Brain::handoff` directly — the engine *triggers* a
//! handoff, it does not re-implement one (`M3c-PLAN.md` §C0, clean-room posture).
//!
//! Shape: one echo child runs under a broker PTY for the whole test. The outgoing
//! brain injects a marker it never reads, then the engine applies a brain-only
//! update: the new brain re-attaches via the supplied relaunch closure (which
//! stands for "exec the verified new binary → `Brain::handoff`") and must find
//! that marker in the *replayed* buffer — proving the broker buffered output
//! produced while no brain was attached. Throughout, the child's pid is unchanged
//! and exactly one session is hosted: the endpoint never noticed the swap.
//!
//! **Filename note:** this file is `brain_swap.rs`, NOT `update.rs`, on purpose.
//! Windows' installer-detection heuristic (UAC) forces elevation for any
//! executable whose name contains `update`/`setup`/`install`/`patch`; a test
//! binary `update-<hash>.exe` then fails to launch with `os error 740` (requires
//! elevation). Do not rename this to match the module under test.
//!
//! **REQ-UPD-3 `int` re-pointed (restoration D7-1).** This test proves the
//! *in-process* brain-only swap shape (the engine's `apply_brain_only` over an
//! in-thread `Brain::handoff` closure) — valuable engine-mechanics coverage, but
//! NOT process-level survival. The REQ-UPD-3 `int` evidence (no endpoint drops
//! across a brain-only update) now lives in `crates/spt/tests/brain_survive.rs`,
//! which swaps a real on-disk binary and respawns the real `spt daemon brain`
//! child process (ADR-0018 V5). This file keeps exercising the engine path; it is
//! no longer the REQ-UPD-3 int tag.

use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use spt_daemon::brain::{Brain, BrainState, BrokerEvent};
use spt_daemon::msg::SpawnReq;
use spt_daemon::update::{apply_brain_only, plan_update, BrokerAbi, ReleaseSpec, UpdateClass};
use spt_daemon::Broker;

static SEQ: AtomicU32 = AtomicU32::new(0);
fn unique_name() -> String {
    let n = SEQ.fetch_add(1, Ordering::Relaxed);
    format!("spt-daemon-c0-{}-{}.sock", std::process::id(), n)
}

fn echo_spawn_req() -> SpawnReq {
    #[cfg(unix)]
    let (program, args) = ("cat".to_string(), Vec::<String>::new());
    #[cfg(windows)]
    let (program, args) = ("findstr".to_string(), vec![".".to_string()]);
    SpawnReq {
        program,
        args,
        rows: 24,
        cols: 80,
        endpoint: String::new(),
        cwd: None,
        env: Default::default(),
        translation_binary: None,
    }
}

fn cold_retry(name: &str, now_ms: u64) -> Brain {
    for _ in 0..300 {
        if let Ok(b) = Brain::cold_start(name, now_ms) {
            return b;
        }
        thread::sleep(Duration::from_millis(10));
    }
    panic!("brain cold-start could not connect");
}

/// The relaunch closure C0's engine drives: it stands for "the verified new
/// binary's brain re-attaches over the existing substrate." Retries the connect
/// (the broker may not have freed the prior brain's slot the instant we drop it),
/// mirroring how a freshly-exec'd brain process races the broker on startup.
fn handoff_relaunch(name: &str, prior: BrainState, now_ms: u64) -> std::io::Result<Brain> {
    let mut last = None;
    for _ in 0..300 {
        match Brain::handoff(name, prior.clone(), now_ms) {
            Ok(b) => return Ok(b),
            Err(e) => last = Some(e),
        }
        thread::sleep(Duration::from_millis(10));
    }
    Err(last.unwrap_or_else(|| std::io::Error::other("relaunch never connected")))
}

#[test]
fn brain_only_update_swaps_logic_with_zero_endpoint_interruption() {
    let name = unique_name();
    let broker = Broker::bind(&name).expect("bind broker");

    // The broker is the stable kernel: it outlives every brain generation.
    let serve_broker = Arc::clone(&broker);
    thread::spawn(move || {
        let _ = serve_broker.serve();
    });

    // Generation 0: cold-start the brain, spawn the long-lived hosted endpoint,
    // record its pid — the thing REQ-UPD-3 forbids us from disturbing.
    let mut now = 1_000_000u64;
    let mut brain = cold_retry(&name, now);
    let sid = brain
        .spawn_session(echo_spawn_req())
        .expect("spawn session");
    let child_pid = broker.session_pid(sid);
    assert_eq!(brain.generation(), 0);

    // The engine classifies the release against the RUNNING broker. A pure logic
    // release (same held-resource ABI, a brain the running broker already hosts)
    // ⇒ brain-only: the routine, endpoint-preserving case.
    let running = BrokerAbi::current();
    let release = ReleaseSpec {
        brain_ipc_version: running.ipc_version,
        broker_resource_abi: running.resource_abi,
    };
    let plan = plan_update(&running, release);
    assert_eq!(
        plan.class,
        UpdateClass::BrainOnly,
        "a pure-logic release is brain-only"
    );

    // The outgoing brain hands a marker to its successor and then is swapped out
    // WITHOUT reading it — only a gapless re-attach can recover it from the
    // broker's replay buffer.
    brain
        .send_input(b"UPDATED_MARKER_DONE\r")
        .expect("inject marker for successor");

    // Apply the brain-only update through the engine. This is the swap: snapshot
    // → drop the outgoing brain (the crash boundary the broker tolerates) →
    // relaunch the new brain over the substrate. The engine touches no endpoint.
    now += 1; // wall clock advances so the new generation gets a fresh gen_start
    let mut brain = apply_brain_only(&plan, brain, |state| handoff_relaunch(&name, state, now))
        .expect("brain-only update must apply");

    // ── REQ-UPD-3: the hosted endpoint never noticed the swap. ──
    assert_eq!(
        broker.session_count(),
        1,
        "exactly one session across the update"
    );
    assert_eq!(
        broker.session_pid(sid),
        child_pid,
        "the hosted child's pid is unchanged"
    );

    // The new brain is a fresh generation with a fresh gen_start (the swap really
    // happened — it is not the same brain object).
    assert_eq!(brain.generation(), 1, "the brain logic generation advanced");
    assert_eq!(
        brain.gen_start_ms(),
        now,
        "fresh gen_start on the swapped-in brain (2.4)"
    );

    // Gapless resume: the marker the pre-update brain injected (and never read)
    // arrives via the broker's replayed buffer — output produced across the swap
    // window was not lost.
    let mut buf = Vec::new();
    brain
        .read_output_until(b"UPDATED_MARKER_DONE", &mut buf)
        .expect("the swapped-in brain must replay output gaplessly across the update");

    // The post-update brain still fully drives the same endpoint: kill it and see
    // the exit event + reaping — the session was live and owned, not a husk.
    brain.kill_session().expect("kill session");
    loop {
        if let BrokerEvent::Exit { session_id, .. } = brain.read_event().expect("read until exit") {
            assert_eq!(session_id, sid);
            break;
        }
    }
    drop(brain);

    let mut reaped = false;
    for _ in 0..200 {
        if broker.session_count() == 0 {
            reaped = true;
            break;
        }
        thread::sleep(Duration::from_millis(10));
    }
    assert!(reaped, "the killed session is reaped from the broker table");
}


Found the real regression — and it's exactly the case doyle flagged. `brain_swap` hangs because **fix #1 broke handoff's load-bearing resume subscribe**: `brain_only_update_swaps_logic...` relies on `Brain::handoff` itself subscribing to replay output (line 168 `read_output_until`). With the eager subscribe removed and no `serve_attach` to compensate, the resumed brain never subscribes → `read_output_until` blocks forever.

doyle's dispatch said: *"Holler if the design's primary (drop handoff's eager subscribe) has a production caller I missed — that flips fix #2 from defense to mandatory."* This is that case. `handoff`-as-resume needs the subscribe; fix #2 (epoch gate) is what actually makes the carrier's double-take safe.

Let me confirm there are no other handoff callers, then restore the subscribe (fix #2 becomes primary):


cd C:/Users/decid/Documents/projects/spt-core && echo "=== Brain::handoff callers ===" && rg -n "Brain::handoff|\.handoff\(|handoff_relaunch" crates/ --type rust | grep -v "fn handoff" && echo "=== does anything call .attach/.subscribe right after handoff? ==="

Find all handoff callers across the tree


=== Brain::handoff callers ===
crates/spt-daemon\tests\brain_swap.rs:7://! rather than calling `Brain::handoff` directly — the engine *triggers* a
crates/spt-daemon\tests\brain_swap.rs:13://! stands for "exec the verified new binary → `Brain::handoff`") and must find
crates/spt-daemon\tests\brain_swap.rs:26://! in-thread `Brain::handoff` closure) — valuable engine-mechanics coverage, but
crates/spt-daemon\tests\brain_swap.rs:83:        match Brain::handoff(name, prior.clone(), now_ms) {
crates/spt-daemon\tests\brain_swap.rs:139:    let mut brain = apply_brain_only(&plan, brain, |state| handoff_relaunch(&name, state, now))
crates/spt-daemon\tests\attach.rs:717:    let mut life2 = Brain::handoff(&name_a, state, 2).expect("handoff");
crates/spt-daemon\tests\attach.rs:1165:// seed). `Brain::handoff` must (1) NOT eagerly subscribe-as-controller (so the
crates/spt-daemon\tests\attach.rs:1222:    let succ = Brain::handoff(&name, state, 2).expect("handoff");
crates/spt-daemon\tests\daemon_e2e.rs:119:        if let Ok(b) = Brain::handoff(name, prior.clone(), now_ms) {
crates/spt-daemon\tests\idempotent.rs:73:        if let Ok(b) = Brain::handoff(name, prior.clone(), now_ms) {
crates/spt-daemon\tests\handoff.rs:68:        if let Ok(b) = Brain::handoff(name, prior.clone(), now_ms) {
crates/spt-daemon\src\brain.rs:14://!   the new generation. [`Brain::handoff`] takes the prior state by value yet
crates/spt-daemon\src\brain.rs:68:/// **deliberately not authoritative on restart** — [`Brain::handoff`] sets a
crates/spt-daemon\src\brain.rs:75:/// message. `BrainState` / [`Brain::handoff`] / [`Brain::snapshot`] stay `pub`
crates/spt-daemon\src\brain.rs:791:    /// [`Brain::handoff`] this does not touch the generation — it is a *second*
crates/spt-daemon\src\update.rs:23://! substrate ([`crate::brain::Brain::handoff`]) — it does **not** re-implement
crates/spt-daemon\src\update.rs:234:/// re-attaches via [`Brain::handoff`]"; in the live daemon it execs the verified
=== does anything call .attach/.subscribe right after handoff? ===


Decisive: handoff's eager subscribe is the **resume mechanism** for many tests (brain_swap, daemon_e2e, idempotent, handoff.rs all read output after handoff). Fix #1 broadly breaks the handoff-as-resume contract — not "test-only trivial" as the plan assumed. Per doyle's explicit "holler if" condition, **fix #1 reverts; fix #2 (epoch gate) becomes the primary, mandatory mechanism**. Restoring the subscribe + updating the contract comments:


Edit

    /// Handoff: connect, handshake, rehydrate the resume cursor + generation
    /// from `prior`, but stamp `gen_start = now()` (NOT `prior.gen_start_ms` —
    /// the 2.4 invariant). It does NOT itself subscribe-as-controller: the
    /// re-serve's `attach_as(sid, 0, …)` is the SOLE controller registration +
    /// replay for this connection (P1c, [REQ-HAZARD-CONTROLLER-WRITER-REORDER]).
    /// `session_cursors` is seeded at the resume point so the consumer uses the
    /// production dedup-below + snap-above path, never the strict reject-gap trap.
    ///
    /// **Test-only (restoration D4-3).** The production resume path is
    /// [`Brain::cold_start`] + [`Brain::resume_sessions`] (broker cursor-of-record),
    /// never this brain→brain frame; `handoff` survives only for the integration
    /// tests. See [`BrainState`].
    // [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
    pub fn handoff(name: &str, prior: BrainState, now_ms: u64) -> io::Result<Self> {
        let mut conn = LocalSocketTransport::connect(name)?;
        send_hello(&mut conn, Role::Brain)?;
        // DEFENSE-IN-DEPTH (P1c): seed the dedup cursor at the resume point so
        // `read_event` routes this session through the dedup-below + snap-above
        // path (matching `resume_sessions`), not the legacy reject-gap path that
        // turns any at-least-once boundary reorder into a fatal `output gap`.
        let mut session_cursors = std::collections::HashMap::new();
        session_cursors.insert(prior.session_id, prior.next_seq);
        let brain = Brain {
            conn: BrainConn::Whole(conn),
            generation: prior.generation + 1,
            gen_start_ms: now_ms, // fresh — prior.gen_start_ms is intentionally discarded
            session_id: Some(prior.session_id),
            next_seq: prior.next_seq,
            net_cursors: std::collections::HashMap::new(),
            presence_cursor: None,
            session_cursors,
            io_timeout: None,
        };
        // PRIMARY (P1c): do NOT eagerly subscribe-as-controller here. A handoff
        // that re-subscribes from `prior.next_seq` (life1's CONSUMPTION cursor,
        // not life2's connection state — this socket has been sent nothing)
        // leaves a stale controller registration that `serve_attach` then
        // re-subscribes from 0 → two `controller_writer` threads race this one
        // socket and reorder the seq stream. Let the re-serve's `attach_as(sid,0)`
        // be the sole controller take + replay.
        Ok(brain)
    }

    /// Handoff: connect, handshake, rehydrate the resume cursor + generation
    /// from `prior`, but stamp `gen_start = now()` (NOT `prior.gen_start_ms` —
    /// the 2.4 invariant), and re-subscribe to the session from the cursor for a
    /// gapless resume.
    ///
    /// The eager `subscribe` IS the resume mechanism — every standalone handoff
    /// caller (the brain-only update engine, `idempotent`/`daemon_e2e`/`handoff`
    /// integration tests) replays output through it with no later `attach`. So it
    /// stays. The P1c controller-writer reorder (a `serve_attach` re-serve that
    /// ALSO subscribes from 0 over this same socket → two racing
    /// `controller_writer`s) is fixed in the BROKER, not by dropping this
    /// subscribe: the epoch gate ([`OutputLog::become_controller`]) guarantees a
    /// single live writer per connection, and the seeded `session_cursors` below
    /// routes the consumer through the dedup-below + snap-above path so any
    /// at-least-once boundary re-send is tolerated, never a fatal reject-gap
    /// ([`REQ-HAZARD-CONTROLLER-WRITER-REORDER`]).
    ///
    /// **Test-only (restoration D4-3).** The production resume path is
    /// [`Brain::cold_start`] + [`Brain::resume_sessions`] (broker cursor-of-record),
    /// never this brain→brain frame; `handoff` survives only for the integration
    /// tests. See [`BrainState`].
    // [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
    pub fn handoff(name: &str, prior: BrainState, now_ms: u64) -> io::Result<Self> {
        let mut conn = LocalSocketTransport::connect(name)?;
        send_hello(&mut conn, Role::Brain)?;
        // DEFENSE-IN-DEPTH (P1c): seed the dedup cursor at the resume point so
        // `read_event` routes this session through the dedup-below + snap-above
        // path (matching `resume_sessions`), not the legacy reject-gap path that
        // turns any at-least-once boundary reorder into a fatal `output gap`.
        let mut session_cursors = std::collections::HashMap::new();
        session_cursors.insert(prior.session_id, prior.next_seq);
        let mut brain = Brain {
            conn: BrainConn::Whole(conn),
            generation: prior.generation + 1,
            gen_start_ms: now_ms, // fresh — prior.gen_start_ms is intentionally discarded
            session_id: Some(prior.session_id),
            next_seq: prior.next_seq,
            net_cursors: std::collections::HashMap::new(),
            presence_cursor: None,
            session_cursors,
            io_timeout: None,
        };
        brain.subscribe(prior.session_id, prior.next_seq)?;
        Ok(brain)
    }


    /// Handoff: connect, handshake, rehydrate the resume cursor + generation
    /// from `prior`, but stamp `gen_start = now()` (NOT `prior.gen_start_ms` —
    /// the 2.4 invariant). It does NOT itself subscribe-as-controller: the
    /// re-serve's `attach_as(sid, 0, …)` is the SOLE controller registration +
    /// replay for this connection (P1c, [REQ-HAZARD-CONTROLLER-WRITER-REORDER]).
    /// `session_cursors` is seeded at the resume point so the consumer uses the
    /// production dedup-below + snap-above path, never the strict reject-gap trap.
    ///
    /// **Test-only (restoration D4-3).** The production resume path is
    /// [`Brain::cold_start`] + [`Brain::resume_sessions`] (broker cursor-of-record),
    /// never this brain→brain frame; `handoff` survives only for the integration
    /// tests. See [`BrainState`].
    // [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
    pub fn handoff(name: &str, prior: BrainState, now_ms: u64) -> io::Result<Self> {
        let mut conn = LocalSocketTransport::connect(name)?;
        send_hello(&mut conn, Role::Brain)?;
        // DEFENSE-IN-DEPTH (P1c): seed the dedup cursor at the resume point so
        // `read_event` routes this session through the dedup-below + snap-above
        // path (matching `resume_sessions`), not the legacy reject-gap path that
        // turns any at-least-once boundary reorder into a fatal `output gap`.
        let mut session_cursors = std::collections::HashMap::new();
        session_cursors.insert(prior.session_id, prior.next_seq);
        let brain = Brain {
            conn: BrainConn::Whole(conn),
            generation: prior.generation + 1,
            gen_start_ms: now_ms, // fresh — prior.gen_start_ms is intentionally discarded
            session_id: Some(prior.session_id),
            next_seq: prior.next_seq,
            net_cursors: std::collections::HashMap::new(),
            presence_cursor: None,
            session_cursors,
            io_timeout: None,
        };
        // PRIMARY (P1c): do NOT eagerly subscribe-as-controller here. A handoff
        // that re-subscribes from `prior.next_seq` (life1's CONSUMPTION cursor,
        // not life2's connection state — this socket has been sent nothing)
        // leaves a stale controller registration that `serve_attach` then
        // re-subscribes from 0 → two `controller_writer` threads race this one
        // socket and reorder the seq stream. Let the re-serve's `attach_as(sid,0)`
        // be the sole controller take + replay.
        Ok(brain)
    }

    /// Handoff: connect, handshake, rehydrate the resume cursor + generation
    /// from `prior`, but stamp `gen_start = now()` (NOT `prior.gen_start_ms` —
    /// the 2.4 invariant), and re-subscribe to the session from the cursor for a
    /// gapless resume.
    ///
    /// The eager `subscribe` IS the resume mechanism — every standalone handoff
    /// caller (the brain-only update engine, `idempotent`/`daemon_e2e`/`handoff`
    /// integration tests) replays output through it with no later `attach`. So it
    /// stays. The P1c controller-writer reorder (a `serve_attach` re-serve that
    /// ALSO subscribes from 0 over this same socket → two racing
    /// `controller_writer`s) is fixed in the BROKER, not by dropping this
    /// subscribe: the epoch gate ([`OutputLog::become_controller`]) guarantees a
    /// single live writer per connection, and the seeded `session_cursors` below
    /// routes the consumer through the dedup-below + snap-above path so any
    /// at-least-once boundary re-send is tolerated, never a fatal reject-gap
    /// ([`REQ-HAZARD-CONTROLLER-WRITER-REORDER`]).
    ///
    /// **Test-only (restoration D4-3).** The production resume path is
    /// [`Brain::cold_start`] + [`Brain::resume_sessions`] (broker cursor-of-record),
    /// never this brain→brain frame; `handoff` survives only for the integration
    /// tests. See [`BrainState`].
    // [impl->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
    pub fn handoff(name: &str, prior: BrainState, now_ms: u64) -> io::Result<Self> {
        let mut conn = LocalSocketTransport::connect(name)?;
        send_hello(&mut conn, Role::Brain)?;
        // DEFENSE-IN-DEPTH (P1c): seed the dedup cursor at the resume point so
        // `read_event` routes this session through the dedup-below + snap-above
        // path (matching `resume_sessions`), not the legacy reject-gap path that
        // turns any at-least-once boundary reorder into a fatal `output gap`.
        let mut session_cursors = std::collections::HashMap::new();
        session_cursors.insert(prior.session_id, prior.next_seq);
        let mut brain = Brain {
            conn: BrainConn::Whole(conn),
            generation: prior.generation + 1,
            gen_start_ms: now_ms, // fresh — prior.gen_start_ms is intentionally discarded
            session_id: Some(prior.session_id),
            next_seq: prior.next_seq,
            net_cursors: std::collections::HashMap::new(),
            presence_cursor: None,
            session_cursors,
            io_timeout: None,
        };
        brain.subscribe(prior.session_id, prior.next_seq)?;
        Ok(brain)
    }

-    /// the 2.4 invariant). It does NOT itself subscribe-as-controller: the

-    /// re-serve's `attach_as(sid, 0, …)` is the SOLE controller registration +

-    /// replay for this connection (P1c, [REQ-HAZARD-CONTROLLER-WRITER-REORDER]).

-    /// `session_cursors` is seeded at the resume point so the consumer uses the

-    /// production dedup-below + snap-above path, never the strict reject-gap trap.

+    /// the 2.4 invariant), and re-subscribe to the session from the cursor for a

+    /// The eager `subscribe` IS the resume mechanism — every standalone handoff

+    /// caller (the brain-only update engine, `idempotent`/`daemon_e2e`/`handoff`

+    /// integration tests) replays output through it with no later `attach`. So it

+    /// stays. The P1c controller-writer reorder (a `serve_attach` re-serve that

+    /// ALSO subscribes from 0 over this same socket → two racing

+    /// `controller_writer`s) is fixed in the BROKER, not by dropping this

+    /// subscribe: the epoch gate ([`OutputLog::become_controller`]) guarantees a

+    /// single live writer per connection, and the seeded `session_cursors` below

+    /// routes the consumer through the dedup-below + snap-above path so any

+    /// at-least-once boundary re-send is tolerated, never a fatal reject-gap

+    /// ([`REQ-HAZARD-CONTROLLER-WRITER-REORDER`]).

-        // PRIMARY (P1c): do NOT eagerly subscribe-as-controller here. A handoff

-        // that re-subscribes from `prior.next_seq` (life1's CONSUMPTION cursor,

-        // not life2's connection state — this socket has been sent nothing)

-        // leaves a stale controller registration that `serve_attach` then

-        // re-subscribes from 0 → two `controller_writer` threads race this one

-        // socket and reorder the seq stream. Let the re-serve's `attach_as(sid,0)`

-        // be the sole controller take + replay.

+        brain.subscribe(prior.session_id, prior.next_seq)?;


Now the subagent's int test `handoff_seeds_resume_cursor_and_issues_no_eager_subscribe` asserts the (now-reverted) no-subscribe contract. Reading it to correct:


1222	    let succ = Brain::handoff(&name, state, 2).expect("handoff");
1223
1224	    // (fix #3) The resume cursor for this session is seeded at exactly the prior
1225	    // consumption point — so `read_event` routes it through the dedup-below +
1226	    // snap-above path (resume mode), never the reject-gap legacy trap.
1227	    assert_eq!(
1228	        succ.session_cursor(sid),
1229	        Some(prior_next_seq),
1230	        "handoff seeds session_cursors at prior.next_seq (resume-mode dedup floor) — \
1231	         this is what keeps a re-served at-least-once boundary re-send from becoming \
1232	         a fatal `output gap` (REQ-HAZARD-CONTROLLER-WRITER-REORDER fix #3)"
1233	    );
1234	    // The brain is in RESUME mode (the per-session map is populated), which is the
1235	    // structural precondition the fix depends on — a handoff that left the map
1236	    // empty (the pre-fix shape) would fall into the strict single-`next_seq`
1237	    // reject-gap path.
1238	    assert!(
1239	        succ.session_cursor(sid).is_some(),
1240	        "handoff leaves the successor in resume mode for the carried session"
1241	    );
1242	    // The local resume bookkeeping matches the snapshot (generation bumped, the
1243	    // session carried, the cursor rehydrated) — corroborating that handoff did its
1244	    // local-only rehydrate without a broker round-trip subscribe.
1245	    assert_eq!(succ.session_id(), Some(sid), "the carried session id is set");
1246	    assert_eq!(
1247	        succ.next_seq(),
1248	        prior_next_seq,
1249	        "the legacy resume cursor is rehydrated from the snapshot"
1250	    );
1251	    assert_eq!(
1252	        succ.generation(),
1253	        prior_generation + 1,
1254	        "handoff bumps the generation (a logic handoff, not a second reader)"
1255	    );
1256
1257	    // Cleanup: reap the echo child (the session id is carried on `succ`).
1258	    let mut succ = succ;
1259	    let _ = succ.kill_session();
1260	    drop(succ);
1261	    let _ = &broker; // hold the broker for the whole test, then drop
1262	}
1263

    let succ = Brain::handoff(&name, state, 2).expect("handoff");

    // (fix #3) The resume cursor for this session is seeded at exactly the prior
    // consumption point — so `read_event` routes it through the dedup-below +
    // snap-above path (resume mode), never the reject-gap legacy trap.
    assert_eq!(
        succ.session_cursor(sid),
        Some(prior_next_seq),
        "handoff seeds session_cursors at prior.next_seq (resume-mode dedup floor) — \
         this is what keeps a re-served at-least-once boundary re-send from becoming \
         a fatal `output gap` (REQ-HAZARD-CONTROLLER-WRITER-REORDER fix #3)"
    );
    // The brain is in RESUME mode (the per-session map is populated), which is the
    // structural precondition the fix depends on — a handoff that left the map
    // empty (the pre-fix shape) would fall into the strict single-`next_seq`
    // reject-gap path.
    assert!(
        succ.session_cursor(sid).is_some(),
        "handoff leaves the successor in resume mode for the carried session"
    );
    // The local resume bookkeeping matches the snapshot (generation bumped, the
    // session carried, the cursor rehydrated) — corroborating that handoff did its
    // local-only rehydrate without a broker round-trip subscribe.
    assert_eq!(succ.session_id(), Some(sid), "the carried session id is set");
    assert_eq!(
        succ.next_seq(),
        prior_next_seq,
        "the legacy resume cursor is rehydrated from the snapshot"
    );
    assert_eq!(
        succ.generation(),
        prior_generation + 1,
        "handoff bumps the generation (a logic handoff, not a second reader)"
    );

    // Cleanup: reap the echo child (the session id is carried on `succ`).
    let mut succ = succ;
    let _ = succ.kill_session();
    drop(succ);
    let _ = &broker; // hold the broker for the whole test, then drop
}


The test's local-state assertions still hold (cursor/session_id/next_seq/generation), but its **name and comments** now assert the wrong contract. Reading its header to correct the framing:


1162
1163	// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
1164	// v0.13.0 P1c — the handoff side of the fix (defects A + the defense-in-depth
1165	// seed). `Brain::handoff` must (1) NOT eagerly subscribe-as-controller (so the
1166	// re-serve's `attach_as(sid,0)` is the SOLE controller registration on this
1167	// connection — no stale `from_seq=prior.next_seq` registration that would spawn a
1168	// second writer to race the re-serve's writer; fix #1), and (2) seed
1169	// `session_cursors` at `prior.next_seq` so the consumer runs the production
1170	// dedup-below + snap-above path (resume mode), never the strict reject-gap legacy
1171	// path that turns any at-least-once boundary reorder into a fatal `output gap`
1172	// (fix #3).
1173	//
1174	// We assert this against a REAL bound broker + a REAL session (so `handoff`
1175	// connects + handshakes for real). The behavioral end-to-end proof that the
1176	// no-eager-subscribe change actually eliminates the two-writer race lives in the
1177	// broker int keystone (`controller_writer_reorder_*`) and the restart carrier
1178	// (`attach_survives_target_brain_restart_exactly_once`); HERE we lock the two
1179	// load-bearing post-conditions of `handoff` itself, deterministically.
1180	#[test]
1181	fn handoff_seeds_resume_cursor_and_issues_no_eager_subscribe() {
1182	    init_home();
1183	    let dir = tempfile::tempdir().expect("tempdir");
1184	    let name = unique_name();
1185	    // A non-net broker is sufficient — handoff is pure brain-IPC (connect +
1186	    // handshake + local cursor rehydrate); no QUIC needed.
1187	    let broker = Broker::bind_in(&name, dir.path().join("effects.log")).expect("bind broker");
1188	    let serve = Arc::clone(&broker);
1189	    thread::spawn(move || {
1190	        let _ = serve.serve();
1191	    });
1192
1193	    // A driver brain spawns the session and reads exactly ONE output chunk, so its
1194	    // consumption cursor (`next_seq`) sits at 1 while the broker's ring holds more
1195	    // — the worst-case stale floor the bug hinged on (`prior.next_seq` is the
1196	    // CONSUMPTION cursor, not the successor connection's delivered state).
1197	    let mut driver = connect_retry(&name);
1198	    let sid = driver.spawn_session(echo_spawn_req()).expect("spawn echo");
1199	    driver.send_effect(1, b"SEED_ONE\r").expect("seed input");
1200	    // Read one Output event to advance the driver's next_seq to 1.
1201	    loop {
1202	        match driver.read_event().expect("driver event") {
1203	            BrokerEvent::Output { .. } => break,
1204	            BrokerEvent::Error { message } => panic!("driver broker error: {message}"),
1205	            _ => {}
1206	        }
1207	    }
1208	    let state: BrainState = driver.snapshot();
1209	    let prior_next_seq = state.next_seq;
1210	    let prior_generation = state.generation;
1211	    assert!(
1212	        prior_next_seq >= 1,
1213	        "driver must have consumed at least seq 0 so the resume cursor is non-trivial \
1214	         (got next_seq={prior_next_seq})"
1215	    );
1216	    drop(driver); // the "crash" — broker, session, output log all survive
1217
1218	    // THE HANDOFF. Post-fix this connects + handshakes + rehydrates local state but
1219	    // sends NO subscribe frame; the successor's controller registration only
1220	    // happens later via an explicit `attach_as`/`attach` (not exercised here — we
1221	    // assert handoff's own post-conditions).
1222	    let succ = Brain::handoff(&name, state, 2).expect("handoff");
1223

// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
// v0.13.0 P1c — the handoff side of the fix (defects A + the defense-in-depth
// seed). `Brain::handoff` must (1) NOT eagerly subscribe-as-controller (so the
// re-serve's `attach_as(sid,0)` is the SOLE controller registration on this
// connection — no stale `from_seq=prior.next_seq` registration that would spawn a
// second writer to race the re-serve's writer; fix #1), and (2) seed
// `session_cursors` at `prior.next_seq` so the consumer runs the production
// dedup-below + snap-above path (resume mode), never the strict reject-gap legacy
// path that turns any at-least-once boundary reorder into a fatal `output gap`
// (fix #3).
//
// We assert this against a REAL bound broker + a REAL session (so `handoff`
// connects + handshakes for real). The behavioral end-to-end proof that the
// no-eager-subscribe change actually eliminates the two-writer race lives in the
// broker int keystone (`controller_writer_reorder_*`) and the restart carrier
// (`attach_survives_target_brain_restart_exactly_once`); HERE we lock the two
// load-bearing post-conditions of `handoff` itself, deterministically.
#[test]
fn handoff_seeds_resume_cursor_and_issues_no_eager_subscribe() {
    init_home();
    let dir = tempfile::tempdir().expect("tempdir");
    let name = unique_name();
    // A non-net broker is sufficient — handoff is pure brain-IPC (connect +
    // handshake + local cursor rehydrate); no QUIC needed.
    let broker = Broker::bind_in(&name, dir.path().join("effects.log")).expect("bind broker");
    let serve = Arc::clone(&broker);
    thread::spawn(move || {
        let _ = serve.serve();
    });

    // A driver brain spawns the session and reads exactly ONE output chunk, so its
    // consumption cursor (`next_seq`) sits at 1 while the broker's ring holds more
    // — the worst-case stale floor the bug hinged on (`prior.next_seq` is the
    // CONSUMPTION cursor, not the successor connection's delivered state).
    let mut driver = connect_retry(&name);
    let sid = driver.spawn_session(echo_spawn_req()).expect("spawn echo");
    driver.send_effect(1, b"SEED_ONE\r").expect("seed input");
    // Read one Output event to advance the driver's next_seq to 1.
    loop {
        match driver.read_event().expect("driver event") {
            BrokerEvent::Output { .. } => break,
            BrokerEvent::Error { message } => panic!("driver broker error: {message}"),
            _ => {}
        }
    }
    let state: BrainState = driver.snapshot();
    let prior_next_seq = state.next_seq;
    let prior_generation = state.generation;
    assert!(
        prior_next_seq >= 1,
        "driver must have consumed at least seq 0 so the resume cursor is non-trivial \
         (got next_seq={prior_next_seq})"
    );
    drop(driver); // the "crash" — broker, session, output log all survive

    // THE HANDOFF. Post-fix this connects + handshakes + rehydrates local state but
    // sends NO subscribe frame; the successor's controller registration only
    // happens later via an explicit `attach_as`/`attach` (not exercised here — we
    // assert handoff's own post-conditions).
    let succ = Brain::handoff(&name, state, 2).expect("handoff");


Rewriting the test's framing to the correct contract (handoff subscribes for resume; the reorder fix is the broker epoch gate), keeping its valid local-state assertions:


// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
// v0.13.0 P1c — the handoff side of the fix (defects A + the defense-in-depth
// seed). `Brain::handoff` must (1) NOT eagerly subscribe-as-controller (so the
// re-serve's `attach_as(sid,0)` is the SOLE controller registration on this
// connection — no stale `from_seq=prior.next_seq` registration that would spawn a
// second writer to race the re-serve's writer; fix #1), and (2) seed
// `session_cursors` at `prior.next_seq` so the consumer runs the production
// dedup-below + snap-above path (resume mode), never the strict reject-gap legacy
// path that turns any at-least-once boundary reorder into a fatal `output gap`
// (fix #3).
//
// We assert this against a REAL bound broker + a REAL session (so `handoff`
// connects + handshakes for real). The behavioral end-to-end proof that the
// no-eager-subscribe change actually eliminates the two-writer race lives in the
// broker int keystone (`controller_writer_reorder_*`) and the restart carrier
// (`attach_survives_target_brain_restart_exactly_once`); HERE we lock the two
// load-bearing post-conditions of `handoff` itself, deterministically.
#[test]
fn handoff_seeds_resume_cursor_and_issues_no_eager_subscribe() {

// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
// v0.13.0 P1c — the handoff side of the fix (the defense-in-depth seed). The
// controller-writer reorder is fixed in the BROKER (the epoch gate guarantees one
// live `controller_writer` per connection), NOT by dropping handoff's eager
// subscribe — that subscribe IS the resume mechanism every standalone handoff
// caller (the brain-only update engine, `idempotent`/`daemon_e2e`/`handoff` int
// tests) replays output through with no later `attach`. So `handoff` must (1)
// re-subscribe for a gapless resume AND (2) seed `session_cursors` at
// `prior.next_seq` so the consumer runs the production dedup-below + snap-above
// path (resume mode), never the strict reject-gap legacy path that turns any
// at-least-once boundary re-send into a fatal `output gap` (fix #3).
//
// We assert this against a REAL bound broker + a REAL session (so `handoff`
// connects + handshakes + subscribes for real). The behavioral end-to-end proof
// that the epoch gate eliminates the two-writer race lives in the broker int
// keystone (`controller_writer_reorder_*`) and the restart carrier
// (`attach_survives_target_brain_restart_exactly_once`); HERE we lock the
// load-bearing post-conditions of `handoff` itself, deterministically.
#[test]
fn handoff_seeds_resume_cursor_and_resubscribes_for_resume() {


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

// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
// v0.13.0 P1c — the handoff side of the fix (defects A + the defense-in-depth
// seed). `Brain::handoff` must (1) NOT eagerly subscribe-as-controller (so the
// re-serve's `attach_as(sid,0)` is the SOLE controller registration on this
// connection — no stale `from_seq=prior.next_seq` registration that would spawn a
// second writer to race the re-serve's writer; fix #1), and (2) seed
// `session_cursors` at `prior.next_seq` so the consumer runs the production
// dedup-below + snap-above path (resume mode), never the strict reject-gap legacy
// path that turns any at-least-once boundary reorder into a fatal `output gap`
// (fix #3).
//
// We assert this against a REAL bound broker + a REAL session (so `handoff`
// connects + handshakes for real). The behavioral end-to-end proof that the
// no-eager-subscribe change actually eliminates the two-writer race lives in the
// broker int keystone (`controller_writer_reorder_*`) and the restart carrier
// (`attach_survives_target_brain_restart_exactly_once`); HERE we lock the two
// load-bearing post-conditions of `handoff` itself, deterministically.
#[test]
fn handoff_seeds_resume_cursor_and_issues_no_eager_subscribe() {

// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
// v0.13.0 P1c — the handoff side of the fix (the defense-in-depth seed). The
// controller-writer reorder is fixed in the BROKER (the epoch gate guarantees one
// live `controller_writer` per connection), NOT by dropping handoff's eager
// subscribe — that subscribe IS the resume mechanism every standalone handoff
// caller (the brain-only update engine, `idempotent`/`daemon_e2e`/`handoff` int
// tests) replays output through with no later `attach`. So `handoff` must (1)
// re-subscribe for a gapless resume AND (2) seed `session_cursors` at
// `prior.next_seq` so the consumer runs the production dedup-below + snap-above
// path (resume mode), never the strict reject-gap legacy path that turns any
// at-least-once boundary re-send into a fatal `output gap` (fix #3).
//
// We assert this against a REAL bound broker + a REAL session (so `handoff`
// connects + handshakes + subscribes for real). The behavioral end-to-end proof
// that the epoch gate eliminates the two-writer race lives in the broker int
// keystone (`controller_writer_reorder_*`) and the restart carrier
// (`attach_survives_target_brain_restart_exactly_once`); HERE we lock the
// load-bearing post-conditions of `handoff` itself, deterministically.
#[test]
fn handoff_seeds_resume_cursor_and_resubscribes_for_resume() {

-// v0.13.0 P1c — the handoff side of the fix (defects A + the defense-in-depth

-// seed). `Brain::handoff` must (1) NOT eagerly subscribe-as-controller (so the

-// re-serve's `attach_as(sid,0)` is the SOLE controller registration on this

-// connection — no stale `from_seq=prior.next_seq` registration that would spawn a

-// second writer to race the re-serve's writer; fix #1), and (2) seed

-// `session_cursors` at `prior.next_seq` so the consumer runs the production

-// dedup-below + snap-above path (resume mode), never the strict reject-gap legacy

-// path that turns any at-least-once boundary reorder into a fatal `output gap`

+// v0.13.0 P1c — the handoff side of the fix (the defense-in-depth seed). The

+// controller-writer reorder is fixed in the BROKER (the epoch gate guarantees one

+// live `controller_writer` per connection), NOT by dropping handoff's eager

+// subscribe — that subscribe IS the resume mechanism every standalone handoff

+// caller (the brain-only update engine, `idempotent`/`daemon_e2e`/`handoff` int

+// tests) replays output through with no later `attach`. So `handoff` must (1)

+// re-subscribe for a gapless resume AND (2) seed `session_cursors` at

+// `prior.next_seq` so the consumer runs the production dedup-below + snap-above

+// path (resume mode), never the strict reject-gap legacy path that turns any

+// at-least-once boundary re-send into a fatal `output gap` (fix #3).

-// connects + handshakes for real). The behavioral end-to-end proof that the

-// no-eager-subscribe change actually eliminates the two-writer race lives in the

-// broker int keystone (`controller_writer_reorder_*`) and the restart carrier

-// (`attach_survives_target_brain_restart_exactly_once`); HERE we lock the two

+// connects + handshakes + subscribes for real). The behavioral end-to-end proof

+// that the epoch gate eliminates the two-writer race lives in the broker int

+// keystone (`controller_writer_reorder_*`) and the restart carrier

+// (`attach_survives_target_brain_restart_exactly_once`); HERE we lock the

let dir = tempfile::tempdir().expect("tempdir");


    // THE HANDOFF. Post-fix this connects + handshakes + rehydrates local state but
    // sends NO subscribe frame; the successor's controller registration only
    // happens later via an explicit `attach_as`/`attach` (not exercised here — we
    // assert handoff's own post-conditions).
    let succ = Brain::handoff(&name, state, 2).expect("handoff");

    // THE HANDOFF. This connects + handshakes + rehydrates local state AND
    // re-subscribes from the resume cursor (the gapless-resume mechanism). The
    // reorder safety for a later `serve_attach` re-serve over this same socket is
    // the broker's epoch gate, not the absence of this subscribe.
    let succ = Brain::handoff(&name, state, 2).expect("handoff");


    // THE HANDOFF. Post-fix this connects + handshakes + rehydrates local state but
    // sends NO subscribe frame; the successor's controller registration only
    // happens later via an explicit `attach_as`/`attach` (not exercised here — we
    // assert handoff's own post-conditions).
    let succ = Brain::handoff(&name, state, 2).expect("handoff");

    // THE HANDOFF. This connects + handshakes + rehydrates local state AND
    // re-subscribes from the resume cursor (the gapless-resume mechanism). The
    // reorder safety for a later `serve_attach` re-serve over this same socket is
    // the broker's epoch gate, not the absence of this subscribe.
    let succ = Brain::handoff(&name, state, 2).expect("handoff");

drop(driver); // the "crash" — broker, session, output log all survive

-    // THE HANDOFF. Post-fix this connects + handshakes + rehydrates local state but

-    // sends NO subscribe frame; the successor's controller registration only

-    // happens later via an explicit `attach_as`/`attach` (not exercised here — we

-    // assert handoff's own post-conditions).

+    // THE HANDOFF. This connects + handshakes + rehydrates local state AND

+    // re-subscribes from the resume cursor (the gapless-resume mechanism). The

+    // reorder safety for a later `serve_attach` re-serve over this same socket is

+    // the broker's epoch gate, not the absence of this subscribe.

// (fix #3) The resume cursor for this session is seeded at exactly the prior


    // The local resume bookkeeping matches the snapshot (generation bumped, the
    // session carried, the cursor rehydrated) — corroborating that handoff did its
    // local-only rehydrate without a broker round-trip subscribe.
    assert_eq!(succ.session_id(), Some(sid), "the carried session id is set");

    // The local resume bookkeeping matches the snapshot (generation bumped, the
    // session carried, the cursor rehydrated) alongside the resume subscribe.
    assert_eq!(succ.session_id(), Some(sid), "the carried session id is set");


    // The local resume bookkeeping matches the snapshot (generation bumped, the
    // session carried, the cursor rehydrated) — corroborating that handoff did its
    // local-only rehydrate without a broker round-trip subscribe.
    assert_eq!(succ.session_id(), Some(sid), "the carried session id is set");

    // The local resume bookkeeping matches the snapshot (generation bumped, the
    // session carried, the cursor rehydrated) alongside the resume subscribe.
    assert_eq!(succ.session_id(), Some(sid), "the carried session id is set");

"handoff leaves the successor in resume mode for the carried session"

-    // session carried, the cursor rehydrated) — corroborating that handoff did its

-    // local-only rehydrate without a broker round-trip subscribe.

+    // session carried, the cursor rehydrated) alongside the resume subscribe.


`attach()` cursor-reset stays (still needed for the carrier's from-0 ground-truth at line 753). The broker epoch-gate keystone is independent of fix #1. Now rebuild + run the full battery — the handoff-resume consumers (brain_swap, handoff, idempotent, daemon_e2e) that fix #1 was silently hanging, plus the carrier + broker keystone:


Bash

cd C:/Users/decid/Documents/projects/spt-core && cargo build -p spt-daemon --tests 2>&1 | tail -5 && echo "BUILD_EXIT=${PIPESTATUS[0]}"

Compile-check all daemon tests after the revert


   Compiling spt-daemon v0.12.1 (C:\Users\decid\Documents\projects\spt-core\crates\spt-daemon)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 37.04s
BUILD_EXIT=0


cd C:/Users/decid/Documents/projects/spt-core
for suite in brain_swap handoff idempotent attach broker inject_control_wedge; do
  echo "=================== $suite ==================="
  timeout 360 cargo test -p spt-daemon --test $suite -- --test-threads=1 2>&1 | grep -E "test result|error\[|panicked|FAILED|has been running" | tail -6
  echo "[$suite EXIT=${PIPESTATUS[0]} (124=HANG)]"
done

Run handoff-consumer + seam suites with timeouts


Command running in background with ID: b577slzfp. 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\b577slzfp.output. You will be notified when it completes. To check interim output, use Read on that file path.


Backgrounded (`b577slzfp`). Build clean. This is a **design deviation** from doyle's locked plan and he explicitly asked to be told — hollering now while tests run: