183
184	/// REQ-SEND-SPT-HOSTED: an inbound message addressed by ENDPOINT ID
185	/// (`KIND_ENDPOINT_INPUT`) is injected into the PTY of the session hosting that
186	/// endpoint — the spt-hosted delivery path a `spt send` rides when there is no
187	/// `api listen` relay. Spawn an echo child LABELLED with an endpoint id; an
188	/// endpoint-keyed inject round-trips through the real PTY and the broker replies
189	/// `delivered=true`. An inject for an UNKNOWN endpoint replies `delivered=false`
190	/// and writes nothing (the caller then falls back to the spool).
191	// [int->REQ-SEND-SPT-HOSTED]
192	fn endpoint_input_test() {
193	    let name = unique_name();
194	    let broker = Broker::bind(&name).expect("bind broker");
195	    let server_broker = Arc::clone(&broker);
196	    let server = thread::spawn(move || {
197	        let handle = server_broker.serve_once().expect("accept brain");
198	        handle.join().expect("handler thread");
199	    });
200
201	    let mut conn = None;
202	    for _ in 0..200 {
203	        match LocalSocketTransport::connect(&name) {
204	            Ok(c) => {
205	                conn = Some(c);
206	                break;
207	            }
208	            Err(_) => thread::sleep(Duration::from_millis(10)),
209	        }
210	    }
211	    let mut conn = conn.expect("connect to broker");
212	    send_hello(&mut conn, Role::Brain).expect("send hello");
213
214	    // Spawn the echo child LABELLED with an endpoint id (the spawn.endpoint the
215	    // broker tracks per session — what KIND_ENDPOINT_INPUT resolves against).
216	    let mut spawn = echo_spawn_req();
217	    spawn.endpoint = "wall-b".to_string();
218	    send(&mut conn, KIND_SPAWN, serde_json::to_value(spawn).unwrap());
219	    let mut out = Vec::<u8>::new();
220	    loop {
221	        let f = read_frame(&mut conn).expect("frame before spawned");
222	        match f.kind.as_str() {
223	            KIND_SPAWNED => break,
224	            KIND_OUTPUT => accumulate_output(&f, &mut out),
225	            _ => {}
226	        }
227	    }
228
229	    // Endpoint-keyed inject (NO session_id — resolved by endpoint): round-trips
230	    // through the real PTY, and the broker acks delivered=true.
231	    send(
232	        &mut conn,
233	        KIND_ENDPOINT_INPUT,
234	        serde_json::to_value(EndpointInputReq {
235	            endpoint: "wall-b".to_string(),
236	            data_b64: encode_bytes(b"ENDPOINT-INJECT-BETA\r"),
237	        })
238	        .unwrap(),
239	    );
240	    let mut delivered: Option<bool> = None;
241	    let mut echoed = false;
242	    loop {
243	        if String::from_utf8_lossy(&out).contains("ENDPOINT-INJECT-BETA") {
244	            echoed = true;
245	        }
246	        if echoed && delivered.is_some() {
247	            break;
248	        }
249	        match read_frame(&mut conn) {
250	            Ok(f) if f.kind == KIND_OUTPUT => accumulate_output(&f, &mut out),
251	            Ok(f) if f.kind == KIND_ENDPOINT_INJECTED => {
252	                delivered = Some(
253	                    serde_json::from_value::<EndpointInjected>(f.payload)
254	                        .unwrap()
255	                        .delivered,
256	                );
257	            }
258	            Ok(_) => {}
259	            Err(_) => break,
260	        }
261	    }
262	    assert_eq!(delivered, Some(true), "ack delivered=true for the hosted endpoint");
263	    assert!(
264	        echoed,
265	        "endpoint-keyed inject must round-trip through the PTY: {:?}",
266	        String::from_utf8_lossy(&out)
267	    );
268
269	    // Inject for an UNKNOWN endpoint: delivered=false, nothing written.
270	    send(
271	        &mut conn,
272	        KIND_ENDPOINT_INPUT,
273	        serde_json::to_value(EndpointInputReq {
274	            endpoint: "no-such-endpoint".to_string(),
275	            data_b64: encode_bytes(b"SHOULD-NOT-APPEAR\r"),
276	        })
277	        .unwrap(),
278	    );
279	    let mut miss: Option<bool> = None;
280	    while miss.is_none() {
281	        match read_frame(&mut conn) {
282	            Ok(f) if f.kind == KIND_ENDPOINT_INJECTED => {
283	                miss = Some(
284	                    serde_json::from_value::<EndpointInjected>(f.payload)
285	                        .unwrap()
286	                        .delivered,
287	                );
288	            }
289	            Ok(f) if f.kind == KIND_OUTPUT => accumulate_output(&f, &mut out),
290	            Ok(_) => {}
291	            Err(_) => break,
292	        }
293	    }
294	    assert_eq!(miss, Some(false), "unknown endpoint acks delivered=false");
295	    assert!(
296	        !String::from_utf8_lossy(&out).contains("SHOULD-NOT-APPEAR"),
297	        "a miss writes nothing to any PTY"
298	    );
299
300	    drop(conn);
301	    server.join().expect("server thread");
302	}

/// REQ-SEND-SPT-HOSTED: an inbound message addressed by ENDPOINT ID
/// (`KIND_ENDPOINT_INPUT`) is injected into the PTY of the session hosting that
/// endpoint — the spt-hosted delivery path a `spt send` rides when there is no
/// `api listen` relay. Spawn an echo child LABELLED with an endpoint id; an
/// endpoint-keyed inject round-trips through the real PTY and the broker replies
/// `delivered=true`. An inject for an UNKNOWN endpoint replies `delivered=false`
/// and writes nothing (the caller then falls back to the spool).
// [int->REQ-SEND-SPT-HOSTED]
fn endpoint_input_test() {
    let name = unique_name();
    let broker = Broker::bind(&name).expect("bind broker");
    let server_broker = Arc::clone(&broker);
    let server = thread::spawn(move || {
        let handle = server_broker.serve_once().expect("accept brain");
        handle.join().expect("handler thread");
    });

    let mut conn = None;
    for _ in 0..200 {
        match LocalSocketTransport::connect(&name) {
            Ok(c) => {
                conn = Some(c);
                break;
            }
            Err(_) => thread::sleep(Duration::from_millis(10)),
        }
    }
    let mut conn = conn.expect("connect to broker");
    send_hello(&mut conn, Role::Brain).expect("send hello");

    // Spawn the echo child LABELLED with an endpoint id (the spawn.endpoint the
    // broker tracks per session — what KIND_ENDPOINT_INPUT resolves against).
    let mut spawn = echo_spawn_req();
    spawn.endpoint = "wall-b".to_string();
    send(&mut conn, KIND_SPAWN, serde_json::to_value(spawn).unwrap());
    let mut out = Vec::<u8>::new();
    loop {
        let f = read_frame(&mut conn).expect("frame before spawned");
        match f.kind.as_str() {
            KIND_SPAWNED => break,
            KIND_OUTPUT => accumulate_output(&f, &mut out),
            _ => {}
        }
    }

    // Endpoint-keyed inject (NO session_id — resolved by endpoint): round-trips
    // through the real PTY, and the broker acks delivered=true.
    send(
        &mut conn,
        KIND_ENDPOINT_INPUT,
        serde_json::to_value(EndpointInputReq {
            endpoint: "wall-b".to_string(),
            data_b64: encode_bytes(b"ENDPOINT-INJECT-BETA\r"),
        })
        .unwrap(),
    );
    let mut delivered: Option<bool> = None;
    let mut echoed = false;
    loop {
        if String::from_utf8_lossy(&out).contains("ENDPOINT-INJECT-BETA") {
            echoed = true;
        }
        if echoed && delivered.is_some() {
            break;
        }
        match read_frame(&mut conn) {
            Ok(f) if f.kind == KIND_OUTPUT => accumulate_output(&f, &mut out),
            Ok(f) if f.kind == KIND_ENDPOINT_INJECTED => {
                delivered = Some(
                    serde_json::from_value::<EndpointInjected>(f.payload)
                        .unwrap()
                        .delivered,
                );
            }
            Ok(_) => {}
            Err(_) => break,
        }
    }
    assert_eq!(delivered, Some(true), "ack delivered=true for the hosted endpoint");
    assert!(
        echoed,
        "endpoint-keyed inject must round-trip through the PTY: {:?}",
        String::from_utf8_lossy(&out)
    );

    // Inject for an UNKNOWN endpoint: delivered=false, nothing written.
    send(
        &mut conn,
        KIND_ENDPOINT_INPUT,
        serde_json::to_value(EndpointInputReq {
            endpoint: "no-such-endpoint".to_string(),
            data_b64: encode_bytes(b"SHOULD-NOT-APPEAR\r"),
        })
        .unwrap(),
    );
    let mut miss: Option<bool> = None;
    while miss.is_none() {
        match read_frame(&mut conn) {
            Ok(f) if f.kind == KIND_ENDPOINT_INJECTED => {
                miss = Some(
                    serde_json::from_value::<EndpointInjected>(f.payload)
                        .unwrap()
                        .delivered,
                );
            }
            Ok(f) if f.kind == KIND_OUTPUT => accumulate_output(&f, &mut out),
            Ok(_) => {}
            Err(_) => break,
        }
    }
    assert_eq!(miss, Some(false), "unknown endpoint acks delivered=false");
    assert!(
        !String::from_utf8_lossy(&out).contains("SHOULD-NOT-APPEAR"),
        "a miss writes nothing to any PTY"
    );

    drop(conn);
    server.join().expect("server thread");
}


This int test (`[int->REQ-SEND-SPT-HOSTED]`) spawns a hosted session with no translation binary and asserts the OLD raw-inject behavior (delivered=true + PTY echo). Under the new contract it must flip to delivered=false + no write (spool). Confirm `echo_spawn_req` sets no translation binary:


