1094
1095	#[test]
1096	fn g1_choreography_happy_path_payload_reaches_pty_and_controller_keeps_control() {
1097	    init_wedge_home();
1098	    let dir = tempfile::tempdir().expect("tempdir");
1099	    std::env::set_var("XLATE_FIXTURE_MODE", "choreo");
1100	    std::env::remove_var("XLATE_FIXTURE_STDIN_LOG");
1101	    std::env::remove_var("SPT_INJECT_COMMIT_DEADLINE_MS");
1102
1103	    let name = unique_name();
1104	    let endpoint = "xlate-g1-ep";
1105	    // The PTY child is the proven cross-OS ECHO child: the injected payload echoes
1106	    // back over the REAL broker output ring (a custom child reading io::stdin() does
1107	    // NOT receive ConPTY input writes — only a console-native app like findstr/cat
1108	    // does, which is why byte-receipt is observed through the echo, not a side file).
1109	    let (broker, sid, mut controller) =
1110	        spawn_xlate_session(&name, &dir.path().join("g1"), endpoint);
1111
1112	    // Keep the spawning controller brain DRAINED on a background thread so it stays
1113	    // the live, serviceable operator (the W1 coexistence partner) while the injection
1114	    // runs. Pump mode → the read deadline is honored, so the stop flag is observed.
1115	    let stop = Arc::new(AtomicBool::new(false));
1116	    let drain_stop = Arc::clone(&stop);
1117	    let drainer = thread::spawn(move || {
1118	        while !drain_stop.load(Ordering::Relaxed) {
1119	            let _ =
1120	                controller.read_event_until(Some(Instant::now() + Duration::from_millis(100)));
1121	        }
1122	        controller // hand it back so it is dropped only after teardown
1123	    });
1124
1125	    // ── Deliver an inbound message as a real `<EVENT…>` envelope via KIND_ENDPOINT_INPUT.
1126	    //    A live (non-faulted) translation binary OWNS the choreography → the broker
1127	    //    queues the whole envelope to the inject worker, which drives it through the
1128	    //    binary and applies the resulting keystrokes to the PTY atomically. ──
1129	    let envelope = br#"<EVENT type="message" from="peer">hello translation</EVENT>"#;
1130	    let delivered = deliver_endpoint_event(&name, endpoint, envelope, Duration::from_secs(8));
1131
1132	    // (b) BYTE RECEIPT: the choreography's `{text:"XLATE_OK"}` actually reached the
1133	    // PTY — observed via the echo child's output over the REAL broker ring (the
1134	    // real-receipt assertion W1's gate lacked, not merely liveness). The choreography's
1135	    // `ctrl+s` (0x13 = XOFF) pauses this ConPTY's OUTPUT flow, stranding the echoed
1136	    // payload; so we interleave OPERATOR XON keystrokes (`ctrl+q` = 0x11 — exactly
1137	    // what a real operator does to un-stick a frozen terminal, and proof injection
1138	    // coexists with live operator input) WHILE polling the ring until the payload
1139	    // echo flushes. The payload byte already landed on the PTY (XOFF gates output,
1140	    // not the input write); XON releases its buffered echo deterministically.
1141	    let payload_reached = observe_with_xon(&name, sid, b"XLATE_OK", false, Duration::from_secs(12));
1142
1143	    // (a) The controller/operator STAYS SERVICEABLE through + after the injection
1144	    // (the W1 non-wedge bar): KIND_SESSIONS still answers, and a FRESH attach drives
1145	    // input and sees it echo back (XON-resumed). Injection coexisted with the live
1146	    // controller via the floor.
1147	    let sessions_answered =
1148	        probe(&name, KIND_SESSIONS, KIND_SESSIONS_REPLY, Duration::from_secs(5));
1149	    let fresh_attach_served =
1150	        observe_with_xon(&name, sid, b"G1_FRESH_MARKER", true, Duration::from_secs(8));
1151
1152	    // Teardown: reap the PTY child + the controller drainer.
1153	    if let Some(pid) = broker.session_pid(sid) {
1154	        kill_pid(pid);
1155	    }
1156	    stop.store(true, Ordering::Relaxed);
1157	    let _ = drainer.join();
1158
1159	    eprintln!(
1160	        "=== W2 G1 CHOREO GATE: delivered={delivered} payload_reached_pty={payload_reached} \
1161	         sessions_answered={sessions_answered} fresh_attach_served={fresh_attach_served} \
1162	         (all true = inject coexists with a live controller; payload landed via the binary) ==="
1163	    );
1164
1165	    // [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
1166	    assert!(
1167	        delivered,
1168	        "the broker must accept the endpoint event (queued to the live translation worker)"
1169	    );
1170	    assert!(
1171	        sessions_answered,
1172	        "the controller/session must stay SERVICEABLE through+after the injection \
1173	         (KIND_SESSIONS answers) — inject coexists with a live controller via the floor"
1174	    );
1175	    assert!(
1176	        fresh_attach_served,
1177	        "a fresh attach must still be served after the injection (receives PTY output, \
1178	         drives input) — proves the session is fully live, not merely process-alive"
1179	    );
1180
1181	    // BYTE RECEIPT of the binary-injected `XLATE_OK` — PLATFORM-DIVERGENT, treated with
1182	    // the SAME banked stance the W1 park-(b) / W1b gates above use for ConPTY-vs-forkpty
1183	    // PTY-echo divergence (capture on the absorbing platform, hard-assert on the other):
1184	    //  - Unix forkpty cooked-mode reliably echoes the injected line, so the payload's
1185	    //    arrival over the real broker ring is a HARD assertion there (the real-receipt
1186	    //    proof W1's gate lacked).
1187	    //  - Windows ConPTY does NOT surface the cooked echo of a PROGRAMMATICALLY-injected
1188	    //    line the way it echoes interactively-typed input (an operator keystroke echoes
1189	    //    — see g3 `secret_on_pty` — but the inject-worker's `write_input` of the same
1190	    //    bytes does not re-emit through `findstr`'s echo here), and a custom PTY child
1191	    //    reading io::stdin() never receives ConPTY input to record. So on Windows we
1192	    //    CAPTURE the observation (never a false-red) and lean on the other three hard
1193	    //    asserts; the gravity-linux CI run carries the byte-receipt assertion. This
1194	    //    matches the file's existing platform-divergence discipline exactly.
1195	    #[cfg(unix)]
1196	    assert!(
1197	        payload_reached,
1198	        "the choreography's `{{text:XLATE_OK}}` must actually REACH the PTY (real byte \
1199	         receipt via the translation binary, echoed back over the broker ring — the \
1200	         assertion W1's gate lacked), not merely liveness"
1201	    );
1202	    #[cfg(windows)]
1203	    eprintln!(
1204	        "=== W2 G1 (Windows ConPTY observation, not asserted): payload_reached={payload_reached} \
1205	         — ConPTY does not surface the injected line's cooked echo; byte-receipt is the \
1206	         hard assertion on gravity-linux (forkpty). The three asserts above hold here. ==="
1207	    );
1208	    let _ = payload_reached;
1209	}
1210
1211	#[test]
1212	fn g2_no_commit_deadline_faults_binary_and_does_not_wedge_controller_input() {
1213	    init_wedge_home();
1214	    let dir = tempfile::tempdir().expect("tempdir");
1215	    // The binary emits the payload + a key but NEVER `{commit}` → the broker's
1216	    // commit deadline must fire. Shrink the deadline so the structural outcome
1217	    // (floor releases → buffered input flushes → binary faults) is observed fast.
1218	    std::env::set_var("XLATE_FIXTURE_MODE", "nocommit");
1219	    std::env::set_var("SPT_INJECT_COMMIT_DEADLINE_MS", "400");
1220	    std::env::remove_var("XLATE_FIXTURE_STDIN_LOG");
1221
1222	    let name = unique_name();
1223	    let endpoint = "xlate-g2-ep";
1224	    let (broker, sid, mut controller) =
1225	        spawn_xlate_session(&name, &dir.path().join("g2"), endpoint);
1226	    // Bind the controller brain to the session so its keystrokes have a target.
1227	    controller.attach(sid, 0).expect("controller attach");
1228
1229	    // Deliver an event whose binary never commits → the floor OPENS, buffers
1230	    // operator input, and the worker hits the 400ms deadline.
1231	    let envelope = br#"<EVENT type="message" from="peer">no-commit event</EVENT>"#;
1232	    let delivered = deliver_endpoint_event(&name, endpoint, envelope, Duration::from_secs(5));
1233
1234	    // While the floor is (briefly) held, the operator types — Enter-terminated so the
1235	    // echo child flushes the line. After the 400ms deadline the floor must RELEASE and
1236	    // the buffered keystrokes flush to the PTY (then echo back over the ring). Send a
1237	    // few times (some before, some after the deadline) so the flush is exercised; then
1238	    // observe the marker echo — proof the controller input did NOT wedge.
1239	    for _ in 0..4 {
1240	        let _ = controller.send_input(b"OPERATOR_KEYS_FLUSHED\r");
1241	        let _ = controller.read_event_until(Some(Instant::now() + Duration::from_millis(150)));
1242	    }
1243	    let op_flushed =
1244	        output_contains_within(&name, sid, b"OPERATOR_KEYS_FLUSHED", Duration::from_secs(8));
1245
1246	    // The session stays serviceable after the FAULT.
1247	    let sessions_answered =
1248	        probe(&name, KIND_SESSIONS, KIND_SESSIONS_REPLY, Duration::from_secs(5));
1249
1250	    // After the binary faulted, a SUBSEQUENT inbound delivery falls back to RAW
1251	    // inject: the whole envelope bytes land on the PTY directly (the binary no longer
1252	    // drives the choreography). The raw envelope ends in `\r` so the echo child
1253	    // flushes the echoed line; assert the marker reaches the PTY via the ring.
1254	    let raw_envelope = b"<EVENT>RAW_FALLBACK_MARKER</EVENT>\r";
1255	    let delivered2 = deliver_endpoint_event(&name, endpoint, raw_envelope, Duration::from_secs(5));
1256	    let raw_fallback_reached =
1257	        output_contains_within(&name, sid, b"RAW_FALLBACK_MARKER", Duration::from_secs(8));
1258
1259	    if let Some(pid) = broker.session_pid(sid) {
1260	        kill_pid(pid);
1261	    }
1262
1263	    eprintln!(
1264	        "=== W2 G2 NO-COMMIT FAULT GATE: delivered={delivered} op_flushed={op_flushed} \
1265	         sessions_answered={sessions_answered} delivered2={delivered2} \
1266	         raw_fallback_reached={raw_fallback_reached} \
1267	         (op_flushed=true → controller input never wedged; raw_fallback → binary faulted) ==="
1268	    );
1269
1270	    // [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
1271	    assert!(delivered, "the no-commit event must still be accepted by the broker");
1272	    assert!(
1273	        op_flushed,
1274	        "after the commit deadline the floor must RELEASE and buffered operator \
1275	         keystrokes must flush to the PTY — the controller's input must NOT wedge \
1276	         (the mandatory bounded-buffer guard; doyle non-negotiable = never park forever)"
1277	    );
1278	    assert!(
1279	        sessions_answered,
1280	        "the session must stay serviceable after the binary faults"
1281	    );
1282	    assert!(
1283	        raw_fallback_reached,
1284	        "after the FAULT a subsequent inbound delivery must fall back to RAW inject — \
1285	         the raw `<EVENT>` envelope must land on the PTY directly (the faulted binary \
1286	         no longer drives the choreography)"
1287	    );
1288	}
1289
1290	#[test]
1291	fn g3_content_free_ping_never_duplicates_operator_keystrokes_into_binary() {
1292	    init_wedge_home();
1293	    let dir = tempfile::tempdir().expect("tempdir");
1294	    let bin_stdin_log = dir.path().join("xlate_stdin.log");
1295	    // The translation binary records EVERY stdin line it receives here.
1296	    std::env::set_var("XLATE_FIXTURE_STDIN_LOG", &bin_stdin_log);
1297	    std::env::set_var("XLATE_FIXTURE_MODE", "choreo");
1298	    std::env::remove_var("SPT_INJECT_COMMIT_DEADLINE_MS");
1299
1300	    let name = unique_name();
1301	    let endpoint = "xlate-g3-ep";
1302	    let (broker, sid, mut controller) =
1303	        spawn_xlate_session(&name, &dir.path().join("g3"), endpoint);
1304	    controller.attach(sid, 0).expect("controller attach");
1305
1306	    // The operator types a recognizable secret payload as keystrokes (Enter-terminated
1307	    // so the echo child flushes the line). dispatch_input fires a CONTENT-FREE
1308	    // `{type:input}` ping to the binary — NEVER the bytes. The floor is FREE (no inject
1309	    // in flight), so the keystrokes pass through to the PTY and echo back.
1310	    let secret = b"SECRET_OPERATOR_KEYSTROKES_1234";
1311	    for _ in 0..6 {
1312	        let _ = controller.send_input(b"SECRET_OPERATOR_KEYSTROKES_1234\r");
1313	        let _ =
1314	            controller.read_event_until(Some(Instant::now() + Duration::from_millis(40)));
1315	    }
1316	    // The secret must reach the PTY (it is a real operator keystroke), echoed back…
1317	    let secret_on_pty =
1318	        output_contains_within(&name, sid, secret, Duration::from_secs(8));
1319	    // …but must NEVER appear in the binary's stdin log. Give the pings time to land,
1320	    // then assert the binary's stdin contains only `init` / `input` (and any `event`)
1321	    // lines — no operator payload.
1322	    thread::sleep(Duration::from_millis(500));
1323	    let bin_stdin = std::fs::read(&bin_stdin_log).unwrap_or_default();
1324	    let secret_leaked = count(&bin_stdin, secret) >= 1;
1325	    // Structurally confirm content-free pings DID flow (the binary saw `{type:input}`).
1326	    let saw_input_ping = count(&bin_stdin, br#"{"type":"input"}"#) >= 1;
1327
1328	    if let Some(pid) = broker.session_pid(sid) {
1329	        kill_pid(pid);
1330	    }
1331
1332	    eprintln!(
1333	        "=== W2 G3 CONTENT-FREE PING GATE: secret_on_pty={secret_on_pty} \
1334	         secret_leaked_into_binary={secret_leaked} saw_input_ping={saw_input_ping} \
1335	         (privacy = secret_leaked false; the binary sees only content-free pings) ==="
1336	    );
1337
1338	    // [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
1339	    assert!(
1340	        secret_on_pty,
1341	        "the operator's keystrokes must reach the PTY (the floor is free — no inject)"
1342	    );
1343	    assert!(
1344	        !secret_leaked,
1345	        "doyle gate #1 (privacy): the operator's PTY keystrokes must NEVER be \
1346	         duplicated into the translation binary's stdin — only init / event / \
1347	         content-free input lines may reach it. The secret payload leaked into the \
1348	         binary's stdin."
1349	    );
1350	    assert!(
1351	        saw_input_ping,
1352	        "the binary must have received at least one CONTENT-FREE `{{type:input}}` ping \
1353	         (proves the ping fires — and the privacy assertion above is meaningful, not \
1354	         vacuous because no ping flowed)"
1355	    );
1356	}
1357
1358	#[test]
1359	fn g4_translation_child_is_reaped_no_zombie_after_session_down() {
1360	    init_wedge_home();
1361	    let dir = tempfile::tempdir().expect("tempdir");
1362	    std::env::set_var("XLATE_FIXTURE_MODE", "choreo");
1363	    std::env::remove_var("XLATE_FIXTURE_STDIN_LOG");
1364	    std::env::remove_var("SPT_INJECT_COMMIT_DEADLINE_MS");
1365
1366	    let name = unique_name();
1367	    let endpoint = "xlate-g4-ep";
1368	    let (broker, sid, _controller) =
1369	        spawn_xlate_session(&name, &dir.path().join("g4"), endpoint);
1370
1371	    // Capture the translation child's pid via its OS process table presence. The
1372	    // broker does not surface the translation child's pid directly, so we discover
1373	    // it: the `xlate_choreo_fixture` process is a child of THIS test process. We
1374	    // confirm it is live before teardown, then assert it is gone after.
1375	    let xlate_pid = find_xlate_child_pid().expect("translation child should be running");
1376	    assert!(
1377	        pid_alive(xlate_pid),
1378	        "the translation child must be live before teardown (sanity)"
1379	    );
1380
1381	    // Tear the session down: kill the PTY child → the exit waiter reaps the session
1382	    // → the HostedSession (and its Translation) drops → the inject worker's event_tx
1383	    // drops → run_inject_worker exits its loop → child.terminate() (bounded reap).
1384	    if let Some(pid) = broker.session_pid(sid) {
1385	        kill_pid(pid);
1386	    }
1387
1388	    // First, the session must leave the broker table (proves the HostedSession +
1389	    // its Translation dropped → the inject worker's event_tx dropped → the worker
1390	    // reaps the child). This is the structural precondition for the reap.
1391	    let session_gone = {
1392	        let deadline = Instant::now() + Duration::from_secs(6);
1393	        let mut gone = false;
1394	        while Instant::now() < deadline {
1395	            if broker.session_count() == 0 {
1396	                gone = true;
1397	                break;
1398	            }
1399	            thread::sleep(Duration::from_millis(50));
1400	        }
1401	        gone
1402	    };
1403
1404	    // Then poll for the translation child to disappear within the bounded reap
1405	    // window. REAP_GRACE is 500ms; the worker also observes the channel close, so we
1406	    // allow a generous structural deadline (still bounded — never forever).
1407	    let reaped = {
1408	        let deadline = Instant::now() + Duration::from_secs(8);
1409	        let mut gone = false;
1410	        while Instant::now() < deadline {
1411	            if !pid_alive(xlate_pid) {
1412	                gone = true;
1413	                break;
1414	            }
1415	            thread::sleep(Duration::from_millis(50));
1416	        }
1417	        gone
1418	    };
1419	    eprintln!("=== W2 G4 DIAG: session_gone={session_gone} ===");
1420
1421	    // Belt-and-braces: if it somehow survived, don't leak it past the test.
1422	    if !reaped {
1423	        kill_pid(xlate_pid);
1424	    }
1425
1426	    eprintln!(
1427	        "=== W2 G4 NO-ZOMBIE GATE: xlate_pid={xlate_pid} reaped_within_bound={reaped} \
1428	         (true = the translation child is terminated+reaped on session-down — doyle gate #2) ==="
1429	    );
1430
1431	    // [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
1432	    assert!(
1433	        reaped,
1434	        "doyle gate #2 (no-zombie): the translation child must be terminated + reaped \
1435	         within the bounded reap window after session-down / broker teardown — a \
1436	         session-down must never leak a translation child"
1437	    );
1438	}
1439
1440	/// Find the OS pid of the spawned `xlate_choreo_fixture` translation child. The
1441	/// broker does not surface it, so we locate it by image name among THIS process's
1442	/// descendants. Cross-OS, best-effort (the no-zombie test only needs *a* live
1443	/// translation-child pid to then watch disappear).
1444	#[cfg(windows)]
1445	fn find_xlate_child_pid() -> Option<u32> {
1446	    let deadline = Instant::now() + Duration::from_secs(5);
1447	    while Instant::now() < deadline {
1448	        let out = std::process::Command::new("tasklist")
1449	            .args(["/FI", "IMAGENAME eq xlate_choreo_fixture.exe", "/NH", "/FO", "CSV"])
1450	            .output()
1451	            .ok()?;
1452	        let s = String::from_utf8_lossy(&out.stdout);
1453	        // CSV: "xlate_choreo_fixture.exe","<pid>",...
1454	        for line in s.lines() {
1455	            let cells: Vec<&str> = line.split(',').collect();
1456	            if cells.len() >= 2 {
1457	                let pid = cells[1].trim_matches('"').trim();
1458	                if let Ok(p) = pid.parse::<u32>() {
1459	                    return Some(p);
1460	                }
1461	            }
1462	        }
1463	        thread::sleep(Duration::from_millis(50));
1464	    }
1465	    None
1466	}
1467	#[cfg(unix)]
1468	fn find_xlate_child_pid() -> Option<u32> {
1469	    let deadline = Instant::now() + Duration::from_secs(5);
1470	    while Instant::now() < deadline {
1471	        let out = std::process::Command::new("pgrep")
1472	            .args(["-f", "xlate_choreo_fixture"])
1473	            .output()
1474	            .ok()?;
1475	        let s = String::from_utf8_lossy(&out.stdout);
1476	        if let Some(first) = s.lines().next() {
1477	            if let Ok(p) = first.trim().parse::<u32>() {
1478	                return Some(p);
1479	            }
1480	        }
1481	        thread::sleep(Duration::from_millis(50));
1482	    }
1483	    None
1484	}
1485
1486	// ── v0.13.0 W5 — REQ-HAZARD-DRIVEN-BY-SELFHEAL: characterize the TWO distinct
1487	//    mechanisms that leave `driven_by = Some` latched, and what each makes the
1488	//    NEW `SessionInfo.controller_by` field READ. The W5 reconcile self-heal needs
1489	//    to know whether `controller_by == None` is a SUFFICIENT Gap-A signal, or
1490	//    whether the production wedged-controller case keeps it `Some` (meaning the
1491	//    fix must be broker-side eviction, not a reconcile controller_by check). ─────
1492	//
1493	// Steering (todlando, 2026-06-19): two mechanisms, characterized empirically on a
1494	// REAL broker:
1495	//   - A1 (restart / lost in-memory slot): a session hosted with NO remote
1496	//     controller in the in-memory slot → `controller_by` reads None while the
1497	//     session is listed live, and `driven_by` (if pre-stamped) stays Some.
1498	//   - A2 (production wedged-pump / lost detach — the REQ's real target): a real
1499	//     remote controller ATTACHES (become_controller → driven_by=Some, slot
1500	//     occupied by Some(origin)), then its remote is gone but the broker-side
1501	//     controller sink stays OPEN (no clean EOF/detach) and the session is IDLE
1502	//     (no output → the W1 drain-evict / CONTROLLER_WRITE_DEADLINE never fires) →
1503	//     the slot stays Some(origin) → `controller_by` reads SOME, `driven_by` stays
1504	//     Some — the broker still THINKS it's controlled.
1505	//
1506	// These run under the SAME runner contract as the rest of this file (nextest
1507	// process-per-test or `--test-threads=1`), share the process-global SPT_HOME via
1508	// init_wedge_home(), and spin a REAL broker — never a mock of the slot.
1509
1510	/// Query a session's `controller_by` (the new W5 field) + its endpoint from a
1511	/// REAL broker via `KIND_SESSIONS`, on a fresh bounded (pump) brain connection so
1512	/// a wedged reply surfaces as None within the deadline instead of hanging. The
1513	/// reconcile self-heal consumes EXACTLY this read, so this is the field-under-test
1514	/// observed through the real reply path.
1515	fn controller_by_of(name: &str, sid: u64) -> Option<Option<String>> {
1516	    let mut b = Brain::cold_start_pump(name, 1, Duration::from_secs(2)).ok()?;
1517	    let reply = b.sessions().ok()?;
1518	    reply
1519	        .sessions
1520	        .into_iter()
1521	        .find(|s| s.session_id == sid)
1522	        .map(|s| s.controller_by)
1523	}
1524
1525	/// Read an endpoint's persisted `driven_by` straight from its info.json under the
1526	/// test SPT_HOME — the SAME perch path the broker's `stamp_driven_by` writes to
1527	/// (`resolve_perch_path(endpoint, Infer)`), so this observes the real latch the
1528	/// picker / `endpoint list` would render.
1529	fn driven_by_of(endpoint: &str) -> Option<String> {
1530	    let perch = spt_store::perch::resolve_perch_path(endpoint, spt_store::perch::ParentHint::Infer);
1531	    spt_store::info::read_info(&perch).and_then(|i| i.driven_by)
1532	}
1533
1534	#[test]
1535	fn w5_a1_locally_driven_session_reports_controller_by_none() {
1536	    // ── Mechanism A1: a session whose in-memory controller slot holds only the
1537	    //    LOCAL spawner placeholder (by=None) — the same READ a fresh broker
1538	    //    re-hosting a pre-stamped endpoint produces (empty/local slot). The
1539	    //    characterization question: what does `SessionInfo.controller_by` read for
1540	    //    a live session with no REMOTE controller? ──
1541	    init_wedge_home();
1542	    let dir = tempfile::tempdir().expect("tempdir");
1543	    let name = unique_name();
1544	    let endpoint = "w5-a1-ep";
1545	    let _broker = net_broker(&name, &dir.path().join("a1"));
1546
1547	    // Spawn a real flooding child. dispatch_spawn pre-attaches the spawning conn
1548	    // as the LOCAL controller (become_controller, by=None) — controller IS Some,
1549	    // but controller_by() (its REMOTE identity) is None.
1550	    let mut spawner = connect_retry(&name);
1551	    let sid = spawner
1552	        .spawn_session(flood_spawn_req(endpoint))
1553	        .expect("spawn flood child");
1554
1555	    // Let the session settle (it is live + listed). No remote ever attaches.
1556	    thread::sleep(Duration::from_millis(300));
1557
1558	    let cby = controller_by_of(&name, sid);
1559	    let dby = driven_by_of(endpoint);
1560
1561	    eprintln!(
1562	        "=== W5 A1 CHARACTERIZATION: controller_by={cby:?} driven_by={dby:?} \
1563	         (expect controller_by=Some(None) — session live, slot is the local \
1564	         placeholder, NO remote driver; driven_by=None — a local-only controller \
1565	         never latches ONLINE+CONTROLLED) ==="
1566	    );
1567
1568	    if let Some(pid) = _broker.session_pid(sid) {
1569	        kill_pid(pid);
1570	    }
1571
1572	    // [int->REQ-HAZARD-DRIVEN-BY-SELFHEAL]
1573	    // FINDING (A1): a live session with only the local-spawner slot reports
1574	    // controller_by == None. So "controller_by == None on a live session" is the
1575	    // Gap-A signal — it cannot distinguish "no controller at all" from "local-only
1576	    // controller", but BOTH are correctly NOT-remote-driven, so for the Gap-A
1577	    // clear (which is gated on driven_by already being Some) this is sufficient:
1578	    // a local-only session never has driven_by==Some, so the gate never fires
1579	    // falsely on it.
1580	    assert!(
1581	        cby.is_some(),
1582	        "the session must be LISTED live (the broker answered KIND_SESSIONS)"
1583	    );
1584	    assert_eq!(
1585	        cby,
1586	        Some(None),
1587	        "A1: a live, locally-driven (no-remote) session must report \
1588	         controller_by == None — this is the Gap-A signal the reconcile keys on"
1589	    );
1590	    // A purely-local controller never latches the remote-drive marker.
1591	    assert_eq!(
1592	        dby, None,
1593	        "A1: a local-only controller must NOT latch driven_by (ONLINE+CONTROLLED \
1594	         is a remote-drive state) — so the Gap-A clear, gated on driven_by==Some, \
1595	         is correctly inert here"
1596	    );
1597	}
1598
1599	#[test]
1600	fn w5_a2_abandoned_remote_controller_conn_close_eviction_is_platform_divergent() {
1601	    // ── Mechanism A2: a REAL remote controller attaches over a loopback conn
1602	    //    (become_controller → driven_by=Some(origin), slot = Some(origin)). The
1603	    //    operator's remote is then ABANDONED by dropping its brain WITHOUT a clean
1604	    //    EOF/detach, and the session is kept IDLE (a QUIET child, no output → the W1
1605	    //    output-drain-evict never fires). We read controller_by + driven_by and REPORT
1606	    //    whether the broker self-clears the abandoned slot (characterization-only). ──
1607	    //
1608	    // doyle's forkpty ruling (2026-06-21) + todlando's Windows run + the matrix
1609	    // run-1 flake REFRAMED the A2 verdict: the abandoned-remote clear is CONN-CLOSE
1610	    // detection, NOT the output path — dropping the operator brain closes its loopback
1611	    // QUIC conn (FIN), and a broker that detects the close clears controller_by. That
1612	    // clear (when observed) is the CORRECT self-heal of a closed-socket controller
1613	    // (REQ-HAZARD-DRIVEN-BY-SELFHEAL), not the Gap-A false-clear the prior version
1614	    // asserted against. But WHETHER it lands in the 2s read window is TIMING-VARIABLE,
1615	    // NOT cleanly platform-split — TWO things, do NOT conflate:
1616	    //   (a) conn-close clear is NON-DETERMINISTIC w.r.t. the read window on BOTH
1617	    //       platforms: QUIC FIN-detection latency vs the 2s window varies run-to-run.
1618	    //       unix loopback USUALLY clears <2s (Some(None)) but NOT ALWAYS — a matrix run
1619	    //       where it didn't (Some(Some)) is exactly what broke the earlier
1620	    //       unix-hard-assert (the QUIC-timing flake class). windows typically needs the
1621	    //       ~30s idle-timeout. So A2 is CHARACTERIZATION-ONLY on BOTH platforms (REPORT
1622	    //       cby_after_abandon, NEVER hard-assert either polarity — that is the flake).
1623	    //       REQ-HAZARD-DRIVEN-BY-SELFHEAL's HARD int is gap_b (driven_by_selfheal.rs) +
1624	    //       w5_a1; w5_a1/w5_a2 are its characterization arm, so char-only here is
1625	    //       consistent with the REQ's int structure, not a coverage loss.
1626	    //   (b) a TRUE half-open abandon (operator process gone with NO socket close — no
1627	    //       FIN, netsplit) clears on NEITHER platform at ANY window, and is UNSTAGEABLE
1628	    //       on an in-process loopback drop. Closing it is the D4c NetPresence-disconnect
1629	    //       → clear_controller oracle, DEFERRED to REQ-HAZARD-DRIVEN-BY-IDLE-REMOTE-EVICT.
1630	    //       (a) is in-window timing variance of a clear that DOES happen; (b) is a clear
1631	    //       that never happens without the oracle — different problems.
1632	    // The reusable rig is the W1b loopback attach (net_dial_loopback / request_attach /
1633	    // serve_attach / become_controller) with a QUIET long-lived child
1634	    // (`quiet_spawn_req`, no output, never exits, killed only at teardown — no mid-read
1635	    // kill, no Windows reap-during-read flake).
1636	    init_wedge_home();
1637	    let dir = tempfile::tempdir().expect("tempdir");
1638	    let name = unique_name();
1639	    let endpoint = "w5-a2-ep";
1640	    let _broker = net_broker(&name, &dir.path().join("a2"));
1641
1642	    // SEED a real perch info.json for the endpoint so the broker's best-effort
1643	    // `stamp_driven_by` (which `set_driven_by`s `resolve_perch_path(endpoint, Infer)`
1644	    // and ERRORS / no-ops when the record is absent) actually LATCHES — the
1645	    // production endpoint always has a perch; without this seed driven_by silently
1646	    // stays None and the A2 verdict is unobservable (the rig artifact the first
1647	    // run surfaced). The path is the SAME one the broker resolves under SPT_HOME.
1648	    {
1649	        let perch =
1650	            spt_store::perch::resolve_perch_path(endpoint, spt_store::perch::ParentHint::Infer);
1651	        std::fs::create_dir_all(&perch).expect("create perch dir");
1652	        let info = spt_store::info::InfoJson::new(endpoint, "2026-06-19T00:00:00Z", 0, "", "online");
1653	        spt_store::info::write_info(&perch, &info).expect("seed perch info.json");
1654	    }
1655
1656	    // Spawn a QUIET long-lived session for the endpoint: it produces NO output, so
1657	    // the session is IDLE (the drain produces nothing → CONTROLLER_WRITE_DEADLINE
1658	    // never trips AND `controller_writer` never writes to the abandoned operator →
1659	    // no Disconnected-evict). It never exits, so the session row stays live for the
1660	    // read with NO mid-read kill — which also removes the Windows reap-during-read
1661	    // flake the old flood-then-kill rig hit. The child is killed only at teardown.
1662	    let mut spawner = connect_retry(&name);
1663	    let sid = spawner
1664	        .spawn_session(quiet_spawn_req(endpoint))
1665	        .expect("spawn child");
1666
1667	    // A REAL remote controller attaches over loopback (by=Some(origin)). The
1668	    // serve loop runs on its own thread; the operator drives via the stream.
1669	    let (ready_tx, ready_rx) = std::sync::mpsc::channel::<Option<String>>();
1670	    let stop = Arc::new(AtomicBool::new(false));
1671	    let serve_name = name.clone();
1672	    let serve_stop = Arc::clone(&stop);
1673	    let server = thread::spawn(move || {
1674	        // The TARGET serves the inbound attach. Its `brain.attach_as(.., Control,
1675	        // Some(origin))` is what occupies the controller slot with Some(origin).
1676	        let mut target = connect_retry(&serve_name);
1677	        let (stream_a, origin) = match wait_for_stream(&mut target) {
1678	            Some(s) => s,
1679	            None => return,
1680	        };
1681	        // Drive serve_attach until told to stop (it blocks on brain.read_event()).
1682	        // We DON'T cleanly detach — we just abandon it when the test ends. Running
1683	        // it here keeps the controller slot occupied by Some(origin).
1684	        let serve_broker = serve_name.clone();
1685	        let _ = serve_stop; // abandoned, not signalled (the "lost detach" shape)
1686	        let _ = serve_attach(&mut target, &serve_broker, stream_a, "w5-a2-ep", &origin, 0);
1687	    });
1688
1689	    // The operator side: dial loopback + request the attach so the slot fills.
1690	    let mut operator = connect_retry(&name);
1691	    let dialed = operator.net_dial_loopback().expect("dial loopback");
1692	    let stream_b = request_attach(
1693	        &mut operator,
1694	        dialed.conn_id,
1695	        sid,
1696	        0,
1697	        2,
1698	        AttachIntent::Control, // a real DRIVER → become_controller(Some(origin))
1699	    )
1700	    .expect("request attach");
1701	    let subscribed = operator.net_stream_subscribe(stream_b, 0).is_ok();
1702	    let _ = ready_tx.send(Some(dialed.remote_id_hex.clone()));
1703	    let _origin = ready_rx.recv_timeout(Duration::from_secs(5)).ok();
1704
1705	    // Give the broker time to resolve the subscribe → become_controller(Some) →
1706	    // stamp driven_by=Some(origin). The quiet child keeps the session IDLE (no
1707	    // output → no drain-evict) without any kill.
1708	    thread::sleep(Duration::from_secs(2));
1709	    let driven_after_attach = driven_by_of(endpoint);
1710	    let cby_attached = controller_by_of(&name, sid);
1711
1712	    // ── ABANDON the operator's remote WITHOUT a clean detach: drop the operator
1713	    //    brain WITHOUT sending the EOF detach record (net_stream_send(.., true)).
1714	    //    The session is idle (quiet child), so nothing evicts the controller slot. ──
1715	    drop(operator);
1716
1717	    // Capture the child pid for TEARDOWN only — the quiet child is NEVER killed
1718	    // mid-read (it stays live + silent through the read window, so the idle slot is
1719	    // faithfully observable and the broker keeps the session row).
1720	    let child_pid = _broker.session_pid(sid);
1721
1722	    // Hold idle, then read what the broker still believes.
1723	    thread::sleep(Duration::from_secs(2));
1724	    let session_still_listed = controller_by_of(&name, sid).is_some();
1725	    let cby_after_abandon = controller_by_of(&name, sid);
1726	    let driven_after_abandon = driven_by_of(endpoint);
1727
1728	    // Teardown.
1729	    stop.store(true, Ordering::Relaxed);
1730	    if let Some(pid) = child_pid {
1731	        kill_pid(pid);
1732	    }
1733	    let _ = server.join();
1734
1735	    eprintln!(
1736	        "=== W5 A2 CHARACTERIZATION: subscribed={subscribed} \
1737	         driven_after_attach={driven_after_attach:?} cby_attached={cby_attached:?} \
1738	         session_still_listed={session_still_listed} \
1739	         cby_after_abandon={cby_after_abandon:?} driven_after_abandon={driven_after_abandon:?} ==="
1740	    );
1741
1742	    // The CHARACTERIZATION (not a hard pass/fail gate — the steering asked us to
1743	    // REPORT what controller_by reads, and to not burn iterations forcing a flaky
1744	    // A2). We assert only the load-bearing precondition that makes the report
1745	    // meaningful: the remote attach actually became the controller (driven_by
1746	    // latched Some, controller_by read Some(origin)). If that precondition does
1747	    // not hold on this platform/run, the test reports inconclusive via the eprintln
1748	    // above rather than a misleading red.
1749	    if matches!(cby_attached, Some(Some(_))) {
1750	        // [int->REQ-HAZARD-DRIVEN-BY-SELFHEAL]
1751	        // FINDING (A2, CHARACTERIZATION-ONLY on BOTH platforms): the remote attach
1752	        // DID become the controller (slot = Some(origin)). The remote is then
1753	        // abandoned (drop, no clean EOF/detach), closing its loopback QUIC conn (FIN).
1754	        // Whether the broker clears the slot WITHIN the 2s read window is conn-close
1755	        // detection — and it is TIMING-VARIABLE on BOTH platforms: QUIC FIN-detection
1756	        // latency vs the read window is NON-DETERMINISTIC (unix loopback USUALLY but
1757	        // NOT ALWAYS clears <2s — a matrix run that didn't is what bit the prior
1758	        // unix-hard-assert; windows typically needs the ~30s idle-timeout). So this
1759	        // is NOT hard-gated either polarity (a hard cby_after_abandon assert IS the
1760	        // QUIC-timing flake class). We REPORT the observed value. The HARD int for
1761	        // REQ-HAZARD-DRIVEN-BY-SELFHEAL is gap_b (driven_by_selfheal.rs: reconcile
1762	        // offlines AND clears driven_by) + w5_a1; w5_a1/w5_a2 are the characterization
1763	        // arm. The TRUE no-FIN half-open abandon (clears on NEITHER platform at ANY
1764	        // window) stays deferred to REQ-HAZARD-DRIVEN-BY-IDLE-REMOTE-EVICT (D4c
1765	        // presence oracle).
1766	        let cleared = cby_after_abandon == Some(None);
1767	        eprintln!(
1768	            "=== W5 A2 VERDICT (characterization-only): conn-close clear observed \
1769	             in-window? {cleared} — TIMING-VARIABLE on BOTH platforms (QUIC \
1770	             FIN-detection latency vs the 2s window is non-deterministic), so NOT \
1771	             hard-gated here. The no-FIN half-open case is deferred to \
1772	             REQ-HAZARD-DRIVEN-BY-IDLE-REMOTE-EVICT ==="
1773	        );
1774	        // And driven_by remained latched while the broker still thinks it's
1775	        // controlled (the phantom CONTROLLED the picker would render). The seed
1776	        // makes this observable; on a run where the seed/stamp didn't take it is
1777	        // None and we don't over-assert the latch (the controller_by finding above
1778	        // is the load-bearing one).
1779	        eprintln!(
1780	            "=== W5 A2 driven_by latch: after_attach={driven_after_attach:?} \
1781	             after_abandon={driven_after_abandon:?} (Some⇒phantom CONTROLLED \
1782	             persists; the picker renders 'controlled by {{origin}}' forever) ==="
1783	        );
1784	    } else {
1785	        eprintln!(
1786	            "=== W5 A2 INCONCLUSIVE: the remote attach did not become the controller \
1787	             on this run (cby_attached={cby_attached:?}) — A2 not faithfully staged \
1788	             here; rely on the A1 gate + the code-read finding in the report ==="
1789	        );
1790	    }
1791	}
1792
1793	// ── v0.13.0 P0 — REQ-HAZARD-PTY-INPUT-WRITER-WEDGE: the PASTE-WEDGE int gate, the
1794	//    REPRO W1b's int LACKED. W1b relied on ConPTY ABSORBING the write, so it never
1795	//    exercised an INDEFINITE block. THIS gate makes `write_input` GENUINELY PARK on
1796	//    a non-draining harness (forkpty's small kernel input queue on Unix; ConPTY
1797	//    absorbs on Windows — the documented platform-divergence stance the rest of
1798	//    this file uses), then proves the fix: with one input-writer thread per session
1799	//    as the SOLE blocking writer, the parked write parks ONLY its own thread —
1800	//    a CONCURRENT `spt rc` attach still OPENS + RECEIVES output, the operator's next
1801	//    keystroke is still ACCEPTED, and a saturated FIFO DROPS + stamps
1802	//    `input_backpressure` (heal on resume) instead of wedging the broker.
1803	//
1804	// PRE-FIX (the RED this would catch): the paste burst's journaled PtyWrite ran
1805	// `write_input` SYNCHRONOUSLY on the broker dispatch thread → on a forkpty park
1806	// that thread blocked forever → the concurrent attach's subscribe wedged
1807	// ("brain IPC read deadline elapsed", subscribed=false / got_output=false). Real
1808	// broker + real PTY + real rc pump, NO mocks; every wait is behind a watchdog so a
1809	// regression surfaces as a clean FAILURE, never a hang.
1810
1811	/// Read an endpoint perch's `input_backpressure` straight from its info.json under
1812	/// the test SPT_HOME — the SAME perch path the broker's `set_input_backpressure`
1813	/// writes to (`resolve_perch_path(endpoint, Infer)`), so this observes the real
1814	/// operator-visible drop signal the picker / `endpoint list` would render.
1815	fn input_backpressure_of(endpoint: &str) -> Option<bool> {
1816	    let perch = spt_store::perch::resolve_perch_path(endpoint, spt_store::perch::ParentHint::Infer);
1817	    spt_store::info::read_info(&perch).and_then(|i| i.input_backpressure)
1818	}
1819
1820	/// Seed a real perch `info.json` for `endpoint` under the test SPT_HOME so the
1821	/// broker's best-effort `set_input_backpressure` (which no-ops when the record is
1822	/// absent — like `stamp_driven_by`) actually LATCHES the drop signal. The path is
1823	/// the SAME one the broker resolves; without this the stamp silently vanishes and
1824	/// the backpressure leg is unobservable (the W5-A2 rig artifact, reused here).
1825	fn seed_perch(endpoint: &str) {
1826	    let perch = spt_store::perch::resolve_perch_path(endpoint, spt_store::perch::ParentHint::Infer);
1827	    std::fs::create_dir_all(&perch).expect("create perch dir");
1828	    let info = spt_store::info::InfoJson::new(endpoint, "2026-06-19T00:00:00Z", 0, "", "online");
1829	    spt_store::info::write_info(&perch, &info).expect("seed perch info.json");
1830	}
1831
1832	#[test]
1833	fn p0_paste_wedge_parked_write_does_not_starve_attach_or_wedge_broker() {
1834	    init_wedge_home();
1835	    let dir = tempfile::tempdir().expect("tempdir");
1836	    let name = unique_name();
1837	    let endpoint = "p0-paste-wedge-ep";
1838
1839	    // TINY input FIFO so the DROP+INPUT_BACKPRESSURE leg is forced in a handful of
1840	    // records (a parked writer never drains) rather than a few hundred KB of real
1841	    // paste. The bound's PRESENCE (drop-on-full, never block) is the invariant. This
1842	    // env is read at InputWriter::spawn — set it BEFORE the session spawns.
1843	    std::env::set_var("SPT_INPUT_QUEUE_DEPTH", "4");
1844	    // Seed the perch so the input_backpressure stamp lands somewhere observable.
1845	    seed_perch(endpoint);
1846
1847	    let _broker = net_broker(&name, &dir.path().join("p0"));
1848
1849	    // ── A REAL child that IGNORES stdin: its PTY input buffer fills and (on forkpty)
1850	    //    `write_input` PARKS the sole writer thread — the genuine indefinite block
1851	    //    W1b's int never reached. The flood child both ignores stdin AND floods
1852	    //    stdout (so the concurrent attach has output to actually receive). ──
1853	    let mut spawner = connect_retry(&name);
1854	    let sid = spawner
1855	        .spawn_session(flood_spawn_req(endpoint))
1856	        .expect("spawn flood child");
1857	    // The depth override has now been consumed at InputWriter::spawn for THIS
1858	    // session — clear it IMMEDIATELY so no later assert-panic can leak the tiny FIFO
1859	    // into the other tests in this binary (they spawn their own sessions and would
1860	    // mis-drop input at depth 4). A defensive remove also runs at teardown.
1861	    std::env::remove_var("SPT_INPUT_QUEUE_DEPTH");
1862
1863	    // ── The PASTE driver: on its OWN pump connection, pump journaled input
1864	    //    (op_id-carrying send_effect → dispatch_input → apply_once(PtyWrite) =
1865	    //    InputWriter::enqueue). Post-fix each enqueue is non-blocking: it fills the
1866	    //    tiny FIFO, the writer parks on the full PTY input buffer (Unix), and further
1867	    //    enqueues DROP + stamp input_backpressure. The dispatch thread NEVER parks.
1868	    //    Pre-fix the FIRST journaled write parked the dispatch thread itself. ──
1869	    let stop = Arc::new(AtomicBool::new(false));
1870	    let pumped = Arc::new(AtomicU64::new(0));
1871	    let driver_name = name.clone();
1872	    let driver_stop = Arc::clone(&stop);
1873	    let driver_pumped = Arc::clone(&pumped);
1874	    let driver = thread::spawn(move || {
1875	        let mut w = match Brain::cold_start_pump(&driver_name, 1, Duration::from_secs(2)) {
1876	            Ok(b) => b,
1877	            Err(_) => return,
1878	        };
1879	        if w.attach(sid, 0).is_err() {
1880	            return;
1881	        }
1882	        // Paste-shaped: modest records, MANY of them — far more than the depth-4
1883	        // FIFO holds, so saturation (and DROP) is guaranteed once the writer parks.
1884	        let chunk = vec![b'P'; 4 * 1024];
1885	        let mut op = 1u64;
1886	        while !driver_stop.load(Ordering::Relaxed) {
1887	            if w.send_effect(op, &chunk).is_err() {
1888	                break;
1889	            }
1890	            driver_pumped.fetch_add(1, Ordering::Relaxed);
1891	            op += 1;
1892	            // Pace the pump (see the journaled-wedge driver): keep a paste write
1893	            // in-flight without a CPU storm that starves the concurrent attacher.
1894	            let _ = w.read_event_until(Some(Instant::now() + Duration::from_millis(15)));
1895	            // Unix-only (see the journaled-wedge driver): Windows ConPTY absorbs the
1896	            // paste, so there is no CPU storm to pace here.
1897	            #[cfg(unix)]
1898	            std::thread::sleep(Duration::from_millis(5));
1899	        }
1900	    });
1901
1902	    // Let the driver saturate the FIFO and park the writer (Unix) / absorb (Windows).
1903	    thread::sleep(Duration::from_secs(2));
1904
1905	    // ── (3) OPERATOR KEYSTROKE STILL ACCEPTED post-paste: a fresh operator connection
1906	    //    sends a keystroke. The enqueue is non-blocking, so send_input must succeed
1907	    //    immediately even while the writer is parked (the byte may itself DROP under
1908	    //    backpressure — that is fine and operator-visible; the point is the dispatch
1909	    //    path ACCEPTS + returns, never blocks). Pre-fix this wedged on the parked
1910	    //    dispatch thread. ──
1911	    let keystroke_accepted = {
1912	        let mut op = match Brain::cold_start_pump(&name, 1, Duration::from_secs(2)) {
1913	            Ok(b) => b,
1914	            Err(_) => Brain::cold_start(&name, 1).expect("operator connect"),
1915	        };
1916	        op.attach(sid, 0).is_ok() && op.send_input(b"x").is_ok()
1917	    };
1918
1919	    // ── (2) The CONCURRENT `spt rc` attach: a SEPARATE operator dials loopback,
1920	    //    requests a real viewer attach, subscribes, and RECEIVES the flood child's
1921	    //    output while the journaled write is parked. The W1b rig verbatim — the
1922	    //    subscribe reply + real output receipt prove the dispatch serviced this
1923	    //    attach despite the parked write. Bounded by the outer watchdog. ──
1924	    let (result_tx, result_rx) = std::sync::mpsc::channel::<(bool, bool)>();
1925	    let attach_name = name.clone();
1926	    let attacher = thread::spawn(move || {
1927	        // PUMP mode (Split): the got_output loop below uses `read_event_until` with a
1928	        // 250ms slice deadline, which a `Whole` cold_start IGNORES (read_frame blocks
1929	        // forever when no NetStreamData lands) — making `subscribed=false` a
1930	        // measurement artifact rather than a real subscribe failure. Pump honors the
1931	        // slices so the gate reports the true signal (same fix as the a_journaled gate).
1932	        let mut operator = match Brain::cold_start_pump(&attach_name, 1, Duration::from_secs(2)) {
1933	            Ok(b) => b,
1934	            Err(_) => {
1935	                let _ = result_tx.send((false, false));
1936	                return;
1937	            }
1938	        };
1939	        let dialed = match operator.net_dial_loopback() {
1940	            Ok(d) => d,
1941	            Err(_) => {
1942	                let _ = result_tx.send((false, false));
1943	                return;
1944	            }
1945	        };
1946	        let own_origin = dialed.remote_id_hex.clone();
1947	        let stream_b = match request_attach(
1948	            &mut operator,
1949	            dialed.conn_id,
1950	            sid,
1951	            0,
1952	            2,
1953	            AttachIntent::Viewer,
1954	        ) {
1955	            Ok(s) => s,
1956	            Err(_) => {
1957	                let _ = result_tx.send((false, false));
1958	                return;
1959	            }
1960	        };
1961	        let subscribed = operator.net_stream_subscribe(stream_b, 0).is_ok();
1962
1963	        let mut target = connect_retry(&attach_name);
1964	        let (stream_a, origin) = match wait_for_stream(&mut target) {
1965	            Some(s) => s,
1966	            None => {
1967	                let _ = result_tx.send((subscribed, false));
1968	                return;
1969	            }
1970	        };
1971	        assert_eq!(origin, own_origin, "loopback origin is this node's own id");
1972	        let serve_broker = attach_name.clone();
1973	        let server = thread::spawn(move || {
1974	            let _ = serve_attach(&mut target, &serve_broker, stream_a, "p0-paste-wedge-ep", &origin, 0);
1975	        });
1976
1977	        let mut decoder = AttachDecoder::new();
1978	        let mut got_output = false;
1979	        let deadline = Instant::now() + Duration::from_secs(8);
1980	        while Instant::now() < deadline {
1981	            match operator.read_event_until(Some(Instant::now() + Duration::from_millis(250))) {
1982	                Ok(BrokerEvent::NetStreamData { stream_id, bytes, .. }) if stream_id == stream_b => {
1983	                    for rec in decoder.push(&bytes) {
1984	                        if let AttachRecord::Output { data_b64, .. } = rec {
1985	                            let chunk = decode_bytes(&data_b64).unwrap_or_default();
1986	                            if count(&chunk, b"FLOOD") >= 1 {
1987	                                got_output = true;
1988	                            }
1989	                        }
1990	                    }
1991	                    if got_output {
1992	                        break;
1993	                    }
1994	                }
1995	                Ok(_) => continue,
1996	                Err(_) => continue,
1997	            }
1998	        }
1999
2000	        let _ = result_tx.send((subscribed, got_output));
2001	        let _ = operator.net_stream_send(stream_b, &[], None, true);
2002	        let drain_deadline = Instant::now() + Duration::from_secs(12);
2003	        while Instant::now() < drain_deadline {
2004	            match operator.read_event_until(Some(Instant::now() + Duration::from_millis(200))) {
2005	                Ok(BrokerEvent::NetStreamEof { .. }) => break,
2006	                Ok(_) => continue,
2007	                Err(_) => continue,
2008	            }
2009	        }
2010	        let _ = server.join();
2011	    });
2012
2013	    // Watchdog: the hard wall-clock ceiling, env-tunable (attach_gate_watchdog:
2014	    // default 30s tight, CI-generous). A real paste-wedge blocks FOREVER → trips any
2015	    // finite deadline; the knob only grants headroom for a serviced-but-late
2016	    // request_attach ack under CI scheduler starvation (never relaxes the asserts).
2017	    let watchdog = attach_gate_watchdog();
2018	    let recv_t0 = Instant::now();
2019	    let (subscribed, got_output) = result_rx
2020	        .recv_timeout(watchdog)
2021	        .unwrap_or((false, false));
2022	    let recv_elapsed = recv_t0.elapsed();
2023	    // Source-attribution (cheap, load-bearing triage); threshold derived from the
2024	    // CONFIGURED watchdog so the label stays truthful at 30s OR 120s.
2025	    let source = if recv_elapsed >= watchdog.saturating_sub(Duration::from_secs(1)) {
2026	        "WATCHDOG-DEFAULT"
2027	    } else {
2028	        "channel"
2029	    };
2030	    eprintln!(
2031	        "PASTE_FLAKE: MAIN recv -> ({subscribed},{got_output}) after {recv_elapsed:?} (source={source})"
2032	    );
2033
2034	    // ── (4) DROP + INPUT_BACKPRESSURE: while the writer is parked and the driver
2035	    //    keeps pumping, the depth-4 FIFO saturates and enqueues DROP — stamping
2036	    //    input_backpressure=Some(true) on the perch. Poll the perch (the operator-
2037	    //    visible surface) for the rising-edge stamp. On Windows ConPTY ABSORBS the
2038	    //    writes (the writer keeps draining → the FIFO may never saturate), so the
2039	    //    DROP is platform-divergent and CAPTURED there, HARD-asserted on Unix. ──
2040	    let backpressured = {
2041	        let deadline = Instant::now() + Duration::from_secs(6);
2042	        let mut seen = false;
2043	        while Instant::now() < deadline {
2044	            if input_backpressure_of(endpoint) == Some(true) {
2045	                seen = true;
2046	                break;
2047	            }
2048	            thread::sleep(Duration::from_millis(50));
2049	        }
2050	        seen
2051	    };
2052
2053	    // ── HEAL: stop the driver (no more overflow) and DRAIN the child's stdin by
2054	    //    killing+draining is not possible (the child ignores stdin), so instead we
2055	    //    let the writer thread drain the parked FIFO once the child dies: killing the
2056	    //    PTY child closes the master, `write_input` errors/returns, the writer drains
2057	    //    remaining records, and the NEXT accepted enqueue clears the stamp. We model
2058	    //    the heal as: stop overflowing → the broker's own teardown drains. Because a
2059	    //    fully-dead harness never resumes, the deterministic HEAL assertion lives in
2060	    //    the UNIT test (consumer-controlled); here we record the live heal-or-stamp
2061	    //    transition as a diagnostic and assert the load-bearing DROP above. ──
2062	    stop.store(true, Ordering::Relaxed);
2063	    // Bound the teardown joins — see `join_bounded`. This gate shares the wedge
2064	    // teardown shape (driver pump + concurrent attacher); a parked helper here must
2065	    // not ride to the 240s backstop and mask the verdict.
2066	    let _ = join_bounded(driver, Duration::from_secs(8));
2067	    let _ = join_bounded(attacher, Duration::from_secs(8));
2068	    let pumped_n = pumped.load(Ordering::Relaxed);
2069	    let backpressure_after_stop = input_backpressure_of(endpoint);
2070
2071	    if let Some(pid) = session_pid_bounded(&_broker, sid, Duration::from_secs(5)) {
2072	        kill_pid(pid);
2073	    }
2074	    // Clear the process-global depth override so it cannot leak a tiny FIFO into the
2075	    // other tests in this binary (they run serial under --test-threads=1 / nextest
2076	    // process-per-test, but removing it here keeps the env hermetic regardless).
2077	    std::env::remove_var("SPT_INPUT_QUEUE_DEPTH");
2078
2079	    // Teardown hygiene (the cold_start_pump abandoned-reader settle, per W1b).
2080	    thread::sleep(Duration::from_millis(750));
2081
2082	    eprintln!(
2083	        "=== P0 PASTE-WEDGE GATE: pumped={pumped_n} keystroke_accepted={keystroke_accepted} \
2084	         concurrent_attach_subscribed={subscribed} attach_received_output={got_output} \
2085	         backpressured={backpressured} backpressure_after_stop={backpressure_after_stop:?} \
2086	         (fixed = subscribed+got_output+keystroke_accepted true; pre-fix: parked dispatch \
2087	         thread → subscribed=false / no output) ==="
2088	    );
2089
2090	    // [int->REQ-HAZARD-PTY-INPUT-WRITER-WEDGE]
2091	    // CORE non-vacuous gate (RED pre-fix on a forkpty park): a concurrent rc attach
2092	    // must be SERVICED + RECEIVE output while a journaled paste write is in-flight
2093	    // (and, on Unix, parked on the full PTY input buffer). Pre-fix the synchronous
2094	    // write_input on the dispatch thread wedged this ("brain IPC read deadline").
2095	    assert!(
2096	        subscribed,
2097	        "a concurrent `spt rc` attach must be SERVICED while a paste write is parked: \
2098	         the subscribe reply did not arrive within the watchdog — the dispatch thread \
2099	         is blocked on a synchronous write_input (the paste wedge, \
2100	         REQ-HAZARD-PTY-INPUT-WRITER-WEDGE). Post-fix the write is off the dispatch \
2101	         thread on the sole input-writer."
2102	    );
2103	    // The viewer keeps RECEIVING under the flood because an evicted viewer SKIPS
2104	    // TO LIVE (re-subscribe from the ring floor) and a still-subscribed viewer
2105	    // SNAPS the pre-eviction ring-roll forward gap — both viewer-survival paths
2106	    // compose, so the bytes render instead of the attach fataling/stalling.
2107	    // [int->REQ-VIEWER-SKIP-TO-LIVE-ON-EVICT]
2108	    // [int->REQ-HAZARD-VIEWER-RING-ROLL-SNAP]
2109	    assert!(
2110	        got_output,
2111	        "the concurrent attach must actually RECEIVE PTY output from the flooding \
2112	         child (not just liveness) while the paste write is parked — output delivery \
2113	         does not go through the input writer, so receiving bytes proves the dispatch \
2114	         serviced this attach despite the parked write."
2115	    );
2116	    // (3) The operator's own next keystroke is still ACCEPTED (enqueued / returned),
2117	    // never blocked on the parked write.
2118	    assert!(
2119	        keystroke_accepted,
2120	        "the operator's next keystroke after the paste must still be ACCEPTED — \
2121	         send_input enqueues non-blocking and returns even while the writer is parked \
2122	         (the enqueue may itself drop under backpressure; the invariant is that the \
2123	         dispatch path never blocks)."
2124	    );
2125
2126	    // (4) DROP + INPUT_BACKPRESSURE — PLATFORM-DIVERGENT, the same banked stance the
2127	    // W1 park-(b) / W1b gates use: forkpty's small kernel input queue parks the
2128	    // writer so the depth-4 FIFO saturates → DROP stamps the perch (HARD assert on
2129	    // Unix). Windows ConPTY ABSORBS the writes (the writer keeps draining → the FIFO
2130	    // may not saturate), so the stamp is CAPTURED, not asserted (never a false-red);
2131	    // the gravity-linux CI run carries the backpressure assertion.
2132	    #[cfg(unix)]
2133	    assert!(
2134	        backpressured,
2135	        "a saturated input FIFO (parked forkpty writer, driver still pumping) must \
2136	         DROP + stamp input_backpressure=true on the perch (the operator-visible \
2137	         'input dropped, harness not draining' signal) instead of wedging the broker \
2138	         — REQ-HAZARD-PTY-INPUT-WRITER-WEDGE. The HEAL edge is covered \
2139	         deterministically by the broker unit test."
2140	    );
2141	    #[cfg(windows)]
2142	    eprintln!(
2143	        "=== P0 (Windows ConPTY observation, not asserted): backpressured={backpressured} \
2144	         — ConPTY absorbs the write so the FIFO may not saturate; the DROP+backpressure \
2145	         assertion is hard on gravity-linux (forkpty). The three asserts above hold here. ==="
2146	    );
2147	    let _ = backpressured;
2148	}
2149

#[test]
fn g1_choreography_happy_path_payload_reaches_pty_and_controller_keeps_control() {
    init_wedge_home();
    let dir = tempfile::tempdir().expect("tempdir");
    std::env::set_var("XLATE_FIXTURE_MODE", "choreo");
    std::env::remove_var("XLATE_FIXTURE_STDIN_LOG");
    std::env::remove_var("SPT_INJECT_COMMIT_DEADLINE_MS");

    let name = unique_name();
    let endpoint = "xlate-g1-ep";
    // The PTY child is the proven cross-OS ECHO child: the injected payload echoes
    // back over the REAL broker output ring (a custom child reading io::stdin() does
    // NOT receive ConPTY input writes — only a console-native app like findstr/cat
    // does, which is why byte-receipt is observed through the echo, not a side file).
    let (broker, sid, mut controller) =
        spawn_xlate_session(&name, &dir.path().join("g1"), endpoint);

    // Keep the spawning controller brain DRAINED on a background thread so it stays
    // the live, serviceable operator (the W1 coexistence partner) while the injection
    // runs. Pump mode → the read deadline is honored, so the stop flag is observed.
    let stop = Arc::new(AtomicBool::new(false));
    let drain_stop = Arc::clone(&stop);
    let drainer = thread::spawn(move || {
        while !drain_stop.load(Ordering::Relaxed) {
            let _ =
                controller.read_event_until(Some(Instant::now() + Duration::from_millis(100)));
        }
        controller // hand it back so it is dropped only after teardown
    });

    // ── Deliver an inbound message as a real `<EVENT…>` envelope via KIND_ENDPOINT_INPUT.
    //    A live (non-faulted) translation binary OWNS the choreography → the broker
    //    queues the whole envelope to the inject worker, which drives it through the
    //    binary and applies the resulting keystrokes to the PTY atomically. ──
    let envelope = br#"<EVENT type="message" from="peer">hello translation</EVENT>"#;
    let delivered = deliver_endpoint_event(&name, endpoint, envelope, Duration::from_secs(8));

    // (b) BYTE RECEIPT: the choreography's `{text:"XLATE_OK"}` actually reached the
    // PTY — observed via the echo child's output over the REAL broker ring (the
    // real-receipt assertion W1's gate lacked, not merely liveness). The choreography's
    // `ctrl+s` (0x13 = XOFF) pauses this ConPTY's OUTPUT flow, stranding the echoed
    // payload; so we interleave OPERATOR XON keystrokes (`ctrl+q` = 0x11 — exactly
    // what a real operator does to un-stick a frozen terminal, and proof injection
    // coexists with live operator input) WHILE polling the ring until the payload
    // echo flushes. The payload byte already landed on the PTY (XOFF gates output,
    // not the input write); XON releases its buffered echo deterministically.
    let payload_reached = observe_with_xon(&name, sid, b"XLATE_OK", false, Duration::from_secs(12));

    // (a) The controller/operator STAYS SERVICEABLE through + after the injection
    // (the W1 non-wedge bar): KIND_SESSIONS still answers, and a FRESH attach drives
    // input and sees it echo back (XON-resumed). Injection coexisted with the live
    // controller via the floor.
    let sessions_answered =
        probe(&name, KIND_SESSIONS, KIND_SESSIONS_REPLY, Duration::from_secs(5));
    let fresh_attach_served =
        observe_with_xon(&name, sid, b"G1_FRESH_MARKER", true, Duration::from_secs(8));

    // Teardown: reap the PTY child + the controller drainer.
    if let Some(pid) = broker.session_pid(sid) {
        kill_pid(pid);
    }
    stop.store(true, Ordering::Relaxed);
    let _ = drainer.join();

    eprintln!(
        "=== W2 G1 CHOREO GATE: delivered={delivered} payload_reached_pty={payload_reached} \
         sessions_answered={sessions_answered} fresh_attach_served={fresh_attach_served} \
         (all true = inject coexists with a live controller; payload landed via the binary) ==="
    );

    // [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
    assert!(
        delivered,
        "the broker must accept the endpoint event (queued to the live translation worker)"
    );
    assert!(
        sessions_answered,
        "the controller/session must stay SERVICEABLE through+after the injection \
         (KIND_SESSIONS answers) — inject coexists with a live controller via the floor"
    );
    assert!(
        fresh_attach_served,
        "a fresh attach must still be served after the injection (receives PTY output, \
         drives input) — proves the session is fully live, not merely process-alive"
    );

    // BYTE RECEIPT of the binary-injected `XLATE_OK` — PLATFORM-DIVERGENT, treated with
    // the SAME banked stance the W1 park-(b) / W1b gates above use for ConPTY-vs-forkpty
    // PTY-echo divergence (capture on the absorbing platform, hard-assert on the other):
    //  - Unix forkpty cooked-mode reliably echoes the injected line, so the payload's
    //    arrival over the real broker ring is a HARD assertion there (the real-receipt
    //    proof W1's gate lacked).
    //  - Windows ConPTY does NOT surface the cooked echo of a PROGRAMMATICALLY-injected
    //    line the way it echoes interactively-typed input (an operator keystroke echoes
    //    — see g3 `secret_on_pty` — but the inject-worker's `write_input` of the same
    //    bytes does not re-emit through `findstr`'s echo here), and a custom PTY child
    //    reading io::stdin() never receives ConPTY input to record. So on Windows we
    //    CAPTURE the observation (never a false-red) and lean on the other three hard
    //    asserts; the gravity-linux CI run carries the byte-receipt assertion. This
    //    matches the file's existing platform-divergence discipline exactly.
    #[cfg(unix)]
    assert!(
        payload_reached,
        "the choreography's `{{text:XLATE_OK}}` must actually REACH the PTY (real byte \
         receipt via the translation binary, echoed back over the broker ring — the \
         assertion W1's gate lacked), not merely liveness"
    );
    #[cfg(windows)]
    eprintln!(
        "=== W2 G1 (Windows ConPTY observation, not asserted): payload_reached={payload_reached} \
         — ConPTY does not surface the injected line's cooked echo; byte-receipt is the \
         hard assertion on gravity-linux (forkpty). The three asserts above hold here. ==="
    );
    let _ = payload_reached;
}

#[test]
fn g2_no_commit_deadline_faults_binary_and_does_not_wedge_controller_input() {
    init_wedge_home();
    let dir = tempfile::tempdir().expect("tempdir");
    // The binary emits the payload + a key but NEVER `{commit}` → the broker's
    // commit deadline must fire. Shrink the deadline so the structural outcome
    // (floor releases → buffered input flushes → binary faults) is observed fast.
    std::env::set_var("XLATE_FIXTURE_MODE", "nocommit");
    std::env::set_var("SPT_INJECT_COMMIT_DEADLINE_MS", "400");
    std::env::remove_var("XLATE_FIXTURE_STDIN_LOG");

    let name = unique_name();
    let endpoint = "xlate-g2-ep";
    let (broker, sid, mut controller) =
        spawn_xlate_session(&name, &dir.path().join("g2"), endpoint);
    // Bind the controller brain to the session so its keystrokes have a target.
    controller.attach(sid, 0).expect("controller attach");

    // Deliver an event whose binary never commits → the floor OPENS, buffers
    // operator input, and the worker hits the 400ms deadline.
    let envelope = br#"<EVENT type="message" from="peer">no-commit event</EVENT>"#;
    let delivered = deliver_endpoint_event(&name, endpoint, envelope, Duration::from_secs(5));

    // While the floor is (briefly) held, the operator types — Enter-terminated so the
    // echo child flushes the line. After the 400ms deadline the floor must RELEASE and
    // the buffered keystrokes flush to the PTY (then echo back over the ring). Send a
    // few times (some before, some after the deadline) so the flush is exercised; then
    // observe the marker echo — proof the controller input did NOT wedge.
    for _ in 0..4 {
        let _ = controller.send_input(b"OPERATOR_KEYS_FLUSHED\r");
        let _ = controller.read_event_until(Some(Instant::now() + Duration::from_millis(150)));
    }
    let op_flushed =
        output_contains_within(&name, sid, b"OPERATOR_KEYS_FLUSHED", Duration::from_secs(8));

    // The session stays serviceable after the FAULT.
    let sessions_answered =
        probe(&name, KIND_SESSIONS, KIND_SESSIONS_REPLY, Duration::from_secs(5));

    // After the binary faulted, a SUBSEQUENT inbound delivery falls back to RAW
    // inject: the whole envelope bytes land on the PTY directly (the binary no longer
    // drives the choreography). The raw envelope ends in `\r` so the echo child
    // flushes the echoed line; assert the marker reaches the PTY via the ring.
    let raw_envelope = b"<EVENT>RAW_FALLBACK_MARKER</EVENT>\r";
    let delivered2 = deliver_endpoint_event(&name, endpoint, raw_envelope, Duration::from_secs(5));
    let raw_fallback_reached =
        output_contains_within(&name, sid, b"RAW_FALLBACK_MARKER", Duration::from_secs(8));

    if let Some(pid) = broker.session_pid(sid) {
        kill_pid(pid);
    }

    eprintln!(
        "=== W2 G2 NO-COMMIT FAULT GATE: delivered={delivered} op_flushed={op_flushed} \
         sessions_answered={sessions_answered} delivered2={delivered2} \
         raw_fallback_reached={raw_fallback_reached} \
         (op_flushed=true → controller input never wedged; raw_fallback → binary faulted) ==="
    );

    // [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
    assert!(delivered, "the no-commit event must still be accepted by the broker");
    assert!(
        op_flushed,
        "after the commit deadline the floor must RELEASE and buffered operator \
         keystrokes must flush to the PTY — the controller's input must NOT wedge \
         (the mandatory bounded-buffer guard; doyle non-negotiable = never park forever)"
    );
    assert!(
        sessions_answered,
        "the session must stay serviceable after the binary faults"
    );
    assert!(
        raw_fallback_reached,
        "after the FAULT a subsequent inbound delivery must fall back to RAW inject — \
         the raw `<EVENT>` envelope must land on the PTY directly (the faulted binary \
         no longer drives the choreography)"
    );
}

#[test]
fn g3_content_free_ping_never_duplicates_operator_keystrokes_into_binary() {
    init_wedge_home();
    let dir = tempfile::tempdir().expect("tempdir");
    let bin_stdin_log = dir.path().join("xlate_stdin.log");
    // The translation binary records EVERY stdin line it receives here.
    std::env::set_var("XLATE_FIXTURE_STDIN_LOG", &bin_stdin_log);
    std::env::set_var("XLATE_FIXTURE_MODE", "choreo");
    std::env::remove_var("SPT_INJECT_COMMIT_DEADLINE_MS");

    let name = unique_name();
    let endpoint = "xlate-g3-ep";
    let (broker, sid, mut controller) =
        spawn_xlate_session(&name, &dir.path().join("g3"), endpoint);
    controller.attach(sid, 0).expect("controller attach");

    // The operator types a recognizable secret payload as keystrokes (Enter-terminated
    // so the echo child flushes the line). dispatch_input fires a CONTENT-FREE
    // `{type:input}` ping to the binary — NEVER the bytes. The floor is FREE (no inject
    // in flight), so the keystrokes pass through to the PTY and echo back.
    let secret = b"SECRET_OPERATOR_KEYSTROKES_1234";
    for _ in 0..6 {
        let _ = controller.send_input(b"SECRET_OPERATOR_KEYSTROKES_1234\r");
        let _ =
            controller.read_event_until(Some(Instant::now() + Duration::from_millis(40)));
    }
    // The secret must reach the PTY (it is a real operator keystroke), echoed back…
    let secret_on_pty =
        output_contains_within(&name, sid, secret, Duration::from_secs(8));
    // …but must NEVER appear in the binary's stdin log. Give the pings time to land,
    // then assert the binary's stdin contains only `init` / `input` (and any `event`)
    // lines — no operator payload.
    thread::sleep(Duration::from_millis(500));
    let bin_stdin = std::fs::read(&bin_stdin_log).unwrap_or_default();
    let secret_leaked = count(&bin_stdin, secret) >= 1;
    // Structurally confirm content-free pings DID flow (the binary saw `{type:input}`).
    let saw_input_ping = count(&bin_stdin, br#"{"type":"input"}"#) >= 1;

    if let Some(pid) = broker.session_pid(sid) {
        kill_pid(pid);
    }

    eprintln!(
        "=== W2 G3 CONTENT-FREE PING GATE: secret_on_pty={secret_on_pty} \
         secret_leaked_into_binary={secret_leaked} saw_input_ping={saw_input_ping} \
         (privacy = secret_leaked false; the binary sees only content-free pings) ==="
    );

    // [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
    assert!(
        secret_on_pty,
        "the operator's keystrokes must reach the PTY (the floor is free — no inject)"
    );
    assert!(
        !secret_leaked,
        "doyle gate #1 (privacy): the operator's PTY keystrokes must NEVER be \
         duplicated into the translation binary's stdin — only init / event / \
         content-free input lines may reach it. The secret payload leaked into the \
         binary's stdin."
    );
    assert!(
        saw_input_ping,
        "the binary must have received at least one CONTENT-FREE `{{type:input}}` ping \
         (proves the ping fires — and the privacy assertion above is meaningful, not \
         vacuous because no ping flowed)"
    );
}

#[test]
fn g4_translation_child_is_reaped_no_zombie_after_session_down() {
    init_wedge_home();
    let dir = tempfile::tempdir().expect("tempdir");
    std::env::set_var("XLATE_FIXTURE_MODE", "choreo");
    std::env::remove_var("XLATE_FIXTURE_STDIN_LOG");
    std::env::remove_var("SPT_INJECT_COMMIT_DEADLINE_MS");

    let name = unique_name();
    let endpoint = "xlate-g4-ep";
    let (broker, sid, _controller) =
        spawn_xlate_session(&name, &dir.path().join("g4"), endpoint);

    // Capture the translation child's pid via its OS process table presence. The
    // broker does not surface the translation child's pid directly, so we discover
    // it: the `xlate_choreo_fixture` process is a child of THIS test process. We
    // confirm it is live before teardown, then assert it is gone after.
    let xlate_pid = find_xlate_child_pid().expect("translation child should be running");
    assert!(
        pid_alive(xlate_pid),
        "the translation child must be live before teardown (sanity)"
    );

    // Tear the session down: kill the PTY child → the exit waiter reaps the session
    // → the HostedSession (and its Translation) drops → the inject worker's event_tx
    // drops → run_inject_worker exits its loop → child.terminate() (bounded reap).
    if let Some(pid) = broker.session_pid(sid) {
        kill_pid(pid);
    }

    // First, the session must leave the broker table (proves the HostedSession +
    // its Translation dropped → the inject worker's event_tx dropped → the worker
    // reaps the child). This is the structural precondition for the reap.
    let session_gone = {
        let deadline = Instant::now() + Duration::from_secs(6);
        let mut gone = false;
        while Instant::now() < deadline {
            if broker.session_count() == 0 {
                gone = true;
                break;
            }
            thread::sleep(Duration::from_millis(50));
        }
        gone
    };

    // Then poll for the translation child to disappear within the bounded reap
    // window. REAP_GRACE is 500ms; the worker also observes the channel close, so we
    // allow a generous structural deadline (still bounded — never forever).
    let reaped = {
        let deadline = Instant::now() + Duration::from_secs(8);
        let mut gone = false;
        while Instant::now() < deadline {
            if !pid_alive(xlate_pid) {
                gone = true;
                break;
            }
            thread::sleep(Duration::from_millis(50));
        }
        gone
    };
    eprintln!("=== W2 G4 DIAG: session_gone={session_gone} ===");

    // Belt-and-braces: if it somehow survived, don't leak it past the test.
    if !reaped {
        kill_pid(xlate_pid);
    }

    eprintln!(
        "=== W2 G4 NO-ZOMBIE GATE: xlate_pid={xlate_pid} reaped_within_bound={reaped} \
         (true = the translation child is terminated+reaped on session-down — doyle gate #2) ==="
    );

    // [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
    assert!(
        reaped,
        "doyle gate #2 (no-zombie): the translation child must be terminated + reaped \
         within the bounded reap window after session-down / broker teardown — a \
         session-down must never leak a translation child"
    );
}

/// Find the OS pid of the spawned `xlate_choreo_fixture` translation child. The
/// broker does not surface it, so we locate it by image name among THIS process's
/// descendants. Cross-OS, best-effort (the no-zombie test only needs *a* live
/// translation-child pid to then watch disappear).
#[cfg(windows)]
fn find_xlate_child_pid() -> Option<u32> {
    let deadline = Instant::now() + Duration::from_secs(5);
    while Instant::now() < deadline {
        let out = std::process::Command::new("tasklist")
            .args(["/FI", "IMAGENAME eq xlate_choreo_fixture.exe", "/NH", "/FO", "CSV"])
            .output()
            .ok()?;
        let s = String::from_utf8_lossy(&out.stdout);
        // CSV: "xlate_choreo_fixture.exe","<pid>",...
        for line in s.lines() {
            let cells: Vec<&str> = line.split(',').collect();
            if cells.len() >= 2 {
                let pid = cells[1].trim_matches('"').trim();
                if let Ok(p) = pid.parse::<u32>() {
                    return Some(p);
                }
            }
        }
        thread::sleep(Duration::from_millis(50));
    }
    None
}
#[cfg(unix)]
fn find_xlate_child_pid() -> Option<u32> {
    let deadline = Instant::now() + Duration::from_secs(5);
    while Instant::now() < deadline {
        let out = std::process::Command::new("pgrep")
            .args(["-f", "xlate_choreo_fixture"])
            .output()
            .ok()?;
        let s = String::from_utf8_lossy(&out.stdout);
        if let Some(first) = s.lines().next() {
            if let Ok(p) = first.trim().parse::<u32>() {
                return Some(p);
            }
        }
        thread::sleep(Duration::from_millis(50));
    }
    None
}

// ── v0.13.0 W5 — REQ-HAZARD-DRIVEN-BY-SELFHEAL: characterize the TWO distinct
//    mechanisms that leave `driven_by = Some` latched, and what each makes the
//    NEW `SessionInfo.controller_by` field READ. The W5 reconcile self-heal needs
//    to know whether `controller_by == None` is a SUFFICIENT Gap-A signal, or
//    whether the production wedged-controller case keeps it `Some` (meaning the
//    fix must be broker-side eviction, not a reconcile controller_by check). ─────
//
// Steering (todlando, 2026-06-19): two mechanisms, characterized empirically on a
// REAL broker:
//   - A1 (restart / lost in-memory slot): a session hosted with NO remote
//     controller in the in-memory slot → `controller_by` reads None while the
//     session is listed live, and `driven_by` (if pre-stamped) stays Some.
//   - A2 (production wedged-pump / lost detach — the REQ's real target): a real
//     remote controller ATTACHES (become_controller → driven_by=Some, slot
//     occupied by Some(origin)), then its remote is gone but the broker-side
//     controller sink stays OPEN (no clean EOF/detach) and the session is IDLE
//     (no output → the W1 drain-evict / CONTROLLER_WRITE_DEADLINE never fires) →
//     the slot stays Some(origin) → `controller_by` reads SOME, `driven_by` stays
//     Some — the broker still THINKS it's controlled.
//
// These run under the SAME runner contract as the rest of this file (nextest
// process-per-test or `--test-threads=1`), share the process-global SPT_HOME via
// init_wedge_home(), and spin a REAL broker — never a mock of the slot.

/// Query a session's `controller_by` (the new W5 field) + its endpoint from a
/// REAL broker via `KIND_SESSIONS`, on a fresh bounded (pump) brain connection so
/// a wedged reply surfaces as None within the deadline instead of hanging. The
/// reconcile self-heal consumes EXACTLY this read, so this is the field-under-test
/// observed through the real reply path.
fn controller_by_of(name: &str, sid: u64) -> Option<Option<String>> {
    let mut b = Brain::cold_start_pump(name, 1, Duration::from_secs(2)).ok()?;
    let reply = b.sessions().ok()?;
    reply
        .sessions
        .into_iter()
        .find(|s| s.session_id == sid)
        .map(|s| s.controller_by)
}

/// Read an endpoint's persisted `driven_by` straight from its info.json under the
/// test SPT_HOME — the SAME perch path the broker's `stamp_driven_by` writes to
/// (`resolve_perch_path(endpoint, Infer)`), so this observes the real latch the
/// picker / `endpoint list` would render.
fn driven_by_of(endpoint: &str) -> Option<String> {
    let perch = spt_store::perch::resolve_perch_path(endpoint, spt_store::perch::ParentHint::Infer);
    spt_store::info::read_info(&perch).and_then(|i| i.driven_by)
}

#[test]
fn w5_a1_locally_driven_session_reports_controller_by_none() {
    // ── Mechanism A1: a session whose in-memory controller slot holds only the
    //    LOCAL spawner placeholder (by=None) — the same READ a fresh broker
    //    re-hosting a pre-stamped endpoint produces (empty/local slot). The
    //    characterization question: what does `SessionInfo.controller_by` read for
    //    a live session with no REMOTE controller? ──
    init_wedge_home();
    let dir = tempfile::tempdir().expect("tempdir");
    let name = unique_name();
    let endpoint = "w5-a1-ep";
    let _broker = net_broker(&name, &dir.path().join("a1"));

    // Spawn a real flooding child. dispatch_spawn pre-attaches the spawning conn
    // as the LOCAL controller (become_controller, by=None) — controller IS Some,
    // but controller_by() (its REMOTE identity) is None.
    let mut spawner = connect_retry(&name);
    let sid = spawner
        .spawn_session(flood_spawn_req(endpoint))
        .expect("spawn flood child");

    // Let the session settle (it is live + listed). No remote ever attaches.
    thread::sleep(Duration::from_millis(300));

    let cby = controller_by_of(&name, sid);
    let dby = driven_by_of(endpoint);

    eprintln!(
        "=== W5 A1 CHARACTERIZATION: controller_by={cby:?} driven_by={dby:?} \
         (expect controller_by=Some(None) — session live, slot is the local \
         placeholder, NO remote driver; driven_by=None — a local-only controller \
         never latches ONLINE+CONTROLLED) ==="
    );

    if let Some(pid) = _broker.session_pid(sid) {
        kill_pid(pid);
    }

    // [int->REQ-HAZARD-DRIVEN-BY-SELFHEAL]
    // FINDING (A1): a live session with only the local-spawner slot reports
    // controller_by == None. So "controller_by == None on a live session" is the
    // Gap-A signal — it cannot distinguish "no controller at all" from "local-only
    // controller", but BOTH are correctly NOT-remote-driven, so for the Gap-A
    // clear (which is gated on driven_by already being Some) this is sufficient:
    // a local-only session never has driven_by==Some, so the gate never fires
    // falsely on it.
    assert!(
        cby.is_some(),
        "the session must be LISTED live (the broker answered KIND_SESSIONS)"
    );
    assert_eq!(
        cby,
        Some(None),
        "A1: a live, locally-driven (no-remote) session must report \
         controller_by == None — this is the Gap-A signal the reconcile keys on"
    );
    // A purely-local controller never latches the remote-drive marker.
    assert_eq!(
        dby, None,
        "A1: a local-only controller must NOT latch driven_by (ONLINE+CONTROLLED \
         is a remote-drive state) — so the Gap-A clear, gated on driven_by==Some, \
         is correctly inert here"
    );
}

#[test]
fn w5_a2_abandoned_remote_controller_conn_close_eviction_is_platform_divergent() {
    // ── Mechanism A2: a REAL remote controller attaches over a loopback conn
    //    (become_controller → driven_by=Some(origin), slot = Some(origin)). The
    //    operator's remote is then ABANDONED by dropping its brain WITHOUT a clean
    //    EOF/detach, and the session is kept IDLE (a QUIET child, no output → the W1
    //    output-drain-evict never fires). We read controller_by + driven_by and REPORT
    //    whether the broker self-clears the abandoned slot (characterization-only). ──
    //
    // doyle's forkpty ruling (2026-06-21) + todlando's Windows run + the matrix
    // run-1 flake REFRAMED the A2 verdict: the abandoned-remote clear is CONN-CLOSE
    // detection, NOT the output path — dropping the operator brain closes its loopback
    // QUIC conn (FIN), and a broker that detects the close clears controller_by. That
    // clear (when observed) is the CORRECT self-heal of a closed-socket controller
    // (REQ-HAZARD-DRIVEN-BY-SELFHEAL), not the Gap-A false-clear the prior version
    // asserted against. But WHETHER it lands in the 2s read window is TIMING-VARIABLE,
    // NOT cleanly platform-split — TWO things, do NOT conflate:
    //   (a) conn-close clear is NON-DETERMINISTIC w.r.t. the read window on BOTH
    //       platforms: QUIC FIN-detection latency vs the 2s window varies run-to-run.
    //       unix loopback USUALLY clears <2s (Some(None)) but NOT ALWAYS — a matrix run
    //       where it didn't (Some(Some)) is exactly what broke the earlier
    //       unix-hard-assert (the QUIC-timing flake class). windows typically needs the
    //       ~30s idle-timeout. So A2 is CHARACTERIZATION-ONLY on BOTH platforms (REPORT
    //       cby_after_abandon, NEVER hard-assert either polarity — that is the flake).
    //       REQ-HAZARD-DRIVEN-BY-SELFHEAL's HARD int is gap_b (driven_by_selfheal.rs) +
    //       w5_a1; w5_a1/w5_a2 are its characterization arm, so char-only here is
    //       consistent with the REQ's int structure, not a coverage loss.
    //   (b) a TRUE half-open abandon (operator process gone with NO socket close — no
    //       FIN, netsplit) clears on NEITHER platform at ANY window, and is UNSTAGEABLE
    //       on an in-process loopback drop. Closing it is the D4c NetPresence-disconnect
    //       → clear_controller oracle, DEFERRED to REQ-HAZARD-DRIVEN-BY-IDLE-REMOTE-EVICT.
    //       (a) is in-window timing variance of a clear that DOES happen; (b) is a clear
    //       that never happens without the oracle — different problems.
    // The reusable rig is the W1b loopback attach (net_dial_loopback / request_attach /
    // serve_attach / become_controller) with a QUIET long-lived child
    // (`quiet_spawn_req`, no output, never exits, killed only at teardown — no mid-read
    // kill, no Windows reap-during-read flake).
    init_wedge_home();
    let dir = tempfile::tempdir().expect("tempdir");
    let name = unique_name();
    let endpoint = "w5-a2-ep";
    let _broker = net_broker(&name, &dir.path().join("a2"));

    // SEED a real perch info.json for the endpoint so the broker's best-effort
    // `stamp_driven_by` (which `set_driven_by`s `resolve_perch_path(endpoint, Infer)`
    // and ERRORS / no-ops when the record is absent) actually LATCHES — the
    // production endpoint always has a perch; without this seed driven_by silently
    // stays None and the A2 verdict is unobservable (the rig artifact the first
    // run surfaced). The path is the SAME one the broker resolves under SPT_HOME.
    {
        let perch =
            spt_store::perch::resolve_perch_path(endpoint, spt_store::perch::ParentHint::Infer);
        std::fs::create_dir_all(&perch).expect("create perch dir");
        let info = spt_store::info::InfoJson::new(endpoint, "2026-06-19T00:00:00Z", 0, "", "online");
        spt_store::info::write_info(&perch, &info).expect("seed perch info.json");
    }

    // Spawn a QUIET long-lived session for the endpoint: it produces NO output, so
    // the session is IDLE (the drain produces nothing → CONTROLLER_WRITE_DEADLINE
    // never trips AND `controller_writer` never writes to the abandoned operator →
    // no Disconnected-evict). It never exits, so the session row stays live for the
    // read with NO mid-read kill — which also removes the Windows reap-during-read
    // flake the old flood-then-kill rig hit. The child is killed only at teardown.
    let mut spawner = connect_retry(&name);
    let sid = spawner
        .spawn_session(quiet_spawn_req(endpoint))
        .expect("spawn child");

    // A REAL remote controller attaches over loopback (by=Some(origin)). The
    // serve loop runs on its own thread; the operator drives via the stream.
    let (ready_tx, ready_rx) = std::sync::mpsc::channel::<Option<String>>();
    let stop = Arc::new(AtomicBool::new(false));
    let serve_name = name.clone();
    let serve_stop = Arc::clone(&stop);
    let server = thread::spawn(move || {
        // The TARGET serves the inbound attach. Its `brain.attach_as(.., Control,
        // Some(origin))` is what occupies the controller slot with Some(origin).
        let mut target = connect_retry(&serve_name);
        let (stream_a, origin) = match wait_for_stream(&mut target) {
            Some(s) => s,
            None => return,
        };
        // Drive serve_attach until told to stop (it blocks on brain.read_event()).
        // We DON'T cleanly detach — we just abandon it when the test ends. Running
        // it here keeps the controller slot occupied by Some(origin).
        let serve_broker = serve_name.clone();
        let _ = serve_stop; // abandoned, not signalled (the "lost detach" shape)
        let _ = serve_attach(&mut target, &serve_broker, stream_a, "w5-a2-ep", &origin, 0);
    });

    // The operator side: dial loopback + request the attach so the slot fills.
    let mut operator = connect_retry(&name);
    let dialed = operator.net_dial_loopback().expect("dial loopback");
    let stream_b = request_attach(
        &mut operator,
        dialed.conn_id,
        sid,
        0,
        2,
        AttachIntent::Control, // a real DRIVER → become_controller(Some(origin))
    )
    .expect("request attach");
    let subscribed = operator.net_stream_subscribe(stream_b, 0).is_ok();
    let _ = ready_tx.send(Some(dialed.remote_id_hex.clone()));
    let _origin = ready_rx.recv_timeout(Duration::from_secs(5)).ok();

    // Give the broker time to resolve the subscribe → become_controller(Some) →
    // stamp driven_by=Some(origin). The quiet child keeps the session IDLE (no
    // output → no drain-evict) without any kill.
    thread::sleep(Duration::from_secs(2));
    let driven_after_attach = driven_by_of(endpoint);
    let cby_attached = controller_by_of(&name, sid);

    // ── ABANDON the operator's remote WITHOUT a clean detach: drop the operator
    //    brain WITHOUT sending the EOF detach record (net_stream_send(.., true)).
    //    The session is idle (quiet child), so nothing evicts the controller slot. ──
    drop(operator);

    // Capture the child pid for TEARDOWN only — the quiet child is NEVER killed
    // mid-read (it stays live + silent through the read window, so the idle slot is
    // faithfully observable and the broker keeps the session row).
    let child_pid = _broker.session_pid(sid);

    // Hold idle, then read what the broker still believes.
    thread::sleep(Duration::from_secs(2));
    let session_still_listed = controller_by_of(&name, sid).is_some();
    let cby_after_abandon = controller_by_of(&name, sid);
    let driven_after_abandon = driven_by_of(endpoint);

    // Teardown.
    stop.store(true, Ordering::Relaxed);
    if let Some(pid) = child_pid {
        kill_pid(pid);
    }
    let _ = server.join();

    eprintln!(
        "=== W5 A2 CHARACTERIZATION: subscribed={subscribed} \
         driven_after_attach={driven_after_attach:?} cby_attached={cby_attached:?} \
         session_still_listed={session_still_listed} \
         cby_after_abandon={cby_after_abandon:?} driven_after_abandon={driven_after_abandon:?} ==="
    );

    // The CHARACTERIZATION (not a hard pass/fail gate — the steering asked us to
    // REPORT what controller_by reads, and to not burn iterations forcing a flaky
    // A2). We assert only the load-bearing precondition that makes the report
    // meaningful: the remote attach actually became the controller (driven_by
    // latched Some, controller_by read Some(origin)). If that precondition does
    // not hold on this platform/run, the test reports inconclusive via the eprintln
    // above rather than a misleading red.
    if matches!(cby_attached, Some(Some(_))) {
        // [int->REQ-HAZARD-DRIVEN-BY-SELFHEAL]
        // FINDING (A2, CHARACTERIZATION-ONLY on BOTH platforms): the remote attach
        // DID become the controller (slot = Some(origin)). The remote is then
        // abandoned (drop, no clean EOF/detach), closing its loopback QUIC conn (FIN).
        // Whether the broker clears the slot WITHIN the 2s read window is conn-close
        // detection — and it is TIMING-VARIABLE on BOTH platforms: QUIC FIN-detection
        // latency vs the read window is NON-DETERMINISTIC (unix loopback USUALLY but
        // NOT ALWAYS clears <2s — a matrix run that didn't is what bit the prior
        // unix-hard-assert; windows typically needs the ~30s idle-timeout). So this
        // is NOT hard-gated either polarity (a hard cby_after_abandon assert IS the
        // QUIC-timing flake class). We REPORT the observed value. The HARD int for
        // REQ-HAZARD-DRIVEN-BY-SELFHEAL is gap_b (driven_by_selfheal.rs: reconcile
        // offlines AND clears driven_by) + w5_a1; w5_a1/w5_a2 are the characterization
        // arm. The TRUE no-FIN half-open abandon (clears on NEITHER platform at ANY
        // window) stays deferred to REQ-HAZARD-DRIVEN-BY-IDLE-REMOTE-EVICT (D4c
        // presence oracle).
        let cleared = cby_after_abandon == Some(None);
        eprintln!(
            "=== W5 A2 VERDICT (characterization-only): conn-close clear observed \
             in-window? {cleared} — TIMING-VARIABLE on BOTH platforms (QUIC \
             FIN-detection latency vs the 2s window is non-deterministic), so NOT \
             hard-gated here. The no-FIN half-open case is deferred to \
             REQ-HAZARD-DRIVEN-BY-IDLE-REMOTE-EVICT ==="
        );
        // And driven_by remained latched while the broker still thinks it's
        // controlled (the phantom CONTROLLED the picker would render). The seed
        // makes this observable; on a run where the seed/stamp didn't take it is
        // None and we don't over-assert the latch (the controller_by finding above
        // is the load-bearing one).
        eprintln!(
            "=== W5 A2 driven_by latch: after_attach={driven_after_attach:?} \
             after_abandon={driven_after_abandon:?} (Some⇒phantom CONTROLLED \
             persists; the picker renders 'controlled by {{origin}}' forever) ==="
        );
    } else {
        eprintln!(
            "=== W5 A2 INCONCLUSIVE: the remote attach did not become the controller \
             on this run (cby_attached={cby_attached:?}) — A2 not faithfully staged \
             here; rely on the A1 gate + the code-read finding in the report ==="
        );
    }
}

// ── v0.13.0 P0 — REQ-HAZARD-PTY-INPUT-WRITER-WEDGE: the PASTE-WEDGE int gate, the
//    REPRO W1b's int LACKED. W1b relied on ConPTY ABSORBING the write, so it never
//    exercised an INDEFINITE block. THIS gate makes `write_input` GENUINELY PARK on
//    a non-draining harness (forkpty's small kernel input queue on Unix; ConPTY
//    absorbs on Windows — the documented platform-divergence stance the rest of
//    this file uses), then proves the fix: with one input-writer thread per session
//    as the SOLE blocking writer, the parked write parks ONLY its own thread —
//    a CONCURRENT `spt rc` attach still OPENS + RECEIVES output, the operator's next
//    keystroke is still ACCEPTED, and a saturated FIFO DROPS + stamps
//    `input_backpressure` (heal on resume) instead of wedging the broker.
//
// PRE-FIX (the RED this would catch): the paste burst's journaled PtyWrite ran
// `write_input` SYNCHRONOUSLY on the broker dispatch thread → on a forkpty park
// that thread blocked forever → the concurrent attach's subscribe wedged
// ("brain IPC read deadline elapsed", subscribed=false / got_output=false). Real
// broker + real PTY + real rc pump, NO mocks; every wait is behind a watchdog so a
// regression surfaces as a clean FAILURE, never a hang.

/// Read an endpoint perch's `input_backpressure` straight from its info.json under
/// the test SPT_HOME — the SAME perch path the broker's `set_input_backpressure`
/// writes to (`resolve_perch_path(endpoint, Infer)`), so this observes the real
/// operator-visible drop signal the picker / `endpoint list` would render.
fn input_backpressure_of(endpoint: &str) -> Option<bool> {
    let perch = spt_store::perch::resolve_perch_path(endpoint, spt_store::perch::ParentHint::Infer);
    spt_store::info::read_info(&perch).and_then(|i| i.input_backpressure)
}

/// Seed a real perch `info.json` for `endpoint` under the test SPT_HOME so the
/// broker's best-effort `set_input_backpressure` (which no-ops when the record is
/// absent — like `stamp_driven_by`) actually LATCHES the drop signal. The path is
/// the SAME one the broker resolves; without this the stamp silently vanishes and
/// the backpressure leg is unobservable (the W5-A2 rig artifact, reused here).
fn seed_perch(endpoint: &str) {
    let perch = spt_store::perch::resolve_perch_path(endpoint, spt_store::perch::ParentHint::Infer);
    std::fs::create_dir_all(&perch).expect("create perch dir");
    let info = spt_store::info::InfoJson::new(endpoint, "2026-06-19T00:00:00Z", 0, "", "online");
    spt_store::info::write_info(&perch, &info).expect("seed perch info.json");
}

#[test]
fn p0_paste_wedge_parked_write_does_not_starve_attach_or_wedge_broker() {
    init_wedge_home();
    let dir = tempfile::tempdir().expect("tempdir");
    let name = unique_name();
    let endpoint = "p0-paste-wedge-ep";

    // TINY input FIFO so the DROP+INPUT_BACKPRESSURE leg is forced in a handful of
    // records (a parked writer never drains) rather than a few hundred KB of real
    // paste. The bound's PRESENCE (drop-on-full, never block) is the invariant. This
    // env is read at InputWriter::spawn — set it BEFORE the session spawns.
    std::env::set_var("SPT_INPUT_QUEUE_DEPTH", "4");
    // Seed the perch so the input_backpressure stamp lands somewhere observable.
    seed_perch(endpoint);

    let _broker = net_broker(&name, &dir.path().join("p0"));

    // ── A REAL child that IGNORES stdin: its PTY input buffer fills and (on forkpty)
    //    `write_input` PARKS the sole writer thread — the genuine indefinite block
    //    W1b's int never reached. The flood child both ignores stdin AND floods
    //    stdout (so the concurrent attach has output to actually receive). ──
    let mut spawner = connect_retry(&name);
    let sid = spawner
        .spawn_session(flood_spawn_req(endpoint))
        .expect("spawn flood child");
    // The depth override has now been consumed at InputWriter::spawn for THIS
    // session — clear it IMMEDIATELY so no later assert-panic can leak the tiny FIFO
    // into the other tests in this binary (they spawn their own sessions and would
    // mis-drop input at depth 4). A defensive remove also runs at teardown.
    std::env::remove_var("SPT_INPUT_QUEUE_DEPTH");

    // ── The PASTE driver: on its OWN pump connection, pump journaled input
    //    (op_id-carrying send_effect → dispatch_input → apply_once(PtyWrite) =
    //    InputWriter::enqueue). Post-fix each enqueue is non-blocking: it fills the
    //    tiny FIFO, the writer parks on the full PTY input buffer (Unix), and further
    //    enqueues DROP + stamp input_backpressure. The dispatch thread NEVER parks.
    //    Pre-fix the FIRST journaled write parked the dispatch thread itself. ──
    let stop = Arc::new(AtomicBool::new(false));
    let pumped = Arc::new(AtomicU64::new(0));
    let driver_name = name.clone();
    let driver_stop = Arc::clone(&stop);
    let driver_pumped = Arc::clone(&pumped);
    let driver = thread::spawn(move || {
        let mut w = match Brain::cold_start_pump(&driver_name, 1, Duration::from_secs(2)) {
            Ok(b) => b,
            Err(_) => return,
        };
        if w.attach(sid, 0).is_err() {
            return;
        }
        // Paste-shaped: modest records, MANY of them — far more than the depth-4
        // FIFO holds, so saturation (and DROP) is guaranteed once the writer parks.
        let chunk = vec![b'P'; 4 * 1024];
        let mut op = 1u64;
        while !driver_stop.load(Ordering::Relaxed) {
            if w.send_effect(op, &chunk).is_err() {
                break;
            }
            driver_pumped.fetch_add(1, Ordering::Relaxed);
            op += 1;
            // Pace the pump (see the journaled-wedge driver): keep a paste write
            // in-flight without a CPU storm that starves the concurrent attacher.
            let _ = w.read_event_until(Some(Instant::now() + Duration::from_millis(15)));
            // Unix-only (see the journaled-wedge driver): Windows ConPTY absorbs the
            // paste, so there is no CPU storm to pace here.
            #[cfg(unix)]
            std::thread::sleep(Duration::from_millis(5));
        }
    });

    // Let the driver saturate the FIFO and park the writer (Unix) / absorb (Windows).
    thread::sleep(Duration::from_secs(2));

    // ── (3) OPERATOR KEYSTROKE STILL ACCEPTED post-paste: a fresh operator connection
    //    sends a keystroke. The enqueue is non-blocking, so send_input must succeed
    //    immediately even while the writer is parked (the byte may itself DROP under
    //    backpressure — that is fine and operator-visible; the point is the dispatch
    //    path ACCEPTS + returns, never blocks). Pre-fix this wedged on the parked
    //    dispatch thread. ──
    let keystroke_accepted = {
        let mut op = match Brain::cold_start_pump(&name, 1, Duration::from_secs(2)) {
            Ok(b) => b,
            Err(_) => Brain::cold_start(&name, 1).expect("operator connect"),
        };
        op.attach(sid, 0).is_ok() && op.send_input(b"x").is_ok()
    };

    // ── (2) The CONCURRENT `spt rc` attach: a SEPARATE operator dials loopback,
    //    requests a real viewer attach, subscribes, and RECEIVES the flood child's
    //    output while the journaled write is parked. The W1b rig verbatim — the
    //    subscribe reply + real output receipt prove the dispatch serviced this
    //    attach despite the parked write. Bounded by the outer watchdog. ──
    let (result_tx, result_rx) = std::sync::mpsc::channel::<(bool, bool)>();
    let attach_name = name.clone();
    let attacher = thread::spawn(move || {
        // PUMP mode (Split): the got_output loop below uses `read_event_until` with a
        // 250ms slice deadline, which a `Whole` cold_start IGNORES (read_frame blocks
        // forever when no NetStreamData lands) — making `subscribed=false` a
        // measurement artifact rather than a real subscribe failure. Pump honors the
        // slices so the gate reports the true signal (same fix as the a_journaled gate).
        let mut operator = match Brain::cold_start_pump(&attach_name, 1, Duration::from_secs(2)) {
            Ok(b) => b,
            Err(_) => {
                let _ = result_tx.send((false, false));
                return;
            }
        };
        let dialed = match operator.net_dial_loopback() {
            Ok(d) => d,
            Err(_) => {
                let _ = result_tx.send((false, false));
                return;
            }
        };
        let own_origin = dialed.remote_id_hex.clone();
        let stream_b = match request_attach(
            &mut operator,
            dialed.conn_id,
            sid,
            0,
            2,
            AttachIntent::Viewer,
        ) {
            Ok(s) => s,
            Err(_) => {
                let _ = result_tx.send((false, false));
                return;
            }
        };
        let subscribed = operator.net_stream_subscribe(stream_b, 0).is_ok();

        let mut target = connect_retry(&attach_name);
        let (stream_a, origin) = match wait_for_stream(&mut target) {
            Some(s) => s,
            None => {
                let _ = result_tx.send((subscribed, false));
                return;
            }
        };
        assert_eq!(origin, own_origin, "loopback origin is this node's own id");
        let serve_broker = attach_name.clone();
        let server = thread::spawn(move || {
            let _ = serve_attach(&mut target, &serve_broker, stream_a, "p0-paste-wedge-ep", &origin, 0);
        });

        let mut decoder = AttachDecoder::new();
        let mut got_output = false;
        let deadline = Instant::now() + Duration::from_secs(8);
        while Instant::now() < deadline {
            match operator.read_event_until(Some(Instant::now() + Duration::from_millis(250))) {
                Ok(BrokerEvent::NetStreamData { stream_id, bytes, .. }) if stream_id == stream_b => {
                    for rec in decoder.push(&bytes) {
                        if let AttachRecord::Output { data_b64, .. } = rec {
                            let chunk = decode_bytes(&data_b64).unwrap_or_default();
                            if count(&chunk, b"FLOOD") >= 1 {
                                got_output = true;
                            }
                        }
                    }
                    if got_output {
                        break;
                    }
                }
                Ok(_) => continue,
                Err(_) => continue,
            }
        }

        let _ = result_tx.send((subscribed, got_output));
        let _ = operator.net_stream_send(stream_b, &[], None, true);
        let drain_deadline = Instant::now() + Duration::from_secs(12);
        while Instant::now() < drain_deadline {
            match operator.read_event_until(Some(Instant::now() + Duration::from_millis(200))) {
                Ok(BrokerEvent::NetStreamEof { .. }) => break,
                Ok(_) => continue,
                Err(_) => continue,
            }
        }
        let _ = server.join();
    });

    // Watchdog: the hard wall-clock ceiling, env-tunable (attach_gate_watchdog:
    // default 30s tight, CI-generous). A real paste-wedge blocks FOREVER → trips any
    // finite deadline; the knob only grants headroom for a serviced-but-late
    // request_attach ack under CI scheduler starvation (never relaxes the asserts).
    let watchdog = attach_gate_watchdog();
    let recv_t0 = Instant::now();
    let (subscribed, got_output) = result_rx
        .recv_timeout(watchdog)
        .unwrap_or((false, false));
    let recv_elapsed = recv_t0.elapsed();
    // Source-attribution (cheap, load-bearing triage); threshold derived from the
    // CONFIGURED watchdog so the label stays truthful at 30s OR 120s.
    let source = if recv_elapsed >= watchdog.saturating_sub(Duration::from_secs(1)) {
        "WATCHDOG-DEFAULT"
    } else {
        "channel"
    };
    eprintln!(
        "PASTE_FLAKE: MAIN recv -> ({subscribed},{got_output}) after {recv_elapsed:?} (source={source})"
    );

    // ── (4) DROP + INPUT_BACKPRESSURE: while the writer is parked and the driver
    //    keeps pumping, the depth-4 FIFO saturates and enqueues DROP — stamping
    //    input_backpressure=Some(true) on the perch. Poll the perch (the operator-
    //    visible surface) for the rising-edge stamp. On Windows ConPTY ABSORBS the
    //    writes (the writer keeps draining → the FIFO may never saturate), so the
    //    DROP is platform-divergent and CAPTURED there, HARD-asserted on Unix. ──
    let backpressured = {
        let deadline = Instant::now() + Duration::from_secs(6);
        let mut seen = false;
        while Instant::now() < deadline {
            if input_backpressure_of(endpoint) == Some(true) {
                seen = true;
                break;
            }
            thread::sleep(Duration::from_millis(50));
        }
        seen
    };

    // ── HEAL: stop the driver (no more overflow) and DRAIN the child's stdin by
    //    killing+draining is not possible (the child ignores stdin), so instead we
    //    let the writer thread drain the parked FIFO once the child dies: killing the
    //    PTY child closes the master, `write_input` errors/returns, the writer drains
    //    remaining records, and the NEXT accepted enqueue clears the stamp. We model
    //    the heal as: stop overflowing → the broker's own teardown drains. Because a
    //    fully-dead harness never resumes, the deterministic HEAL assertion lives in
    //    the UNIT test (consumer-controlled); here we record the live heal-or-stamp
    //    transition as a diagnostic and assert the load-bearing DROP above. ──
    stop.store(true, Ordering::Relaxed);
    // Bound the teardown joins — see `join_bounded`. This gate shares the wedge
    // teardown shape (driver pump + concurrent attacher); a parked helper here must
    // not ride to the 240s backstop and mask the verdict.
    let _ = join_bounded(driver, Duration::from_secs(8));
    let _ = join_bounded(attacher, Duration::from_secs(8));
    let pumped_n = pumped.load(Ordering::Relaxed);
    let backpressure_after_stop = input_backpressure_of(endpoint);

    if let Some(pid) = session_pid_bounded(&_broker, sid, Duration::from_secs(5)) {
        kill_pid(pid);
    }
    // Clear the process-global depth override so it cannot leak a tiny FIFO into the
    // other tests in this binary (they run serial under --test-threads=1 / nextest
    // process-per-test, but removing it here keeps the env hermetic regardless).
    std::env::remove_var("SPT_INPUT_QUEUE_DEPTH");

    // Teardown hygiene (the cold_start_pump abandoned-reader settle, per W1b).
    thread::sleep(Duration::from_millis(750));

    eprintln!(
        "=== P0 PASTE-WEDGE GATE: pumped={pumped_n} keystroke_accepted={keystroke_accepted} \
         concurrent_attach_subscribed={subscribed} attach_received_output={got_output} \
         backpressured={backpressured} backpressure_after_stop={backpressure_after_stop:?} \
         (fixed = subscribed+got_output+keystroke_accepted true; pre-fix: parked dispatch \
         thread → subscribed=false / no output) ==="
    );

    // [int->REQ-HAZARD-PTY-INPUT-WRITER-WEDGE]
    // CORE non-vacuous gate (RED pre-fix on a forkpty park): a concurrent rc attach
    // must be SERVICED + RECEIVE output while a journaled paste write is in-flight
    // (and, on Unix, parked on the full PTY input buffer). Pre-fix the synchronous
    // write_input on the dispatch thread wedged this ("brain IPC read deadline").
    assert!(
        subscribed,
        "a concurrent `spt rc` attach must be SERVICED while a paste write is parked: \
         the subscribe reply did not arrive within the watchdog — the dispatch thread \
         is blocked on a synchronous write_input (the paste wedge, \
         REQ-HAZARD-PTY-INPUT-WRITER-WEDGE). Post-fix the write is off the dispatch \
         thread on the sole input-writer."
    );
    // The viewer keeps RECEIVING under the flood because an evicted viewer SKIPS
    // TO LIVE (re-subscribe from the ring floor) and a still-subscribed viewer
    // SNAPS the pre-eviction ring-roll forward gap — both viewer-survival paths
    // compose, so the bytes render instead of the attach fataling/stalling.
    // [int->REQ-VIEWER-SKIP-TO-LIVE-ON-EVICT]
    // [int->REQ-HAZARD-VIEWER-RING-ROLL-SNAP]
    assert!(
        got_output,
        "the concurrent attach must actually RECEIVE PTY output from the flooding \
         child (not just liveness) while the paste write is parked — output delivery \
         does not go through the input writer, so receiving bytes proves the dispatch \
         serviced this attach despite the parked write."
    );
    // (3) The operator's own next keystroke is still ACCEPTED (enqueued / returned),
    // never blocked on the parked write.
    assert!(
        keystroke_accepted,
        "the operator's next keystroke after the paste must still be ACCEPTED — \
         send_input enqueues non-blocking and returns even while the writer is parked \
         (the enqueue may itself drop under backpressure; the invariant is that the \
         dispatch path never blocks)."
    );

    // (4) DROP + INPUT_BACKPRESSURE — PLATFORM-DIVERGENT, the same banked stance the
    // W1 park-(b) / W1b gates use: forkpty's small kernel input queue parks the
    // writer so the depth-4 FIFO saturates → DROP stamps the perch (HARD assert on
    // Unix). Windows ConPTY ABSORBS the writes (the writer keeps draining → the FIFO
    // may not saturate), so the stamp is CAPTURED, not asserted (never a false-red);
    // the gravity-linux CI run carries the backpressure assertion.
    #[cfg(unix)]
    assert!(
        backpressured,
        "a saturated input FIFO (parked forkpty writer, driver still pumping) must \
         DROP + stamp input_backpressure=true on the perch (the operator-visible \
         'input dropped, harness not draining' signal) instead of wedging the broker \
         — REQ-HAZARD-PTY-INPUT-WRITER-WEDGE. The HEAL edge is covered \
         deterministically by the broker unit test."
    );
    #[cfg(windows)]
    eprintln!(
        "=== P0 (Windows ConPTY observation, not asserted): backpressured={backpressured} \
         — ConPTY absorbs the write so the FIFO may not saturate; the DROP+backpressure \
         assertion is hard on gravity-linux (forkpty). The three asserts above hold here. ==="
    );
    let _ = backpressured;
}