43:fn echo_spawn_req() -> SpawnReq {
44-    #[cfg(unix)]
45-    let (program, args) = ("cat".to_string(), Vec::<String>::new());
46-    #[cfg(windows)]
47-    let (program, args) = ("findstr".to_string(), vec![".".to_string()]);
48-    SpawnReq {
49-        program,
50-        args,
51-        rows: 24,
52-        cols: 80,
53-        endpoint: String::new(),
54-        cwd: None,
55-        env: Default::default(),
56:        translation_binary: None,
57-        adapter: String::new(),
58-        install_dir: None,
59-    }
60-}
61-
62-fn send(conn: &mut Stream, kind: &str, payload: serde_json::Value) {

[Showing results with pagination = limit: 20]


Confirmed `translation_binary: None`. Flip the test to the new spool contract (doc + first inject block):


Edit

/// REQ-SEND-SPT-HOSTED: an inbound message addressed by ENDPOINT ID
/// (`KIND_ENDPOINT_INPUT`) is injected into the PTY of the session hosting that
/// endpoint — the spt-hosted delivery path a `spt send` rides when there is no
/// `api listen` relay. Spawn an echo child LABELLED with an endpoint id; an
/// endpoint-keyed inject round-trips through the real PTY and the broker replies
/// `delivered=true`. An inject for an UNKNOWN endpoint replies `delivered=false`
/// and writes nothing (the caller then falls back to the spool).
// [int->REQ-SEND-SPT-HOSTED]
fn endpoint_input_test() {

/// REQ-SEND-SPT-HOSTED / REQ-MSG-IDLE-TRANSLATION-BINARY (ADR-0022 amendment): an
/// inbound message addressed by ENDPOINT ID (`KIND_ENDPOINT_INPUT`) is delivered to
/// an spt-hosted session ONLY through its translation binary. With NO translation
/// binary declared (this echo child), idle delivery has no working binary → the
/// broker acks `delivered=false` and writes NOTHING to the PTY (the caller spools;
/// raw `payload+\r` was removed as a delivery path — it did not submit on a modern
/// TUI, the silent pseudo-delivery that masked F-019). An inject for an UNKNOWN
/// endpoint likewise replies `delivered=false` and writes nothing. (The happy-path
/// delivery — a real binary's choreography reaching the PTY — is the
/// inject_control_wedge.rs int gate, which spawns the xlate_choreo_fixture binary.)
// [int->REQ-SEND-SPT-HOSTED]
// [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
fn endpoint_input_test() {


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

/// REQ-SEND-SPT-HOSTED: an inbound message addressed by ENDPOINT ID
/// (`KIND_ENDPOINT_INPUT`) is injected into the PTY of the session hosting that
/// endpoint — the spt-hosted delivery path a `spt send` rides when there is no
/// `api listen` relay. Spawn an echo child LABELLED with an endpoint id; an
/// endpoint-keyed inject round-trips through the real PTY and the broker replies
/// `delivered=true`. An inject for an UNKNOWN endpoint replies `delivered=false`
/// and writes nothing (the caller then falls back to the spool).
// [int->REQ-SEND-SPT-HOSTED]
fn endpoint_input_test() {

/// REQ-SEND-SPT-HOSTED / REQ-MSG-IDLE-TRANSLATION-BINARY (ADR-0022 amendment): an
/// inbound message addressed by ENDPOINT ID (`KIND_ENDPOINT_INPUT`) is delivered to
/// an spt-hosted session ONLY through its translation binary. With NO translation
/// binary declared (this echo child), idle delivery has no working binary → the
/// broker acks `delivered=false` and writes NOTHING to the PTY (the caller spools;
/// raw `payload+\r` was removed as a delivery path — it did not submit on a modern
/// TUI, the silent pseudo-delivery that masked F-019). An inject for an UNKNOWN
/// endpoint likewise replies `delivered=false` and writes nothing. (The happy-path
/// delivery — a real binary's choreography reaching the PTY — is the
/// inject_control_wedge.rs int gate, which spawns the xlate_choreo_fixture binary.)
// [int->REQ-SEND-SPT-HOSTED]
// [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
fn endpoint_input_test() {

-/// REQ-SEND-SPT-HOSTED: an inbound message addressed by ENDPOINT ID

-/// (`KIND_ENDPOINT_INPUT`) is injected into the PTY of the session hosting that

-/// endpoint — the spt-hosted delivery path a `spt send` rides when there is no

-/// `api listen` relay. Spawn an echo child LABELLED with an endpoint id; an

-/// endpoint-keyed inject round-trips through the real PTY and the broker replies

-/// `delivered=true`. An inject for an UNKNOWN endpoint replies `delivered=false`

-/// and writes nothing (the caller then falls back to the spool).

+/// REQ-SEND-SPT-HOSTED / REQ-MSG-IDLE-TRANSLATION-BINARY (ADR-0022 amendment): an

+/// inbound message addressed by ENDPOINT ID (`KIND_ENDPOINT_INPUT`) is delivered to

+/// an spt-hosted session ONLY through its translation binary. With NO translation

+/// binary declared (this echo child), idle delivery has no working binary → the

+/// broker acks `delivered=false` and writes NOTHING to the PTY (the caller spools;

+/// raw `payload+\r` was removed as a delivery path — it did not submit on a modern

+/// TUI, the silent pseudo-delivery that masked F-019). An inject for an UNKNOWN

+/// endpoint likewise replies `delivered=false` and writes nothing. (The happy-path

+/// delivery — a real binary's choreography reaching the PTY — is the

+/// inject_control_wedge.rs int gate, which spawns the xlate_choreo_fixture binary.)

let broker = Broker::bind(&name).expect("bind broker");


    // Endpoint-keyed inject (NO session_id — resolved by endpoint): round-trips
    // through the real PTY, and the broker acks delivered=true.
    send(
        &mut conn,
        KIND_ENDPOINT_INPUT,
        serde_json::to_value(EndpointInputReq {
            endpoint: "wall-b".to_string(),
            data_b64: encode_bytes(b"ENDPOINT-INJECT-BETA\r"),
        })
        .unwrap(),
    );
    let mut delivered: Option<bool> = None;
    let mut echoed = false;
    loop {
        if String::from_utf8_lossy(&out).contains("ENDPOINT-INJECT-BETA") {
            echoed = true;
        }
        if echoed && delivered.is_some() {
            break;
        }
        match read_frame(&mut conn) {
            Ok(f) if f.kind == KIND_OUTPUT => accumulate_output(&f, &mut out),
            Ok(f) if f.kind == KIND_ENDPOINT_INJECTED => {
                delivered = Some(
                    serde_json::from_value::<EndpointInjected>(f.payload)
                        .unwrap()
                        .delivered,
                );
            }
            Ok(_) => {}
            Err(_) => break,
        }
    }
    assert_eq!(delivered, Some(true), "ack delivered=true for the hosted endpoint");
    assert!(
        echoed,
        "endpoint-keyed inject must round-trip through the PTY: {:?}",
        String::from_utf8_lossy(&out)
    );

    // Endpoint-keyed inject (NO session_id — resolved by endpoint) into a hosted
    // session that declares NO translation binary: idle delivery is
    // translation-binary-ONLY, so there is no working binary → the broker acks
    // delivered=FALSE and writes NOTHING to the PTY (the caller spools).
    send(
        &mut conn,
        KIND_ENDPOINT_INPUT,
        serde_json::to_value(EndpointInputReq {
            endpoint: "wall-b".to_string(),
            data_b64: encode_bytes(b"ENDPOINT-INJECT-BETA\r"),
        })
        .unwrap(),
    );
    let mut delivered: Option<bool> = None;
    while delivered.is_none() {
        match read_frame(&mut conn) {
            Ok(f) if f.kind == KIND_OUTPUT => accumulate_output(&f, &mut out),
            Ok(f) if f.kind == KIND_ENDPOINT_INJECTED => {
                delivered = Some(
                    serde_json::from_value::<EndpointInjected>(f.payload)
                        .unwrap()
                        .delivered,
                );
            }
            Ok(_) => {}
            Err(_) => break,
        }
    }
    assert_eq!(
        delivered,
        Some(false),
        "a hosted session with no translation binary acks delivered=false (spool, not raw inject)"
    );
    assert!(
        !String::from_utf8_lossy(&out).contains("ENDPOINT-INJECT-BETA"),
        "no working translation binary → nothing is written to the PTY: {:?}",
        String::from_utf8_lossy(&out)
    );


    // Endpoint-keyed inject (NO session_id — resolved by endpoint): round-trips
    // through the real PTY, and the broker acks delivered=true.
    send(
        &mut conn,
        KIND_ENDPOINT_INPUT,
        serde_json::to_value(EndpointInputReq {
            endpoint: "wall-b".to_string(),
            data_b64: encode_bytes(b"ENDPOINT-INJECT-BETA\r"),
        })
        .unwrap(),
    );
    let mut delivered: Option<bool> = None;
    let mut echoed = false;
    loop {
        if String::from_utf8_lossy(&out).contains("ENDPOINT-INJECT-BETA") {
            echoed = true;
        }
        if echoed && delivered.is_some() {
            break;
        }
        match read_frame(&mut conn) {
            Ok(f) if f.kind == KIND_OUTPUT => accumulate_output(&f, &mut out),
            Ok(f) if f.kind == KIND_ENDPOINT_INJECTED => {
                delivered = Some(
                    serde_json::from_value::<EndpointInjected>(f.payload)
                        .unwrap()
                        .delivered,
                );
            }
            Ok(_) => {}
            Err(_) => break,
        }
    }
    assert_eq!(delivered, Some(true), "ack delivered=true for the hosted endpoint");
    assert!(
        echoed,
        "endpoint-keyed inject must round-trip through the PTY: {:?}",
        String::from_utf8_lossy(&out)
    );

    // Endpoint-keyed inject (NO session_id — resolved by endpoint) into a hosted
    // session that declares NO translation binary: idle delivery is
    // translation-binary-ONLY, so there is no working binary → the broker acks
    // delivered=FALSE and writes NOTHING to the PTY (the caller spools).
    send(
        &mut conn,
        KIND_ENDPOINT_INPUT,
        serde_json::to_value(EndpointInputReq {
            endpoint: "wall-b".to_string(),
            data_b64: encode_bytes(b"ENDPOINT-INJECT-BETA\r"),
        })
        .unwrap(),
    );
    let mut delivered: Option<bool> = None;
    while delivered.is_none() {
        match read_frame(&mut conn) {
            Ok(f) if f.kind == KIND_OUTPUT => accumulate_output(&f, &mut out),
            Ok(f) if f.kind == KIND_ENDPOINT_INJECTED => {
                delivered = Some(
                    serde_json::from_value::<EndpointInjected>(f.payload)
                        .unwrap()
                        .delivered,
                );
            }
            Ok(_) => {}
            Err(_) => break,
        }
    }
    assert_eq!(
        delivered,
        Some(false),
        "a hosted session with no translation binary acks delivered=false (spool, not raw inject)"
    );
    assert!(
        !String::from_utf8_lossy(&out).contains("ENDPOINT-INJECT-BETA"),
        "no working translation binary → nothing is written to the PTY: {:?}",
        String::from_utf8_lossy(&out)
    );

-    // Endpoint-keyed inject (NO session_id — resolved by endpoint): round-trips

-    // through the real PTY, and the broker acks delivered=true.

+    // Endpoint-keyed inject (NO session_id — resolved by endpoint) into a hosted

+    // session that declares NO translation binary: idle delivery is

+    // translation-binary-ONLY, so there is no working binary → the broker acks

+    // delivered=FALSE and writes NOTHING to the PTY (the caller spools).

-        if String::from_utf8_lossy(&out).contains("ENDPOINT-INJECT-BETA") {

-        if echoed && delivered.is_some() {

-    assert_eq!(delivered, Some(true), "ack delivered=true for the hosted endpoint");

+        "a hosted session with no translation binary acks delivered=false (spool, not raw inject)"

-        "endpoint-keyed inject must round-trip through the PTY: {:?}",

+        !String::from_utf8_lossy(&out).contains("ENDPOINT-INJECT-BETA"),

+        "no working translation binary → nothing is written to the PTY: {:?}",


Now the int gate `inject_control_wedge.rs` — g2 asserts post-fault "raw-inject fallback". Assess its raw-inject assertions:


15://! `KIND_SESSIONS` enumeration, which reads each log's `delivered_through`)
22://! the writer advances `delivered_through`). The drain hands each chunk off with a
32://! PTY child. Under the default `cargo test` harness — N tests as parallel
38://!   - `cargo test --test inject_control_wedge -- --test-threads=1`  (single-threaded fallback).
77:/// hard wall-clock ceiling on the attacher's `result_rx.recv_timeout`. DEFAULT 30s —
79:/// gate keeps catching regressions locally / by default. CI exports
103:/// (brain.rs:311-323, :569). DEFAULT 2s — tight locally, so a REAL wedge (an ack that
173:/// case (a real TUI redraw burst). Cross-OS, same shape as the broker B1 test's
193:        env: Default::default(),
227:        env: Default::default(),
321:    // session's log (`delivered_through`) under each log lock — PRE-FIX it hung on
347:         (which reads each log's delivered_through under the log lock) must still \
348:         answer because the controller write is delivered OFF the log lock on a \
742:                            let chunk = decode_bytes(&data_b64).unwrap_or_default();
783:    // (attach_gate_watchdog: default 30s tight, CI-generous): a real wedge blocks
793:    // reported; `WATCHDOG-DEFAULT` = the gate's elastic bound (request_attach's
797:        "WATCHDOG-DEFAULT"
903://     broker's commit-deadline FAULT. It appends every stdin LINE it receives to
945:        env: Default::default(),
1035:/// Deliver an inbound `<EVENT>` to a hosted endpoint via a raw `KIND_ENDPOINT_INPUT`
1037:/// helper), and return whether the broker acked `delivered=true` within `deadline`.
1068:                    // The reply carries `delivered`; surface it.
1069:                    let delivered = f
1071:                        .get("delivered")
1074:                    let _ = tx.send(delivered);
1175:    //    A live (non-faulted) translation binary OWNS the choreography → the broker
1179:    let delivered = deliver_endpoint_event(&name, endpoint, envelope, Duration::from_secs(8));
1209:        "=== W2 G1 CHOREO GATE: delivered={delivered} payload_reached_pty={payload_reached} \
1216:        delivered,
1261:fn g2_no_commit_deadline_faults_binary_and_does_not_wedge_controller_input() {
1266:    // (floor releases → buffered input flushes → binary faults) is observed fast.
1281:    let delivered = deliver_endpoint_event(&name, endpoint, envelope, Duration::from_secs(5));
1295:    // The session stays serviceable after the FAULT.
1299:    // After the binary faulted, a SUBSEQUENT inbound delivery falls back to RAW
1301:    // drives the choreography). The raw envelope ends in `\r` so the echo child
1303:    let raw_envelope = b"<EVENT>RAW_FALLBACK_MARKER</EVENT>\r";
1304:    let delivered2 = deliver_endpoint_event(&name, endpoint, raw_envelope, Duration::from_secs(5));
1305:    let raw_fallback_reached =
1306:        output_contains_within(&name, sid, b"RAW_FALLBACK_MARKER", Duration::from_secs(8));
1313:        "=== W2 G2 NO-COMMIT FAULT GATE: delivered={delivered} op_flushed={op_flushed} \
1314:         sessions_answered={sessions_answered} delivered2={delivered2} \
1315:         raw_fallback_reached={raw_fallback_reached} \
1316:         (op_flushed=true → controller input never wedged; raw_fallback → binary faulted) ==="
1320:    assert!(delivered, "the no-commit event must still be accepted by the broker");
1329:        "the session must stay serviceable after the binary faults"
1332:        raw_fallback_reached,
1333:        "after the FAULT a subsequent inbound delivery must fall back to RAW inject — \
1334:         the raw `<EVENT>` envelope must land on the PTY directly (the faulted binary \
1372:    let bin_stdin = std::fs::read(&bin_stdin_log).unwrap_or_default();
2045:                            let chunk = decode_bytes(&data_b64).unwrap_or_default();

[Showing results with pagination = limit: 50]


The g2 int gate (line 1261) asserts post-fault **raw-inject fallback** reaches the PTY — the exact removed behavior. Must flip to: post-fault inbound spools (delivered2=false, marker does NOT reach PTY). Read g2's tail + the fixture's raw_fallback:


1261	fn g2_no_commit_deadline_faults_binary_and_does_not_wedge_controller_input() {
1262	    init_wedge_home();
1263	    let dir = tempfile::tempdir().expect("tempdir");
1264	    // The binary emits the payload + a key but NEVER `{commit}` → the broker's
1265	    // commit deadline must fire. Shrink the deadline so the structural outcome
1266	    // (floor releases → buffered input flushes → binary faults) is observed fast.
1267	    std::env::set_var("XLATE_FIXTURE_MODE", "nocommit");
1268	    std::env::set_var("SPT_INJECT_COMMIT_DEADLINE_MS", "400");
1269	    std::env::remove_var("XLATE_FIXTURE_STDIN_LOG");
1270
1271	    let name = unique_name();
1272	    let endpoint = "xlate-g2-ep";
1273	    let (broker, sid, mut controller) =
1274	        spawn_xlate_session(&name, &dir.path().join("g2"), endpoint);
1275	    // Bind the controller brain to the session so its keystrokes have a target.
1276	    controller.attach(sid, 0).expect("controller attach");
1277
1278	    // Deliver an event whose binary never commits → the floor OPENS, buffers
1279	    // operator input, and the worker hits the 400ms deadline.
1280	    let envelope = br#"<EVENT type="message" from="peer">no-commit event</EVENT>"#;
1281	    let delivered = deliver_endpoint_event(&name, endpoint, envelope, Duration::from_secs(5));
1282
1283	    // While the floor is (briefly) held, the operator types — Enter-terminated so the
1284	    // echo child flushes the line. After the 400ms deadline the floor must RELEASE and
1285	    // the buffered keystrokes flush to the PTY (then echo back over the ring). Send a
1286	    // few times (some before, some after the deadline) so the flush is exercised; then
1287	    // observe the marker echo — proof the controller input did NOT wedge.
1288	    for _ in 0..4 {
1289	        let _ = controller.send_input(b"OPERATOR_KEYS_FLUSHED\r");
1290	        let _ = controller.read_event_until(Some(Instant::now() + Duration::from_millis(150)));
1291	    }
1292	    let op_flushed =
1293	        output_contains_within(&name, sid, b"OPERATOR_KEYS_FLUSHED", Duration::from_secs(8));
1294
1295	    // The session stays serviceable after the FAULT.
1296	    let sessions_answered =
1297	        probe(&name, KIND_SESSIONS, KIND_SESSIONS_REPLY, Duration::from_secs(5));
1298
1299	    // After the binary faulted, a SUBSEQUENT inbound delivery falls back to RAW
1300	    // inject: the whole envelope bytes land on the PTY directly (the binary no longer
1301	    // drives the choreography). The raw envelope ends in `\r` so the echo child
1302	    // flushes the echoed line; assert the marker reaches the PTY via the ring.
1303	    let raw_envelope = b"<EVENT>RAW_FALLBACK_MARKER</EVENT>\r";
1304	    let delivered2 = deliver_endpoint_event(&name, endpoint, raw_envelope, Duration::from_secs(5));
1305	    let raw_fallback_reached =
1306	        output_contains_within(&name, sid, b"RAW_FALLBACK_MARKER", Duration::from_secs(8));
1307
1308	    if let Some(pid) = broker.session_pid(sid) {
1309	        kill_pid(pid);
1310	    }
1311
1312	    eprintln!(
1313	        "=== W2 G2 NO-COMMIT FAULT GATE: delivered={delivered} op_flushed={op_flushed} \
1314	         sessions_answered={sessions_answered} delivered2={delivered2} \
1315	         raw_fallback_reached={raw_fallback_reached} \
1316	         (op_flushed=true → controller input never wedged; raw_fallback → binary faulted) ==="
1317	    );
1318
1319	    // [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
1320	    assert!(delivered, "the no-commit event must still be accepted by the broker");
1321	    assert!(
1322	        op_flushed,
1323	        "after the commit deadline the floor must RELEASE and buffered operator \
1324	         keystrokes must flush to the PTY — the controller's input must NOT wedge \
1325	         (the mandatory bounded-buffer guard; doyle non-negotiable = never park forever)"
1326	    );
1327	    assert!(
1328	        sessions_answered,
1329	        "the session must stay serviceable after the binary faults"
1330	    );
1331	    assert!(
1332	        raw_fallback_reached,
1333	        "after the FAULT a subsequent inbound delivery must fall back to RAW inject — \
1334	         the raw `<EVENT>` envelope must land on the PTY directly (the faulted binary \
1335	         no longer drives the choreography)"
1336	    );
1337	}
1338
1339	#[test]
1340	fn g3_content_free_ping_never_duplicates_operator_keystrokes_into_binary() {
1341	    init_wedge_home();
1342	    let dir = tempfile::tempdir().expect("tempdir");
1343	    let bin_stdin_log = dir.path().join("xlate_stdin.log");
1344	    // The translation binary records EVERY stdin line it receives here.
1345	    std::env::set_var("XLATE_FIXTURE_STDIN_LOG", &bin_stdin_log);
1346	    std::env::set_var("XLATE_FIXTURE_MODE", "choreo");
1347	    std::env::remove_var("SPT_INJECT_COMMIT_DEADLINE_MS");
1348
1349	    let name = unique_name();
1350	    let endpoint = "xlate-g3-ep";

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";


g2's wedge-proof (delivered, op_flushed, sessions_answered) stays; only the post-fault tail inverts. Flip raw-inject → spool:


    // 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)"
    );
}

    // After the binary faulted, a SUBSEQUENT inbound delivery has NO working
    // translation binary → it SPOOLS: the broker acks delivered=false and writes
    // NOTHING to the PTY (ADR-0022 amendment — raw inject was REMOVED as a delivery
    // path; a faulted binary no longer degrades to a raw `payload+\r` pseudo-write
    // that does not submit on a modern TUI). The marker must therefore NOT appear on
    // the ring. The envelope ends in `\r` only to match the old shape; nothing is
    // written so the echo child never sees it.
    let raw_envelope = b"<EVENT>SPOOL_NOT_INJECTED_MARKER</EVENT>\r";
    let delivered2 = deliver_endpoint_event(&name, endpoint, raw_envelope, Duration::from_secs(5));
    let marker_reached_pty =
        output_contains_within(&name, sid, b"SPOOL_NOT_INJECTED_MARKER", Duration::from_secs(3));

    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} \
         marker_reached_pty={marker_reached_pty} \
         (op_flushed=true → controller input never wedged; delivered2=false + \
         !marker_reached_pty → faulted binary spools, never raw-injects) ==="
    );

    // [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!(
        !delivered2,
        "after the FAULT a subsequent inbound delivery must SPOOL (delivered=false), \
         not raw-inject — idle delivery is translation-binary-only (ADR-0022 amendment)"
    );
    assert!(
        !marker_reached_pty,
        "a faulted binary no longer raw-injects: the raw `<EVENT>` envelope must NOT \
         land on the PTY (it spools, poll-fed, never a non-submitting PTY pseudo-write)"
    );
}


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

    // 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)"
    );
}

    // After the binary faulted, a SUBSEQUENT inbound delivery has NO working
    // translation binary → it SPOOLS: the broker acks delivered=false and writes
    // NOTHING to the PTY (ADR-0022 amendment — raw inject was REMOVED as a delivery
    // path; a faulted binary no longer degrades to a raw `payload+\r` pseudo-write
    // that does not submit on a modern TUI). The marker must therefore NOT appear on
    // the ring. The envelope ends in `\r` only to match the old shape; nothing is
    // written so the echo child never sees it.
    let raw_envelope = b"<EVENT>SPOOL_NOT_INJECTED_MARKER</EVENT>\r";
    let delivered2 = deliver_endpoint_event(&name, endpoint, raw_envelope, Duration::from_secs(5));
    let marker_reached_pty =
        output_contains_within(&name, sid, b"SPOOL_NOT_INJECTED_MARKER", Duration::from_secs(3));

    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} \
         marker_reached_pty={marker_reached_pty} \
         (op_flushed=true → controller input never wedged; delivered2=false + \
         !marker_reached_pty → faulted binary spools, never raw-injects) ==="
    );

    // [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!(
        !delivered2,
        "after the FAULT a subsequent inbound delivery must SPOOL (delivered=false), \
         not raw-inject — idle delivery is translation-binary-only (ADR-0022 amendment)"
    );
    assert!(
        !marker_reached_pty,
        "a faulted binary no longer raw-injects: the raw `<EVENT>` envelope must NOT \
         land on the PTY (it spools, poll-fed, never a non-submitting PTY pseudo-write)"
    );
}

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";

+    // After the binary faulted, a SUBSEQUENT inbound delivery has NO working

+    // translation binary → it SPOOLS: the broker acks delivered=false and writes

+    // NOTHING to the PTY (ADR-0022 amendment — raw inject was REMOVED as a delivery

+    // path; a faulted binary no longer degrades to a raw `payload+\r` pseudo-write

+    // that does not submit on a modern TUI). The marker must therefore NOT appear on

+    // the ring. The envelope ends in `\r` only to match the old shape; nothing is

+    // written so the echo child never sees it.

+    let raw_envelope = b"<EVENT>SPOOL_NOT_INJECTED_MARKER</EVENT>\r";

-        output_contains_within(&name, sid, b"RAW_FALLBACK_MARKER", Duration::from_secs(8));

+        output_contains_within(&name, sid, b"SPOOL_NOT_INJECTED_MARKER", Duration::from_secs(3));

-         raw_fallback_reached={raw_fallback_reached} \

-         (op_flushed=true → controller input never wedged; raw_fallback → binary faulted) ==="

+         marker_reached_pty={marker_reached_pty} \

+         (op_flushed=true → controller input never wedged; delivered2=false + \

+         !marker_reached_pty → faulted binary spools, never raw-injects) ==="

-        "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)"

+        "after the FAULT a subsequent inbound delivery must SPOOL (delivered=false), \

+         not raw-inject — idle delivery is translation-binary-only (ADR-0022 amendment)"

+        "a faulted binary no longer raw-injects: the raw `<EVENT>` envelope must NOT \

+         land on the PTY (it spools, poll-fed, never a non-submitting PTY pseudo-write)"


Now the fixture comments (xlate_choreo_fixture.rs:78/84). Read that region:


60	            Err(_) => continue,
61	        };
62	        if v.get("type").and_then(|t| t.as_str()) != Some("event") {
63	            continue;
64	        }
65
66	        // Emit the choreography, flushing each line so the broker's line-reader
67	        // applies it promptly (the delays are part of the sequence the broker
68	        // honors, not a wall-clock the test asserts on).
69	        emit(&mut out, r#"{"key":"ctrl+s"}"#);
70	        emit(&mut out, r#"{"delay_ms":50}"#);
71	        emit(&mut out, &format!(r#"{{"text":"{PAYLOAD}"}}"#));
72	        emit(&mut out, r#"{"key":"enter"}"#);
73
74	        if mode == "nocommit" {
75	            // FAULT path: the payload + a key landed, but we deliberately NEVER
76	            // emit `{"commit":true}`. The broker's inject worker must hit its
77	            // commit deadline, flush the buffered controller input, release the
78	            // floor, and FAULT this binary (revert to raw inject).
79	            //
80	            // RESTORE FLOW (XON / `ctrl+q` = 0x11) BEFORE the early return: the
81	            // `ctrl+s` (XOFF, 0x13) emitted above PAUSED terminal output. On a
82	            // forkpty PTY (IXON honored) that pause STRANDS every subsequent echo —
83	            // the deadline-flushed operator keystrokes (op_flushed) AND the
84	            // post-fault raw inject (raw_fallback), both observed via the child's
85	            // echo, never reach the output ring → the g2 reads time out
86	            // (forkpty-ONLY; Windows ConPTY ignores XOFF, so g2 passed there and the
87	            // strand stayed hidden until the forkpty matrix). The happy path already
88	            // emits this XON before `{commit}`; an adapter that ABORTS mid-sequence
89	            // must restore flow just the same. We still NEVER commit, so the
90	            // commit-deadline FAULT path is exercised exactly as before.
91	            emit(&mut out, r#"{"key":"ctrl+q"}"#);
92	            continue;
93	        }
94
95	        emit(&mut out, r#"{"delay_ms":50}"#);
96	        emit(&mut out, r#"{"key":"ctrl+s"}"#);
97	        // XON (`ctrl+q` = 0x11): resume the terminal output flow the `ctrl+s` (XOFF)
98	        // chord paused, so the payload's echo flushes deterministically on a ConPTY
99	        // (the int test observes byte-receipt via that echo). A real stash/restore

            Err(_) => continue,
        };
        if v.get("type").and_then(|t| t.as_str()) != Some("event") {
            continue;
        }

        // Emit the choreography, flushing each line so the broker's line-reader
        // applies it promptly (the delays are part of the sequence the broker
        // honors, not a wall-clock the test asserts on).
        emit(&mut out, r#"{"key":"ctrl+s"}"#);
        emit(&mut out, r#"{"delay_ms":50}"#);
        emit(&mut out, &format!(r#"{{"text":"{PAYLOAD}"}}"#));
        emit(&mut out, r#"{"key":"enter"}"#);

        if mode == "nocommit" {
            // FAULT path: the payload + a key landed, but we deliberately NEVER
            // emit `{"commit":true}`. The broker's inject worker must hit its
            // commit deadline, flush the buffered controller input, release the
            // floor, and FAULT this binary (revert to raw inject).
            //
            // RESTORE FLOW (XON / `ctrl+q` = 0x11) BEFORE the early return: the
            // `ctrl+s` (XOFF, 0x13) emitted above PAUSED terminal output. On a
            // forkpty PTY (IXON honored) that pause STRANDS every subsequent echo —
            // the deadline-flushed operator keystrokes (op_flushed) AND the
            // post-fault raw inject (raw_fallback), both observed via the child's
            // echo, never reach the output ring → the g2 reads time out
            // (forkpty-ONLY; Windows ConPTY ignores XOFF, so g2 passed there and the
            // strand stayed hidden until the forkpty matrix). The happy path already
            // emits this XON before `{commit}`; an adapter that ABORTS mid-sequence
            // must restore flow just the same. We still NEVER commit, so the
            // commit-deadline FAULT path is exercised exactly as before.
            emit(&mut out, r#"{"key":"ctrl+q"}"#);
            continue;
        }

        emit(&mut out, r#"{"delay_ms":50}"#);
        emit(&mut out, r#"{"key":"ctrl+s"}"#);
        // XON (`ctrl+q` = 0x11): resume the terminal output flow the `ctrl+s` (XOFF)
        // chord paused, so the payload's echo flushes deterministically on a ConPTY
        // (the int test observes byte-receipt via that echo). A real stash/restore


Fixture comments describe the OLD daemon behavior — the XON restore stays (needed for op_flushed) but the raw_fallback references are stale. Reword:


            // FAULT path: the payload + a key landed, but we deliberately NEVER
            // emit `{"commit":true}`. The broker's inject worker must hit its
            // commit deadline, flush the buffered controller input, release the
            // floor, and FAULT this binary (revert to raw inject).
            //
            // RESTORE FLOW (XON / `ctrl+q` = 0x11) BEFORE the early return: the
            // `ctrl+s` (XOFF, 0x13) emitted above PAUSED terminal output. On a
            // forkpty PTY (IXON honored) that pause STRANDS every subsequent echo —
            // the deadline-flushed operator keystrokes (op_flushed) AND the
            // post-fault raw inject (raw_fallback), both observed via the child's
            // echo, never reach the output ring → the g2 reads time out
            // (forkpty-ONLY; Windows ConPTY ignores XOFF, so g2 passed there and the
            // strand stayed hidden until the forkpty matrix). The happy path already

            // FAULT path: the payload + a key landed, but we deliberately NEVER
            // emit `{"commit":true}`. The broker's inject worker must hit its
            // commit deadline, flush the buffered controller input, release the
            // floor, and FAULT this binary (after which idle inbound SPOOLS — raw
            // inject was removed as a delivery path, ADR-0022 amendment).
            //
            // RESTORE FLOW (XON / `ctrl+q` = 0x11) BEFORE the early return: the
            // `ctrl+s` (XOFF, 0x13) emitted above PAUSED terminal output. On a
            // forkpty PTY (IXON honored) that pause STRANDS every subsequent echo —
            // the deadline-flushed operator keystrokes (op_flushed), observed via the
            // child's echo, never reach the output ring → the g2 op_flushed read
            // times out (forkpty-ONLY; Windows ConPTY ignores XOFF, so g2 passed
            // there and the strand stayed hidden until the forkpty matrix). The happy path already


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

            // FAULT path: the payload + a key landed, but we deliberately NEVER
            // emit `{"commit":true}`. The broker's inject worker must hit its
            // commit deadline, flush the buffered controller input, release the
            // floor, and FAULT this binary (after which idle inbound SPOOLS — raw
            // inject was removed as a delivery path, ADR-0022 amendment).
            //
            // RESTORE FLOW (XON / `ctrl+q` = 0x11) BEFORE the early return: the
            // `ctrl+s` (XOFF, 0x13) emitted above PAUSED terminal output. On a
            // forkpty PTY (IXON honored) that pause STRANDS every subsequent echo —
            // the deadline-flushed operator keystrokes (op_flushed), observed via the
            // child's echo, never reach the output ring → the g2 op_flushed read
            // times out (forkpty-ONLY; Windows ConPTY ignores XOFF, so g2 passed
            // there and the strand stayed hidden until the forkpty matrix). The happy path already

//! W2 Layer G integration fixture: a REAL ADR-0022 translation binary —
//! a pure stdin→stdout JSON-lines filter spt-core lifecycle-manages. Used by
//! `tests/inject_control_wedge.rs` (referenced via
//! `env!("CARGO_BIN_EXE_xlate_choreo_fixture")`). NOT a production binary.
//!
//! Protocol (spt-core → here, one JSON object per line on stdin):
//!   `{"type":"init",…}`  — identity; noted, never drives output.
//!   `{"type":"input"}`   — a CONTENT-FREE operator-activity ping; ignored.
//!   `{"type":"event","envelope":"…"}` — an inbound `<EVENT>`; we respond with
//!                          the CC stash/restore choreography.
//!
//! On an `event` we emit (here → spt-core, one JSON object per line on stdout,
//! flushing each so the broker's reader sees them promptly):
//!   `{"key":"ctrl+s"}` `{"delay_ms":50}` `{"text":"XLATE_OK"}` `{"key":"enter"}`
//!   `{"delay_ms":50}` `{"key":"ctrl+s"}` then `{"commit":true}`.
//!
//! Modes (env `XLATE_FIXTURE_MODE`, read ONCE at start; default `choreo`):
//!   - `choreo`   — the full sequence ENDING in `{"commit":true}` (happy path).
//!   - `nocommit` — emit the payload text + a key but NEVER `{"commit":true}`, so
//!     the broker's commit-deadline FAULT path is exercised.
//!
//! Privacy assertion support (doyle gate #1): every stdin line we receive is
//! appended verbatim to the file named by env `XLATE_FIXTURE_STDIN_LOG` (when
//! set). The int test reads that file and asserts NO operator keystroke payload
//! (e.g. the controller's typed bytes) ever appears — only `init` / `event` /
//! content-free `input` lines do. The binary never sees PTY keystroke content.

use std::fs::OpenOptions;
use std::io::{self, BufRead, Write};

/// The fixed, recognizable payload token the choreography types into the PTY.
const PAYLOAD: &str = "XLATE_OK";

fn main() {
    let mode = std::env::var("XLATE_FIXTURE_MODE").unwrap_or_else(|_| "choreo".to_string());
    let stdin_log = std::env::var("XLATE_FIXTURE_STDIN_LOG").ok();

    let stdin = io::stdin();
    let mut out = io::stdout();

    for line in stdin.lock().lines() {
        let Ok(line) = line else { break }; // stdin closed (EOF) → exit (no-zombie).
        let trimmed = line.trim();
        if trimmed.is_empty() {
            continue;
        }

        // Record EVERY received stdin line for the privacy (content-free ping)
        // assertion. Best-effort: a log failure never changes our behavior.
        if let Some(path) = &stdin_log {
            if let Ok(mut f) = OpenOptions::new().create(true).append(true).open(path) {
                let _ = writeln!(f, "{trimmed}");
            }
        }

        // Only `{"type":"event",…}` drives a response. `init` and the
        // content-free `input` ping are noted (logged above) and ignored.
        let v: serde_json::Value = match serde_json::from_str(trimmed) {
            Ok(v) => v,
            Err(_) => continue,
        };
        if v.get("type").and_then(|t| t.as_str()) != Some("event") {
            continue;
        }

        // Emit the choreography, flushing each line so the broker's line-reader
        // applies it promptly (the delays are part of the sequence the broker
        // honors, not a wall-clock the test asserts on).
        emit(&mut out, r#"{"key":"ctrl+s"}"#);
        emit(&mut out, r#"{"delay_ms":50}"#);
        emit(&mut out, &format!(r#"{{"text":"{PAYLOAD}"}}"#));
        emit(&mut out, r#"{"key":"enter"}"#);

        if mode == "nocommit" {
            // FAULT path: the payload + a key landed, but we deliberately NEVER
            // emit `{"commit":true}`. The broker's inject worker must hit its
            // commit deadline, flush the buffered controller input, release the
            // floor, and FAULT this binary (revert to raw inject).
            //
            // RESTORE FLOW (XON / `ctrl+q` = 0x11) BEFORE the early return: the
            // `ctrl+s` (XOFF, 0x13) emitted above PAUSED terminal output. On a
            // forkpty PTY (IXON honored) that pause STRANDS every subsequent echo —
            // the deadline-flushed operator keystrokes (op_flushed) AND the
            // post-fault raw inject (raw_fallback), both observed via the child's
            // echo, never reach the output ring → the g2 reads time out
            // (forkpty-ONLY; Windows ConPTY ignores XOFF, so g2 passed there and the
            // strand stayed hidden until the forkpty matrix). The happy path already
            // emits this XON before `{commit}`; an adapter that ABORTS mid-sequence
            // must restore flow just the same. We still NEVER commit, so the
            // commit-deadline FAULT path is exercised exactly as before.
            emit(&mut out, r#"{"key":"ctrl+q"}"#);
            continue;
        }

        emit(&mut out, r#"{"delay_ms":50}"#);
        emit(&mut out, r#"{"key":"ctrl+s"}"#);
        // XON (`ctrl+q` = 0x11): resume the terminal output flow the `ctrl+s` (XOFF)
        // chord paused, so the payload's echo flushes deterministically on a ConPTY
        // (the int test observes byte-receipt via that echo). A real stash/restore
        // adapter restores flow at the end of its sequence just the same; this keeps
        // the `ctrl+s` chord (and its real 0x13 mapping + floor exercise) intact while
        // making the payload's arrival observable, per the test-specialist's latitude.
        emit(&mut out, r#"{"key":"ctrl+q"}"#);
        emit(&mut out, r#"{"commit":true}"#);
    }
}

/// Write one JSON-lines command and flush so the broker sees it immediately.
fn emit(out: &mut io::Stdout, line: &str) {
    let _ = writeln!(out, "{line}");
    let _ = out.flush();
}

-            // floor, and FAULT this binary (revert to raw inject).

+            // floor, and FAULT this binary (after which idle inbound SPOOLS — raw

+            // inject was removed as a delivery path, ADR-0022 amendment).

-            // the deadline-flushed operator keystrokes (op_flushed) AND the

-            // post-fault raw inject (raw_fallback), both observed via the child's

-            // echo, never reach the output ring → the g2 reads time out

-            // (forkpty-ONLY; Windows ConPTY ignores XOFF, so g2 passed there and the

-            // strand stayed hidden until the forkpty matrix). The happy path already

+            // the deadline-flushed operator keystrokes (op_flushed), observed via the

+            // child's echo, never reach the output ring → the g2 op_flushed read

+            // times out (forkpty-ONLY; Windows ConPTY ignores XOFF, so g2 passed

+            // there and the strand stayed hidden until the forkpty matrix). The happy path already


Check remaining test surfaces (wanmsg.rs + any other delivered=true on no-binary path) and cli.rs unit tests:


crates\spt-runtime\src\manifest.rs:59:    /// v0.11.0 degenerate raw-inject / spool).
crates\spt-runtime\manifest.schema.json:60:[Omitted long matching line]
crates\spt-daemon\src\broker.rs:154:/// respawn → idle inbound then SPOOLS, never raw-injected), and never re-opens. A wedged or
crates\spt-daemon\src\broker.rs:829:/// has no idle PTY delivery and inbound SPOOLS (ADR-0022 amendment — raw inject
crates\spt-daemon\src\broker.rs:838:/// the session's idle inbound SPOOLS (never raw-injected) and pinging stops.
crates\spt-daemon\src\broker.rs:849:    /// session's idle inbound then SPOOLS (never raw-injected) and `dispatch_input`
crates\spt-daemon\src\broker.rs:1030:/// inbound then SPOOLS, never raw-injected). The loop ends when `event_tx` is dropped
crates\spt-daemon\src\broker.rs:1182:/// reap the child. Never respawns — inbound spools (poll-fed), never raw-injected,
crates\spt-daemon\src\broker.rs:1686:        // (logged, `None` → idle inbound spools, never raw-injected) rather than
crates\spt-daemon\src\broker.rs:1884:    /// IDLE/DIRECT path only (REQ-SEND-SPT-HOSTED, MVP per CONTEXT:188): a write
crates\spt-daemon\src\broker.rs:1925:                        // worker receiver dropped → SPOOL (below), never raw inject.
crates\spt-daemon\tests\inject_control_wedge.rs:1037:/// helper), and return whether the broker acked `delivered=true` within `deadline`.
crates\spt-daemon\tests\inject_control_wedge.rs:1301:    // NOTHING to the PTY (ADR-0022 amendment — raw inject was REMOVED as a delivery
crates\spt-daemon\tests\inject_control_wedge.rs:1320:         !marker_reached_pty → faulted binary spools, never raw-injects) ==="
crates\spt-daemon\tests\inject_control_wedge.rs:1338:         not raw-inject — idle delivery is translation-binary-only (ADR-0022 amendment)"
crates\spt-daemon\tests\inject_control_wedge.rs:1342:        "a faulted binary no longer raw-injects: the raw `<EVENT>` envelope must NOT \
crates\spt-daemon\src\msg.rs:167:pub const KIND_ENDPOINT_INJECTED: &str = "endpoint-injected";
crates\spt-daemon\src\msg.rs:224:    /// v0.11.0 raw-inject was removed as a delivery path, ADR-0022 amendment).
crates\spt-daemon\src\msg.rs:700:/// `endpoint-injected` reply payload — the outcome of an [`EndpointInputReq`].
crates\spt-daemon\src\msg.rs:861:/// Build an `endpoint-injected` reply envelope (REQ-SEND-SPT-HOSTED).
crates\spt-daemon\tests\broker.rs:242:            data_b64: encode_bytes(b"ENDPOINT-INJECT-BETA\r"),
crates\spt-daemon\tests\broker.rs:264:        "a hosted session with no translation binary acks delivered=false (spool, not raw inject)"
crates\spt-daemon\tests\broker.rs:267:        !String::from_utf8_lossy(&out).contains("ENDPOINT-INJECT-BETA"),
crates\spt-daemon\src\translation.rs:76:    /// the buffered controller input race-free. (The v0.11.0 raw-inject —
crates\spt-daemon\src\translation.rs:239:    /// error (the broker logs it and `None` → idle inbound spools, never raw-injected).


A few more: `manifest.rs:59` + the function doc at `broker.rs:1884` (IDLE/DIRECT path). Read the dispatch_endpoint_input doc header:


1879	    /// the wire format — ADR-0020). Fire-and-forget: a direct write, no journal
1880	    /// (a user message is delivered like the relay's emit, not an exactly-once
1881	    /// effect). Replies [`KIND_ENDPOINT_INJECTED`] with `delivered` so the caller
1882	    /// knows whether to fall back to the spool.
1883	    ///
1884	    /// IDLE/DIRECT path only (REQ-SEND-SPT-HOSTED, MVP per CONTEXT:188): a write
1885	    /// arriving mid-agent-turn can interleave with the agent's active output —
1886	    /// activity-gated routing (idle→inject / active→spool-for-poll-drain) is a
1887	    /// deferred follow wave. The write is logged so an active-state inject is
1888	    /// never silent.
1889	    // [impl->REQ-SEND-SPT-HOSTED]
1890	    fn dispatch_endpoint_input(&self, env: Envelope, send: &SharedSend) -> Result<(), String> {
1891	        let req: EndpointInputReq = serde_json::from_value(env.payload)
1892	            .map_err(|e| format!("bad endpoint-input payload: {e}"))?;

    /// the wire format — ADR-0020). Fire-and-forget: a direct write, no journal
    /// (a user message is delivered like the relay's emit, not an exactly-once
    /// effect). Replies [`KIND_ENDPOINT_INJECTED`] with `delivered` so the caller
    /// knows whether to fall back to the spool.
    ///
    /// IDLE/DIRECT path only (REQ-SEND-SPT-HOSTED, MVP per CONTEXT:188): a write
    /// arriving mid-agent-turn can interleave with the agent's active output —
    /// activity-gated routing (idle→inject / active→spool-for-poll-drain) is a
    /// deferred follow wave. The write is logged so an active-state inject is
    /// never silent.
    // [impl->REQ-SEND-SPT-HOSTED]
    fn dispatch_endpoint_input(&self, env: Envelope, send: &SharedSend) -> Result<(), String> {
        let req: EndpointInputReq = serde_json::from_value(env.payload)
            .map_err(|e| format!("bad endpoint-input payload: {e}"))?;


52	    /// stdin→stdout JSON-lines filter: spt-core feeds it `init`/`event`/`input`
53	    /// lines and reads back `{key}`/`{delay_ms}`/`{text}` keystroke-commands, which
54	    /// spt-core applies to the broker-held PTY atomically (spt-core owns every PTY
55	    /// write). spt-core LIFECYCLE-manages it (spawn when the spt-hosted endpoint
56	    /// comes up, terminate when it goes down). A NEW manifest primitive — NOT
57	    /// collapsed into `[inject]`/`notif_command` — though it shares the poll-feed
58	    /// substrate. Absent ⇒ no translation binary (delivery falls back to the
59	    /// v0.11.0 degenerate raw-inject / spool).
60	    // [impl->REQ-MSG-IDLE-TRANSLATION-BINARY]
61	    #[serde(
62	        default,
63	        rename = "message-idle-translation-binary",

    /// stdin→stdout JSON-lines filter: spt-core feeds it `init`/`event`/`input`
    /// lines and reads back `{key}`/`{delay_ms}`/`{text}` keystroke-commands, which
    /// spt-core applies to the broker-held PTY atomically (spt-core owns every PTY
    /// write). spt-core LIFECYCLE-manages it (spawn when the spt-hosted endpoint
    /// comes up, terminate when it goes down). A NEW manifest primitive — NOT
    /// collapsed into `[inject]`/`notif_command` — though it shares the poll-feed
    /// substrate. Absent ⇒ no translation binary (delivery falls back to the
    /// v0.11.0 degenerate raw-inject / spool).
    // [impl->REQ-MSG-IDLE-TRANSLATION-BINARY]
    #[serde(
        default,
        rename = "message-idle-translation-binary",


Reword the dispatch_endpoint_input doc header + manifest.rs:59. Read the full doc header first:


1872	    /// Deliver an inbound message to an spt-hosted endpoint by ENDPOINT ID:
1873	    /// resolve the endpoint to its hosted session and inject the bytes straight
1874	    /// into that session's PTY (REQ-SEND-SPT-HOSTED). The endpoint-keyed
1875	    /// counterpart of [`dispatch_input`] — a CLI `spt send` to an spt-hosted
1876	    /// endpoint (broker holds its PTY, no `api listen` relay) lands here instead
1877	    /// of spooling silently. Resolution is atomic under the sessions lock (no
1878	    /// TOCTOU); the bytes are a pre-rendered `<EVENT>` envelope (the caller owns
1879	    /// the wire format — ADR-0020). Fire-and-forget: a direct write, no journal
1880	    /// (a user message is delivered like the relay's emit, not an exactly-once

    /// Deliver an inbound message to an spt-hosted endpoint by ENDPOINT ID:
    /// resolve the endpoint to its hosted session and inject the bytes straight
    /// into that session's PTY (REQ-SEND-SPT-HOSTED). The endpoint-keyed
    /// counterpart of [`dispatch_input`] — a CLI `spt send` to an spt-hosted
    /// endpoint (broker holds its PTY, no `api listen` relay) lands here instead
    /// of spooling silently. Resolution is atomic under the sessions lock (no
    /// TOCTOU); the bytes are a pre-rendered `<EVENT>` envelope (the caller owns
    /// the wire format — ADR-0020). Fire-and-forget: a direct write, no journal
    /// (a user message is delivered like the relay's emit, not an exactly-once


    /// Deliver an inbound message to an spt-hosted endpoint by ENDPOINT ID:
    /// resolve the endpoint to its hosted session and inject the bytes straight
    /// into that session's PTY (REQ-SEND-SPT-HOSTED). The endpoint-keyed
    /// counterpart of [`dispatch_input`] — a CLI `spt send` to an spt-hosted
    /// endpoint (broker holds its PTY, no `api listen` relay) lands here instead
    /// of spooling silently. Resolution is atomic under the sessions lock (no
    /// TOCTOU); the bytes are a pre-rendered `<EVENT>` envelope (the caller owns
    /// the wire format — ADR-0020). Fire-and-forget: a direct write, no journal
    /// (a user message is delivered like the relay's emit, not an exactly-once
    /// effect). Replies [`KIND_ENDPOINT_INJECTED`] with `delivered` so the caller
    /// knows whether to fall back to the spool.
    ///
    /// IDLE/DIRECT path only (REQ-SEND-SPT-HOSTED, MVP per CONTEXT:188): a write
    /// arriving mid-agent-turn can interleave with the agent's active output —
    /// activity-gated routing (idle→inject / active→spool-for-poll-drain) is a
    /// deferred follow wave. The write is logged so an active-state inject is
    /// never silent.
    // [impl->REQ-SEND-SPT-HOSTED]
    fn dispatch_endpoint_input(&self, env: Envelope, send: &SharedSend) -> Result<(), String> {

    /// Deliver an inbound message to an spt-hosted endpoint by ENDPOINT ID:
    /// resolve the endpoint to its hosted session and deliver the bytes through its
    /// translation binary (REQ-SEND-SPT-HOSTED / REQ-MSG-IDLE-TRANSLATION-BINARY).
    /// The endpoint-keyed counterpart of [`dispatch_input`] — a CLI `spt send` to an
    /// spt-hosted endpoint (broker holds its PTY, no `api listen` relay) lands here.
    /// Resolution is atomic under the sessions lock (no TOCTOU); the bytes are a
    /// pre-rendered `<EVENT>` envelope (the caller owns the wire format — ADR-0020).
    /// Replies [`KIND_ENDPOINT_INJECTED`] with `delivered` so the caller knows
    /// whether to fall back to the spool.
    ///
    /// Idle delivery is translation-binary-ONLY (ADR-0022 amendment): a working
    /// (non-faulted) binary OWNS the choreography (the envelope is queued to its
    /// inject worker, which drives keystrokes onto the PTY atomically). With NO
    /// working binary (none declared, faulted, or its worker channel is gone) the
    /// message is NOT raw-injected — it SPOOLS (`delivered=false`, poll-fed, never
    /// lost), LOUDLY. Raw `payload+\r` was removed as a delivery path: it did not
    /// submit on a modern TUI — the silent pseudo-delivery that masked F-019.
    // [impl->REQ-SEND-SPT-HOSTED]
    // [impl->REQ-MSG-IDLE-TRANSLATION-BINARY]
    fn dispatch_endpoint_input(&self, env: Envelope, send: &SharedSend) -> Result<(), String> {


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

    /// Deliver an inbound message to an spt-hosted endpoint by ENDPOINT ID:
    /// resolve the endpoint to its hosted session and inject the bytes straight
    /// into that session's PTY (REQ-SEND-SPT-HOSTED). The endpoint-keyed
    /// counterpart of [`dispatch_input`] — a CLI `spt send` to an spt-hosted
    /// endpoint (broker holds its PTY, no `api listen` relay) lands here instead
    /// of spooling silently. Resolution is atomic under the sessions lock (no
    /// TOCTOU); the bytes are a pre-rendered `<EVENT>` envelope (the caller owns
    /// the wire format — ADR-0020). Fire-and-forget: a direct write, no journal
    /// (a user message is delivered like the relay's emit, not an exactly-once
    /// effect). Replies [`KIND_ENDPOINT_INJECTED`] with `delivered` so the caller
    /// knows whether to fall back to the spool.
    ///
    /// IDLE/DIRECT path only (REQ-SEND-SPT-HOSTED, MVP per CONTEXT:188): a write
    /// arriving mid-agent-turn can interleave with the agent's active output —
    /// activity-gated routing (idle→inject / active→spool-for-poll-drain) is a
    /// deferred follow wave. The write is logged so an active-state inject is
    /// never silent.
    // [impl->REQ-SEND-SPT-HOSTED]
    fn dispatch_endpoint_input(&self, env: Envelope, send: &SharedSend) -> Result<(), String> {

    /// Deliver an inbound message to an spt-hosted endpoint by ENDPOINT ID:
    /// resolve the endpoint to its hosted session and deliver the bytes through its
    /// translation binary (REQ-SEND-SPT-HOSTED / REQ-MSG-IDLE-TRANSLATION-BINARY).
    /// The endpoint-keyed counterpart of [`dispatch_input`] — a CLI `spt send` to an
    /// spt-hosted endpoint (broker holds its PTY, no `api listen` relay) lands here.
    /// Resolution is atomic under the sessions lock (no TOCTOU); the bytes are a
    /// pre-rendered `<EVENT>` envelope (the caller owns the wire format — ADR-0020).
    /// Replies [`KIND_ENDPOINT_INJECTED`] with `delivered` so the caller knows
    /// whether to fall back to the spool.
    ///
    /// Idle delivery is translation-binary-ONLY (ADR-0022 amendment): a working
    /// (non-faulted) binary OWNS the choreography (the envelope is queued to its
    /// inject worker, which drives keystrokes onto the PTY atomically). With NO
    /// working binary (none declared, faulted, or its worker channel is gone) the
    /// message is NOT raw-injected — it SPOOLS (`delivered=false`, poll-fed, never
    /// lost), LOUDLY. Raw `payload+\r` was removed as a delivery path: it did not
    /// submit on a modern TUI — the silent pseudo-delivery that masked F-019.
    // [impl->REQ-SEND-SPT-HOSTED]
    // [impl->REQ-MSG-IDLE-TRANSLATION-BINARY]
    fn dispatch_endpoint_input(&self, env: Envelope, send: &SharedSend) -> Result<(), String> {

-    /// resolve the endpoint to its hosted session and inject the bytes straight

-    /// into that session's PTY (REQ-SEND-SPT-HOSTED). The endpoint-keyed

-    /// counterpart of [`dispatch_input`] — a CLI `spt send` to an spt-hosted

-    /// endpoint (broker holds its PTY, no `api listen` relay) lands here instead

-    /// of spooling silently. Resolution is atomic under the sessions lock (no

-    /// TOCTOU); the bytes are a pre-rendered `<EVENT>` envelope (the caller owns

-    /// the wire format — ADR-0020). Fire-and-forget: a direct write, no journal

-    /// (a user message is delivered like the relay's emit, not an exactly-once

-    /// effect). Replies [`KIND_ENDPOINT_INJECTED`] with `delivered` so the caller

-    /// knows whether to fall back to the spool.

+    /// resolve the endpoint to its hosted session and deliver the bytes through its

+    /// translation binary (REQ-SEND-SPT-HOSTED / REQ-MSG-IDLE-TRANSLATION-BINARY).

+    /// The endpoint-keyed counterpart of [`dispatch_input`] — a CLI `spt send` to an

+    /// spt-hosted endpoint (broker holds its PTY, no `api listen` relay) lands here.

+    /// Resolution is atomic under the sessions lock (no TOCTOU); the bytes are a

+    /// pre-rendered `<EVENT>` envelope (the caller owns the wire format — ADR-0020).

+    /// Replies [`KIND_ENDPOINT_INJECTED`] with `delivered` so the caller knows

+    /// whether to fall back to the spool.

-    /// IDLE/DIRECT path only (REQ-SEND-SPT-HOSTED, MVP per CONTEXT:188): a write

-    /// arriving mid-agent-turn can interleave with the agent's active output —

-    /// activity-gated routing (idle→inject / active→spool-for-poll-drain) is a

-    /// deferred follow wave. The write is logged so an active-state inject is

+    /// Idle delivery is translation-binary-ONLY (ADR-0022 amendment): a working

+    /// (non-faulted) binary OWNS the choreography (the envelope is queued to its

+    /// inject worker, which drives keystrokes onto the PTY atomically). With NO

+    /// working binary (none declared, faulted, or its worker channel is gone) the

+    /// message is NOT raw-injected — it SPOOLS (`delivered=false`, poll-fed, never

+    /// lost), LOUDLY. Raw `payload+\r` was removed as a delivery path: it did not

+    /// submit on a modern TUI — the silent pseudo-delivery that masked F-019.

+    // [impl->REQ-MSG-IDLE-TRANSLATION-BINARY]

let req: EndpointInputReq = serde_json::from_value(env.payload)

.map_err(|e| format!("bad endpoint-input payload: {e}"))?;


    /// substrate. Absent ⇒ no translation binary (delivery falls back to the
    /// v0.11.0 degenerate raw-inject / spool).

    /// substrate. Absent ⇒ no translation binary (idle inbound SPOOLS, poll-fed;
    /// the v0.11.0 raw-inject was removed as a delivery path, ADR-0022 amendment).


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

    /// substrate. Absent ⇒ no translation binary (delivery falls back to the
    /// v0.11.0 degenerate raw-inject / spool).

    /// substrate. Absent ⇒ no translation binary (idle inbound SPOOLS, poll-fed;
    /// the v0.11.0 raw-inject was removed as a delivery path, ADR-0022 amendment).

/// write). spt-core LIFECYCLE-manages it (spawn when the spt-hosted endpoint

/// comes up, terminate when it goes down). A NEW manifest primitive — NOT

/// collapsed into `[inject]`/`notif_command` — though it shares the poll-feed

-    /// substrate. Absent ⇒ no translation binary (delivery falls back to the

-    /// v0.11.0 degenerate raw-inject / spool).

+    /// substrate. Absent ⇒ no translation binary (idle inbound SPOOLS, poll-fed;

+    /// the v0.11.0 raw-inject was removed as a delivery path, ADR-0022 amendment).


Code + comment sweep + test flips done. `manifest.rs` doc changed → schema.json needs regen (doc-drift gate). Now compile-check the affected crates. Per [[delegate-build-preflight-hang]], keep it targeted:


Bash

cargo check -p spt-daemon -p spt-runtime --quiet 2>&1 | tail -30

Check daemon + runtime compile


(Bash completed with no output)


Clean compile. Now compile the test targets + clippy on the daemon:


cargo test -p spt-daemon --no-run --quiet 2>&1 | tail -25

Compile daemon test targets


Tests compile. Run the flipped broker test:


cargo test -p spt-daemon --test broker endpoint_input -- --nocapture 2>&1 | tail -25

Run flipped endpoint_input test


    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.48s
     Running tests\broker.rs (target\debug\deps\broker-e228b522eedf21eb.exe)

running 0 tests

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


178-
179:#[test]
--
195-// [int->REQ-MSG-IDLE-TRANSLATION-BINARY]
196:fn endpoint_input_test() {
--
306-
307:#[test]
308-fn endpoint_keyed_inject_reaches_hosted_pty() {
309:    endpoint_input_test();
--
415-
416:#[test]
--
519-
520:#[test]
--
657-
658:#[test]
--
841-
842:#[test]
--
944-
945:#[test]
--
1180-// [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER]
1181:#[test]


cargo test -p spt-daemon --test broker endpoint_keyed_inject_reaches_hosted_pty -- --nocapture 2>&1 | tail -20

Run flipped endpoint test by wrapper name


    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.42s
     Running tests\broker.rs (target\debug\deps\broker-e228b522eedf21eb.exe)

running 1 test
ENDPOINT_INJECT:wall-b: no working translation binary (absent/faulted/worker-gone) -> SPOOLED, not injected
test endpoint_keyed_inject_reaches_hosted_pty ... ok

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


Passes + the loud spool log fires. The wrapper name `endpoint_keyed_inject_reaches_hosted_pty` is now a misnomer (it spools, doesn't reach PTY). Rename for accuracy:


304	    server.join().expect("server thread");
305	}
306
307	#[test]
308	fn endpoint_keyed_inject_reaches_hosted_pty() {
309	    endpoint_input_test();
310	}
311
312	/// REQ-HAZARD-ENV-SUBST: a SpawnReq's `env` map reaches the spawned PTY child's
313	/// environment — the broker leg of the F-013 fix (a flagless harness gets
314	/// SPT_ENDPOINT_ID populated, instead of an empty value → seed-by-PPID → zero
315	/// perch). Spawn a child that ECHOES the injected env var; its output must carry

    server.join().expect("server thread");
}

#[test]
fn endpoint_keyed_inject_reaches_hosted_pty() {
    endpoint_input_test();
}

/// REQ-HAZARD-ENV-SUBST: a SpawnReq's `env` map reaches the spawned PTY child's
/// environment — the broker leg of the F-013 fix (a flagless harness gets
/// SPT_ENDPOINT_ID populated, instead of an empty value → seed-by-PPID → zero
/// perch). Spawn a child that ECHOES the injected env var; its output must carry


Edit

#[test]
fn endpoint_keyed_inject_reaches_hosted_pty() {
    endpoint_input_test();
}

#[test]
fn endpoint_keyed_inject_without_binary_spools_not_pty() {
    endpoint_input_test();
}


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

#[test]
fn endpoint_keyed_inject_reaches_hosted_pty() {
    endpoint_input_test();
}

#[test]
fn endpoint_keyed_inject_without_binary_spools_not_pty() {
    endpoint_input_test();
}


Add nothing new at unit level yet (int coverage is solid; doyle's tail may specify a specific unit). Run the flipped g2 int gate + g1 happy-path to validate:


Bash

cargo test -p spt-daemon --test inject_control_wedge g1_ g2_ -- --nocapture --test-threads=1 2>&1 | tail -40

Run g1 + g2 int gates


error: unexpected argument 'g2_' found

Usage: cargo.exe test [OPTIONS] [TESTNAME] [-- [ARGS]...]

For more information, try '--help'.


cargo test -p spt-daemon --test inject_control_wedge -- --nocapture --test-threads=1 g 2>&1 | tail -45

Run inject_control_wedge g* gates single-threaded


PUMP_IPC_READER: spawned
PUMP_IPC_READER: exited
=== W2 G1 CHOREO GATE: delivered=true payload_reached_pty=false sessions_answered=true fresh_attach_served=true (all true = inject coexists with a live controller; payload landed via the binary) ===
=== W2 G1 (Windows ConPTY observation, not asserted): payload_reached=false — 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. ===
ok
test g2_no_commit_deadline_faults_binary_and_does_not_wedge_controller_input ... PUMP_IPC_READER: spawned
ENDPOINT_INJECT:xlate-g2-ep (57 bytes → translation binary)
PUMP_IPC_READER: spawned
TRANSLATION_FAULT: no {commit} within INJECT_COMMIT_DEADLINE — terminating binary; idle messages spool until a working binary
ENDPOINT_INJECT:xlate-g2-ep: no working translation binary (absent/faulted/worker-gone) -> SPOOLED, not injected
PUMP_IPC_READER: spawned
PUMP_IPC_READER: exited
=== W2 G2 NO-COMMIT FAULT GATE: delivered=true op_flushed=true sessions_answered=true delivered2=false marker_reached_pty=false (op_flushed=true → controller input never wedged; delivered2=false + !marker_reached_pty → faulted binary spools, never raw-injects) ===
ok
test g3_content_free_ping_never_duplicates_operator_keystrokes_into_binary ... PUMP_IPC_READER: spawned
PUMP_IPC_READER: spawned
PUMP_IPC_READER: exited
=== W2 G3 CONTENT-FREE PING GATE: secret_on_pty=true secret_leaked_into_binary=false saw_input_ping=true (privacy = secret_leaked false; the binary sees only content-free pings) ===
ok
test g4_translation_child_is_reaped_no_zombie_after_session_down ... PUMP_IPC_READER: spawned
=== W2 G4 DIAG: session_gone=true ===
=== W2 G4 NO-ZOMBIE GATE: xlate_pid=177860 reaped_within_bound=true (true = the translation child is terminated+reaped on session-down — doyle gate #2) ===
ok
test injecting_a_large_payload_into_a_stdin_ignoring_child ... ENDPOINT_INJECT:inj-ep: no working translation binary (absent/faulted/worker-gone) -> SPOOLED, not injected
=== W1 PARK-B DIAGNOSTIC: inject_acked=true broker_alive=true (expect inject_acked=false = write_input parked on write_all) ===
ok
test p0_paste_wedge_parked_write_does_not_starve_attach_or_wedge_broker ... PUMP_IPC_READER: spawned
PUMP_IPC_READER: spawned
PUMP_IPC_READER: spawned
PUMP_IPC_READER: exited
PASTE_FLAKE: MAIN recv -> (true,true) after 15.2529ms (source=channel)
PUMP_IPC_READER: exited
=== P0 PASTE-WEDGE GATE: pumped=5209 keystroke_accepted=true concurrent_attach_subscribed=true attach_received_output=true backpressured=true backpressure_after_stop=None (fixed = subscribed+got_output+keystroke_accepted true; pre-fix: parked dispatch thread → subscribed=false / no output) ===
=== P0 (Windows ConPTY observation, not asserted): backpressured=true — 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. ===
ok
test w5_a2_abandoned_remote_controller_conn_close_eviction_is_platform_divergent ... PUMP_IPC_READER: spawned
PUMP_IPC_READER: spawned
PUMP_IPC_READER: spawned
=== W5 A2 CHARACTERIZATION: subscribed=true driven_after_attach=Some("403aa173fc75f353ad2bc068cc2f1836e368abfe43f35ebd3c806648e201261b") cby_attached=Some(Some("403aa173fc75f353ad2bc068cc2f1836e368abfe43f35ebd3c806648e201261b")) session_still_listed=true cby_after_abandon=Some(Some("403aa173fc75f353ad2bc068cc2f1836e368abfe43f35ebd3c806648e201261b")) driven_after_abandon=Some("403aa173fc75f353ad2bc068cc2f1836e368abfe43f35ebd3c806648e201261b") ===
=== W5 A2 VERDICT (characterization-only): conn-close clear observed in-window? false — 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 ===
=== W5 A2 driven_by latch: after_attach=Some("403aa173fc75f353ad2bc068cc2f1836e368abfe43f35ebd3c806648e201261b") after_abandon=Some("403aa173fc75f353ad2bc068cc2f1836e368abfe43f35ebd3c806648e201261b") (Some⇒phantom CONTROLLED persists; the picker renders 'controlled by {origin}' forever) ===
ok

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


All 9 int gates green — g2 flip confirmed (`delivered2=false marker_reached_pty=false`), g1 happy-path still `delivered=true`. Now lib units + full broker test file + runtime units:


cargo test -p spt-daemon --lib 2>&1 | tail -15

Run daemon lib unit tests


cargo test -p spt-runtime --lib resolve_program 2>&1 | tail -10

Run runtime resolve_program units


Command running in background with ID: baikiumtt. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\22d5a4f6-16ae-4552-82b1-0f69cfb556b0\tasks\baikiumtt.output. You will be notified when it completes. To check interim output, use Read on that file path.


    Finished `test` profile [unoptimized + debuginfo] target(s) in 8.18s
     Running unittests src\lib.rs (target\debug\deps\spt_runtime-94d9b78e4e2b7186.exe)

running 3 tests
test runtime::tests::resolve_program_falls_back_to_path ... ok
test runtime::tests::resolve_program_prefers_install_dir ... ok
test runtime::tests::resolve_program_adds_exe_suffix_on_windows ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 71 filtered out; finished in 0.00s


runtime 3/3 green. The daemon lib run backgrounded (larger). While it runs, check the schema.json/docs regen path (manifest.rs doc changed):


grep -rn "schema.json\|message-idle-translation\|gen" xtask/src 2>/dev/null | grep -i "schema\|manifest" | head; echo "=== schema gen cmd ==="; grep -rn "fn main\|gen\b" xtask/src/main.rs 2>/dev/null | head

Find schema/docs gen mechanism in xtask


=== schema gen cmd ===


1://! spt-core docs/site generation (M6-D5) — the anti-drift plumbing behind
2://! DOCS-STRATEGY's "generation is part of the build" commitment (REQ-DOCS-5):
4://! - `gen` — regenerate the checked-in generated docs (CLI reference).
5://! - `check` — drift gate: regenerate + diff the CLI reference, and
9://!   llms-full.txt / manifest.schema.json / install scripts at site root +
33:        "gen" => gen(false),
35:            gen(true);
44:        "release-keygen" => release_keygen(&args[1..]),
48:        "debug-keygen" => debug_keygen(&args[1..]),
54:                "usage: xtask <gen|check|site <outdir>|release-keygen <key-id>|release-sign …|release-publish …|debug-keygen <key-id>|debug-pin …|debug-rollout …|debug-converge --version <u64> …>"
64:/// `spt` name (Windows prints `spt.exe`, which would make the generated
76:/// renders two grouped blocks (`User commands:` / `Agent commands:`).
82:        if heading == "Commands:" || heading == "User commands:" || heading == "Agent commands:" {
111:/// The generated CLI reference: every command + nested subcommand's help,
113:/// reference IS the binary's own words — it cannot drift (REQ-DOCS-5).
118:         > **Generated** from the `spt` binary's own `--help` output \
119:         (`cargo run -p xtask -- gen`) and drift-gated in CI — this page \
161:fn gen(check: bool) {
164:    let generated = cli_reference(&bin);
165:    let path = root.join("docs-site/src/cli/reference.md");
168:            .expect("checked-in cli/reference.md (run `cargo run -p xtask -- gen`)")
170:        if on_disk != generated {
172:                "xtask check: docs-site/src/cli/reference.md drifted from the \
173:                 binary's --help — run `cargo run -p xtask -- gen` and commit"
178:        std::fs::write(&path, &generated).expect("write cli reference");
179:        eprintln!("xtask gen: wrote {}", path.display());
193:/// Internal tracker/decision codes that must never appear in the GENERATED CLI
199:/// reference.md) — those keep their REQ/ADR cross-refs.
250:/// Fail the docs gate if the GENERATED CLI reference carries any internal
251:/// tracker/decision code. Regeneration alone keeps drift==0, but a faithfully

[Showing results with pagination = limit: 30]


`xtask check` only drift-gates the CLI reference.md (from `--help`), not the manifest schema. My change was a `///` doc comment though — check whether the schema.json embeds doc comments and whether a test gates it:


grep -rln "manifest.schema\|schema_for\|schemars" crates --include=*.rs | head; echo "=== does schema.json contain the old text? ==="; grep -n "degenerate raw-inject\|raw-inject" crates/spt-runtime/manifest.schema.json 2>/dev/null

Find schema gen + check stale text in schema.json


crates/spt-runtime/src/lib.rs
crates/spt-runtime/src/manifest.rs
crates/xtask/src/main.rs
=== does schema.json contain the old text? ===
60:      "description": "`[message-idle-translation-binary]` — opt-in adapter idle-delivery\ntranslation binary (ADR-0022 / REQ-MSG-IDLE-TRANSLATION-BINARY). A TABLE\ncarrying a `path` scalar (modeled as a table, not a bare top-level scalar, so\nan author who writes it after another section cannot have it silently\nabsorbed — and so it stays N+1 extensible). The binary is a pure\nstdin→stdout JSON-lines filter: spt-core feeds it `init`/`event`/`input`\nlines and reads back `{key}`/`{delay_ms}`/`{text}` keystroke-commands, which\nspt-core applies to the broker-held PTY atomically (spt-core owns every PTY\nwrite). spt-core LIFECYCLE-manages it (spawn when the spt-hosted endpoint\ncomes up, terminate when it goes down). A NEW manifest primitive — NOT\ncollapsed into `[inject]`/`notif_command` — though it shares the poll-feed\nsubstrate. Absent ⇒ no translation binary (delivery falls back to the\nv0.11.0 degenerate raw-inject / spool).",


Schema.json embeds the doc comment (schemars) — line 60 is now stale. Find whether a test/CI gate compares it:


.github\workflows\release.yml:5:# (binaries, SHA256SUMS, manifest.schema.json, mock-adapter.zip), and create
.github\workflows\release.yml:82:          cp ../crates/spt-runtime/manifest.schema.json .
.github\workflows\release.yml:123:            dist/manifest.schema.json \
crates\xtask\src\main.rs:9://!   llms-full.txt / manifest.schema.json / install scripts at site root +
crates\xtask\src\main.rs:294:            "llms-full.txt" | "manifest.schema.json" => true,
crates\xtask\src\main.rs:380:            "crates/spt-runtime/manifest.schema.json",
crates\xtask\src\main.rs:381:            "manifest.schema.json",
docs-site\llms.txt:7:> /manifest.schema.json. Append `.md` to any doc URL for raw markdown (~90%
docs-site\src\index.md:58:- [`manifest.schema.json`](https://sabermage.github.io/spt-releases/manifest.schema.json)
crates\spt-runtime\src\manifest.rs:785:/// (`crates/spt-runtime/manifest.schema.json`) is the site/release asset;
crates\spt-runtime\src\manifest.rs:786:/// the `checked_in_schema_is_current` test is the drift gate (regenerate with
crates\spt-runtime\src\manifest.rs:796:    let schema = schemars::schema_for!(Manifest);
crates\spt-runtime\src\manifest.rs:801:        "https://sabermage.github.io/spt-releases/manifest.schema.json".into(),
crates\spt-runtime\src\manifest.rs:1737:            "https://sabermage.github.io/spt-releases/manifest.schema.json"
crates\spt-runtime\src\manifest.rs:1761:    /// The drift gate (M6-D3): the checked-in `manifest.schema.json` — the
crates\spt-runtime\src\manifest.rs:1770:        let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("manifest.schema.json");
crates\spt-runtime\src\manifest.rs:1772:            std::fs::write(&path, &want).expect("bless schema");
crates\spt-runtime\src\manifest.rs:1776:            "checked-in manifest.schema.json (regenerate: SPT_BLESS=1 cargo test -p spt-runtime)",
crates\spt-runtime\src\manifest.rs:1781:            "manifest.schema.json drifted from the derives — regenerate with \
crates\spt-runtime\manifest.schema.json:902:  "$id": "https://sabermage.github.io/spt-releases/manifest.schema.json"
crates\spt-runtime\Cargo.toml:15:# same types — the published schema can never drift from the parser because
docs-site\src\harness-contract\overview.md:40:  [`manifest.schema.json`](https://sabermage.github.io/spt-releases/manifest.schema.json).
docs\RELEASE-RUNBOOK.md:54:     `spt-x86_64-windows.exe`, `SHA256SUMS`, `manifest.schema.json`,
docs-site\src\harness-contract\manifest.md:7:Machine-readable companion: [`manifest.schema.json`](https://sabermage.github.io/spt-releases/manifest.schema.json)
docs\MANIFEST.md:7:**SPT is not a harness.** The manifest declares only what *varies per harness*. Command templates are **opaque strings** — spt-core never parses out a model, tool list, or flag; the adapter writes the full command line and spt-core just runs it with substitution keys filled. Anything spt-core owns (sentinels, spool/registry/perch schemas, the event-block vocabulary, the version-trampoline mechanism, config knobs) is **not** in the manifest.
docs-site\src\harness-contract\integration-checklist.md:134:      [`manifest.schema.json`](https://sabermage.github.io/spt-releases/manifest.schema.json)
docs-site\src\reference\schema.md:5:**<https://sabermage.github.io/spt-releases/manifest.schema.json>**
docs-site\src\reference\schema.md:28:    "https://sabermage.github.io/spt-releases/manifest.schema.json"))
docs\KNOWN-HAZARDS.md:515:| 6.8 | No irreversible durable-state migration before update ready-promotion (pre-ready writes stay N-1-readable) | auto-rollback / durable-state schema (ADR-0018) |
docs\DOCS-STRATEGY.md:20:10. **Docs-as-product, gated in CI** — generation (rustdoc, `llms.txt`, schema, CLI help) is part of the build so docs can never drift from code. Drift is the #1 most-cited docs failure; this kills it structurally.

[Showing results with pagination = limit: 30]


There's a drift-gate test `checked_in_schema_is_current`. My doc change will fail it until regenerated. Bless the schema:


SPT_BLESS=1 cargo test -p spt-runtime checked_in_schema_is_current 2>&1 | tail -8; echo "=== confirm new text in schema ==="; grep -n "removed as a delivery path\|degenerate raw-inject" crates/spt-runtime/manifest.schema.json

Regenerate manifest.schema.json


    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.20s
     Running unittests src\lib.rs (target\debug\deps\spt_runtime-94d9b78e4e2b7186.exe)

running 1 test
test manifest::tests::checked_in_schema_is_current ... ok

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

=== confirm new text in schema ===
60:      "description": "`[message-idle-translation-binary]` — opt-in adapter idle-delivery\ntranslation binary (ADR-0022 / REQ-MSG-IDLE-TRANSLATION-BINARY). A TABLE\ncarrying a `path` scalar (modeled as a table, not a bare top-level scalar, so\nan author who writes it after another section cannot have it silently\nabsorbed — and so it stays N+1 extensible). The binary is a pure\nstdin→stdout JSON-lines filter: spt-core feeds it `init`/`event`/`input`\nlines and reads back `{key}`/`{delay_ms}`/`{text}` keystroke-commands, which\nspt-core applies to the broker-held PTY atomically (spt-core owns every PTY\nwrite). spt-core LIFECYCLE-manages it (spawn when the spt-hosted endpoint\ncomes up, terminate when it goes down). A NEW manifest primitive — NOT\ncollapsed into `[inject]`/`notif_command` — though it shares the poll-feed\nsubstrate. Absent ⇒ no translation binary (idle inbound SPOOLS, poll-fed;\nthe v0.11.0 raw-inject was removed as a delivery path, ADR-0022 amendment).",


Schema regenerated + drift gate green. Check the daemon lib run:


Read daemon lib test result


(Bash completed with no output)


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


Cat daemon lib output file


Background file empty — rerun daemon lib foreground:


cargo test -p spt-daemon --lib 2>&1 | tail -12

Run daemon lib unit tests foreground


Command running in background with ID: b2mj0f7yc. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\22d5a4f6-16ae-4552-82b1-0f69cfb556b0\tasks\b2mj0f7yc.output. You will be notified when it completes. To check interim output, use Read on that file path.


Daemon lib backgrounded — I'll get notified. Meanwhile check the human docs (CONTEXT.md / MANIFEST.md / KNOWN-HAZARDS.md) for raw-inject-as-delivery framing that now contradicts the contract: