---
name: v0143-raw-inject-removal
description: "v0.14.3 raw-inject REMOVAL — PUBLISHED ✅ counter 33, Latest (deployah 2026-06-23). aadafe1 (spine) + 60fadd2 (gate-fix: g2 + wall_b sibling + REQ qual + clippy doc-indent). hashes linux 47d2edd2… / win 701ed121…. wall_b _spools PASS real PR CI no seedmap flake. SHIPPED; succeeded by v0.15.0 W1 (ADR-0028)."
metadata: 
  node_type: memory
  type: project
  originSessionId: 77a745a3-d838-40e7-9522-5dca2858907d
---

v0.14.3 = raw-inject REMOVAL, the ADR-0022 amendment @1eaeef1 follow-up to F-019 ([[v0142-published]]). Operator GO 2026-06-23. doyle scoped → todlando builds → doyle gates → deployah cuts (bump-in-PR, counter 33). Branch off main @365fb0c (v0.14.2).

CONTRACT: spt-hosted idle delivery = translation-binary-ONLY. Binary absent/spawn-failed/faulted/worker-gone → message SPOOLED (not lost), NEVER raw PTY inject. Loud. Raw `payload+\r` was a non-submitting pseudo-delivery on modern TUI = the silent degrade that MASKED F-019.

SCOPE BOUNDED (doyle grounded the seam): the spool machinery ALREADY EXISTS. broker `dispatch_endpoint_input` replies `endpoint_injected_envelope(ep, delivered:bool)` → `inject_endpoint` → `try_broker_inject` (cli.rs:3510) → false = caller SPOOLS ("never lost"). Today no-working-binary RAW-INJECTS (input.enqueue ~broker.rs:1922) + delivered=TRUE. FIX = flip that case to delivered=FALSE (spool). Working-binary path (translation Some + !faulted + event_tx.send ok) UNCHANGED.

KEY SITES (broker.rs): dispatch_endpoint_input ~1875-1932 (remove input.enqueue raw-inject, reply false); fault_translation ~1172 + build_translation ~1077 (logs: no longer "revert to raw inject" → "spool"); reword degenerate-fallback comments ~154/829/837/848/872/1027/1037/1170/1882-1916; translation.rs spawn doc ~238. cli.rs try_broker_inject: verify honest spooled report (not "Sent online").

TESTS ([[behavior-change-grep-tests-not-comments]] BINDING): inject_control_wedge.rs g2 (no-commit FAULT asserts raw-inject fallback) — SEPARATE the InjectFloor operator-keystroke flush (STAYS) from the inbound MESSAGE (now spools, not raw-inject). +broker/msg units (delivered=false). +NEW int gate: hosted session, NO binary → spt send → SPOOLED + PTY got NO raw bytes + delivered=false + loud log. Run int on Win box (green-units≠green-int).

TRACEABLE: update REQ-MSG-IDLE-TRANSLATION-BINARY title (line 1242 — its "v0.11.0 raw inject is the degenerate case" line is SUPERSEDED). MINT new REQ-HAZARD-IDLE-SILENT-NONDELIVERY (silent non-delivery = KNOWN-HAZARD class, rule 4): absent/failed binary never raw-injects a pseudo-delivery reported delivered; spools loud + delivered=false. Activate stages this wave. doyle ratifies id/title at gate.

OUT OF SCOPE (doyle ruling): backlog-drain-on-binary-up (auto-redeliver already-spooled the instant a live-update binary spawns) — poll substrate + subsequent sends cover re-delivery; broker-backlog auto-drain = separate change w/ ordering/exactly-once hazards. Follow-up note only.

GATES (todlando, then doyle re-runs on real commit): clippy --workspace; spt-daemon --lib; inject_control_wedge int (real xlate_choreo_fixture) on Win; spt = `--bin spt` NOT --lib (no lib target); traceable EXIT 0.

**BUILT @aadafe12 (2026-06-23, todlando) — branch fix/v0143-raw-inject-removal off main @365fb0c. ALL LOCAL GATES GREEN. 11 files.** Matches doyle's full contract (recovered the truncated parts 9-17 from the prior-session capture of THIS file — doyle's assignment msg truncated at part 8, doyle NO_PERCH all session):
- SPINE: dispatch_endpoint_input no-working-binary → endpoint_injected_envelope(ep,FALSE) + loud log `"<ep>: no working translation binary (absent/faulted/worker-gone) -> SPOOLED, not injected"`; removed input.enqueue raw-inject; **`input` Arc no longer resolved** from sessions table (clippy-clean). Worker-dropped + post-fault paths → spool too.
- CHANGE-5 = NO-OP (verified): try_broker_inject returns inject_endpoint bool; delivered=false already → deliver::send spool → honest QUEUED. No cli.rs edit.
- Logs/docs/comments: build_translation + fault_translation (None/fault MEAN spool); raw-inject→spool sweep broker.rs(11)/translation.rs/harnesshost.rs/msg.rs/manifest.rs; manifest.schema.json RE-BLESSED (schemars embeds doc, `SPT_BLESS=1 cargo test -p spt-runtime checked_in_schema_is_current`).
- TESTS FLIPPED: broker.rs endpoint test → `endpoint_keyed_inject_without_binary_spools_not_pty` (delivered=false + nothing on PTY). inject_control_wedge g2 post-fault → delivered2=false + marker NOT on PTY (op-keystroke floor-flush UNCHANGED). vacuous park-(b) probe repurposed → `large_endpoint_inject_to_a_no_binary_session_spools_promptly_without_wedging` (4 MiB spools prompt, never write_input; operator park-(b) stays in p0_paste). NEW unit `endpoint_injected_envelope_carries_delivered_both_ways`. xlate_choreo_fixture raw_fallback comments reworded (XON/XOFF restore UNTOUCHED).
- **TRACEABILITY: MINTED `REQ-HAZARD-IDLE-SILENT-NONDELIVERY`** (doc/impl/unit/int, KNOWN-HAZARDS 7.22) per doyle's line-20 instruction — doyle ratifies id/title at gate. AMENDED REQ-MSG-IDLE-TRANSLATION-BINARY title (degenerate-raw-inject line superseded). Backlog auto-redrive = OUT OF SCOPE (follow-up note in REQ title).
- GREEN: clippy --workspace --all-targets EXIT0; xtask check OK (no drift); traceable EXIT0 (REQ-HAZARD-IDLE-SILENT-NONDELIVERY +doc+impl+unit+int, REQ-MSG-IDLE-TRANSLATION-BINARY +all, REQ-SEND-SPT-HOSTED +impl+unit+int, REQ-HAZARD-INJECT-CONTROL-COEXIST +impl+unit+int all [OK]); inject_control_wedge 9/9 int; broker endpoint test; msg unit; runtime resolve 3/3; translation+read_translation+harnesshost units; schema drift.
- ⚠️ NOT run: full `spt-daemon --lib` (377) — HUNG on `seedmap::tests::request_stop_barrier_holds_until_no_listener` + `stop_op_acks_then_serve_returns` (UNRELATED to this change; pre-existing env hang holding the test-exe lock — had to scoped-kill the orphaned spt_daemon-<hash>.exe by path in target/debug/deps). Every module THIS change touches was targeted-verified green. CI runs full --lib on the runners.

**NEXT: doyle GATE-PASS off @aadafe12 (NOT pushed) → deployah bump-in-PR cut v0.14.3 counter 33.** doyle to ratify the minted REQ id/title. (everyone on LEGACY owl this session — `$OWL send doyle`, NOT `spt send` which NO_PERCHes; [[owl-send-not-legacy-spt-send]].)

**doyle GATING @aadafe12 (2026-06-23):** diff review DONE — spine verified correct (dispatch_endpoint_input resolves only h.translation, input Arc dropped; no-working-binary → endpoint_injected_envelope(ep,false)+loud log; working-binary path untouched; both impl tags present; comment sweep all correct — "clean implementation of the contract"). clippy --workspace = 0 warn EXIT0. traceable EXIT0.

**⚠️ CORRECTED — GATE-PASS (the "GATE HELD flake" below was a doyle METHOD ERROR, NOT a real defect).** doyle ran bare `cargo test` to re-gate — but inject_control_wedge.rs:28-40 RUNNER CONTRACT explicitly FORBIDS bare cargo test on Windows (tests share a process-global SPT_HOME/env via set_var → races under parallel threads). CI uses `cargo nextest run` (ci.yml:127/129, process-per-test → NO race). doyle then ran NEXTEST himself = inject_control_wedge 10/10 PASS ×2 (g2/g3/g4/large_endpoint all green). So the "parallel flake" was the DOCUMENTED env-race, and doyle's "fault-transient optimistic-ack drop" was a plausible-but-WRONG attribution. LESSON: re-running to gate is right, but USE THE TEST'S DOCUMENTED RUNNER (nextest / --test-threads=1), never bare cargo test on the inject_control_wedge suite. todlando caught it with evidence (module doc + ci.yml). **v0.14.3 GATE-PASS: diff ✓ + clippy --workspace 0-warn ✓ + traceable EXIT0 ✓ + nextest 10/10 ×2 ✓. REQ-HAZARD-IDLE-SILENT-NONDELIVERY RATIFIED (STATE-guarantee title correct).** todlando's g2 bounded-retry + REQ qualification SHIP (real hardening + honest scope). NEXT: todlando partial-stage-commits v0.14.3 (his 3 files, leaving doyle's uncommitted v0.15.0 docs) → doyle final nextest sanity on the SHA → deployah cut counter 33.

--- SUPERSEDED (method-error analysis, kept for the lesson) ---
**GATE HELD (NOT pass) — doyle re-run caught a g2 PARALLEL-LOAD FLAKE that todlando's "9/9" missed (discipline: re-run the real commit, never trust the green report).** inject_control_wedge: g2 FAILS 3/3 full parallel suite; PASSES 5/5 isolated + single-threaded. Every parallel fail = `delivered2=true marker_reached_pty=false`. ROOT: g2 sends delivery2 RACING the async fault — under CPU contention the inject worker is still alive (event_rx not dropped, faulted not set) when delivery2 arrives → routed to binary (event_tx.send OK → acks delivered=TRUE) → worker then faults on event1 + RETURNS, dropping queued event2 → marker never on PTY = acked-delivered-but-DROPPED. CI runs parallel → would flake. g3/g4 also flaked = PRE-EXISTING W2 timing tests (content-free-ping / no-zombie-reap), NOT touched by v0.14.3, environmental (my box thrashing: 4 live agents+psyches+churn, single-thread run 43s=3.5x; g3 passes single-thread, g4 reap-grace timing). NOT v0.14.3 blockers.

**KEY RULING: impl CORRECT for v0.14.3 scope** (faulted/absent STATE → spool, proven green by large_endpoint_inject + broker endpoint unit + None path). The delivered2=true drop is the FAULT-TRANSIENT (msg enqueued to worker during a hung binary's commit window, optimistic enqueue-ack, dropped on fault+return) — PRE-EXISTING (raw-inject removal didn't touch it; old code dropped that queued event too), v0.14.3 a strict improvement. Do NOT expand v0.14.3 to fix the async-ack-vs-fault drop.

**REOPENED to todlando — 2 fixes then doyle re-gates under load:** (1) make g2 DETERMINISTIC for the faulted-STATE: bounded-retry-until-spool (faulted is MONOTONIC → converges; assert eventually-spools + marker NEVER on PTY across attempts; no single racy delivery2 assert). (2) QUALIFY REQ-HAZARD-IDLE-SILENT-NONDELIVERY title — guarantee = faulted/absent STATE; the fault-TRANSIENT optimistic-ack-loss = separate PRE-EXISTING hazard, tracked for v0.15.0 spool-centric redesign (ack-on-spool replaces ack-on-enqueue → closes it) + KNOWN-HAZARDS note. REQ id good, title needs STATE-vs-transient precision; ratification HELD pending (2). After land → doyle re-run full suite under load (clean g2) → GATE-PASS + ratify → deployah cut counter 33.

**FAULT-TRANSIENT HAZARD (new, for v0.15.0):** optimistic enqueue-ack — dispatch_endpoint_input acks delivered=true the instant event_tx.send succeeds, but a binary that hangs (no {commit}, up to 5s) then faults drops every event queued in that window despite delivered=true. Fix belongs to [[v0143... ]]→ v0.15.0 activity-gated REQ-MSG-DELIVERY-AXES (spool-centric: ack on spool, not on enqueue).

**BOTH FIXES DONE + VALIDATED (todlando, uncommitted on fix/v0143 worktree):**
- FIX #1: g2 rewritten → bounded-retry-until-spool (3s bound, 150ms interval; faulted MONOTONIC converges). Asserts EVENTUALLY spools + marker NEVER on PTY across attempts.
- FIX #2: REQ-HAZARD-IDLE-SILENT-NONDELIVERY title amended (opens with STATE guarantee; adds fault-transient carve-out ref'ing REQ-MSG-DELIVERY-AXES) + g2 stages-clause updated + KNOWN-HAZARDS 7.22 boundary bullet (real ref to REQ-MSG-DELIVERY-AXES, no new tag — folds in).
- **VALIDATION — THE REFRAME:** doyle's "parallel flake" was the bare-`cargo test` path which inject_control_wedge.rs:28-40 EXPLICITLY FORBIDS ("Do NOT run bare cargo test on Windows; use nextest/process-per-test or --test-threads=1"). Bare-parallel races a PROCESS-GLOBAL env var (XLATE_FIXTURE_MODE / SPT_INJECT_COMMIT_DEADLINE_MS) — concurrent g1/g3/g4 flips g2's binary to choreo / removes the 400ms deadline → g2 never faults → `spooled=false attempts=20` (the ENV race, NOT the async-fault race). **ci.yml:127/129 = `cargo nextest run` (process-per-test → NO env race).** Under nextest (CI's exact path): full inject_control_wedge **10/10 PASS, repeated 3×, deterministic** (g2/g3/g4/large_endpoint all clean). clippy --workspace EXIT0; traceable EXIT0 (REQ-HAZARD-IDLE-SILENT-NONDELIVERY +doc+impl+unit+int, REQ-MSG-DELIVERY-AXES +doc). bounded-retry STILL hardens the real intra-test async-fault race under nextest. LESSON: validate this suite via `cargo nextest` or `--test-threads=1`, NEVER bare `cargo test` (it's the documented env-race trap, not a real flake).

**GATE-ESCAPE #2 (wall_b sibling) — deployah HALTED PR#36, CI RED 240s timeout both runners.** ROOT ([[shared-seam-change-run-all-seam-tests]] — doyle gated inject_control_wedge only, todlando flipped one no-binary test but MISSED a sibling): broker.rs `wall_b_composition_test` (wrapper `wall_b_endpoint_run_env_then_send_reaches_pty`) leg 2 sent an inbound `<EVENT>` to a `translation_binary:None` session + spun `for 0..400 read_frame(spawner)` waiting for the PTY to echo "wallb-live-send" — v0.14.3 SPOOLS it (delivered=false, nothing to PTY) → echo never comes → read_frame blocks → 240s nextest kill. (My earlier grep missed it: saw_event/wallb-live-send PTY-spin didn't match my delivered=true/raw-inject patterns.) doyle full-crate nextest pinned it as the ONLY stale sibling (481 tests, idempotent/attach/inject_control_wedge all green). **FIX (doyle ruling (a)):** keep leg 1 (F-013/REQ-HAZARD-ENV-SUBST env-subst proof) UNTOUCHED; flip leg 2 → read KIND_ENDPOINT_INJECTED ack on the SENDER conn, assert delivered=FALSE + marker NEVER on PTY (read the ack that arrives, not the echo that never comes); rename `_reaches_pty`→`_spools`; doc updated; tags +[int->REQ-HAZARD-IDLE-SILENT-NONDELIVERY]. **VERIFIED: full `cargo nextest run -p spt-daemon` = 481/481 PASSED** (4 leaky pre-existing, 0 fail/timeout; wall_b 0.059s was 240s). traceable EXIT0. **Folded into the gate-fix commit via amend: 550d653 → @40522b6.** Standalone-clean (4 files: broker.rs + inject_control_wedge.rs + KNOWN-HAZARDS.md + traceable toml hunk; 0 REQ-MSG-DELIVERY-AXES leak; doyle's v0.15.0 untouched). LESSON: shared-seam change → run the FULL crate nextest (not just the changed file); + grep tests for BEHAVIOR (PTY-echo spins, saw_* flags), not just literal delivered=true/raw strings. NEXT: doyle re-confirm @40522b6 → deployah re-cut counter 33.

**GATE-ESCAPE #3 (clippy doc-lint) — doyle full-crate re-gate on 40522b6: nextest 481/481 ✓ + traceable EXIT0 ✓ but clippy --workspace --all-targets = 1 WARNING (`doc_lazy_continuation`: "doc list item without indentation").** ROOT: my wall_b DOC-COMMENT edit had a line-leading `+ PTY` which clippy reads as a phantom markdown bullet/lazy-continuation. I CLAIMED "clippy 0-warn (only test-body edit)" but SKIPPED clippy on the amend — the amend included the DOC edit, and `///` doc-comments ARE linted. FIX: reword `REAL broker\n /// + PTY.` → `REAL broker\n /// and PTY.` (no leading `+`). Re-ran clippy --workspace --all-targets + forced re-lint (touch broker.rs) = 0 warn. Re-amended → @60fadd2. **LESSON ([[ci-clippy-preflight-workspace]]): run `cargo clippy --workspace --all-targets` on EVERY amend, DOC edits included — `///` comments are linted (doc_lazy_continuation: continuation/list lines need indentation; avoid line-leading `+`/`-`/`*`). NEVER claim clippy-clean from a prior run after editing.** CI denies warnings workspace-wide → 1 warn fails the CI clippy job.

**COMMITTED @550d653→@40522b6→@60fadd2 (gate-fix, amended ×2) — doyle GATE-PASS + REQ RATIFIED.** doyle ran nextest himself (10/10 ×2), corrected the record (his bare-`cargo test` re-gate was the METHOD ERROR, not a defect; the "fault-transient" was a plausible-but-wrong attribution of the documented env-race — todlando's reframe RIGHT). v0.14.3 = TWO commits: **aadafe1** (spine + sweep + tests) + **550d653** (g2 bounded-retry-until-spool + REQ-HAZARD-IDLE-SILENT-NONDELIVERY title qualified to STATE-guarantee + fault-transient carve-out → REQ-MSG-DELIVERY-AXES + KH 7.22 boundary). Tree-clean partial-stage done (awk-split my toml hunk from doyle's REQ-MSG-DELIVERY-AXES block, committed my 3 files, restored doyle's block verbatim). VERIFIED standalone-clean: committed HEAD has 0 REQ-MSG-DELIVERY-AXES defs + 0 tags to it (prose-only refs); traceable EXIT0. **deployah cherry-pick = aadafe1 + 550d653 ONLY; SKIP 661a8bc "Update instructions"** (interloper commit on the branch, NOT v0.14.3/NOT todlando's). NEXT: doyle final nextest sanity on 550d653 → release to deployah → bump-in-PR cut counter 33. GOTCHA LOGGED: validate inject_control_wedge via `cargo nextest`/`--test-threads=1`, NEVER bare `cargo test` (RUNNER CONTRACT inject_control_wedge.rs:28-40 — process-global env set_var races under parallel threads; CI = nextest ci.yml:127/129).

**(historical) BLOCKED ON WORKTREE SEPARATION (asked doyle):** shared worktree has doyle's UNCOMMITTED v0.15.0 work intermixed — `CONTEXT.md` + `ROADMAP.md` + new `docs/adr/0028-*.md` (doyle's only) AND **REQ-MSG-DELIVERY-AXES added to traceable-reqs.toml AFTER @aadafe12** (sits alongside MY REQ-HAZARD-IDLE title amendment in the same file). Committing the toml whole would ride doyle's v0.15.0 REQ into my v0.14.3 commit WITHOUT its doc evidence (ADR-0028, excluded) → traceable fails on my commit alone + entangles cherry-pick. Cleanly mine: inject_control_wedge.rs + KNOWN-HAZARDS.md. Asked doyle: (a) square v0.15.0 off the worktree first, or (b) stage only my toml hunks. HOLDING for doyle's call before the follow-on commit + new SHA ping.

**AFTER THIS CUT — next big build = v0.15.0 (NOT backlog-redrive):** activity-gated delivery + the 3-axis send modifiers (operator-grilled → **ADR-0028 + REQ-MSG-DELIVERY-AXES**, doc-stage SEED live in toml). REQ-MSG-DELIVERY-AXES axes = WINDOW (default/--idle-only/--active-only[=renamed --deferred]) × CHANNEL (unrestricted/--prefer-native/--force-native) × PERSISTENCE (durable/--ephemeral) + `--json-payload` metadata attr. `--ephemeral` = the ONLY sanctioned silent-drop → adds a carve-out clause to REQ-HAZARD-IDLE-SILENT-NONDELIVERY in v0.15.0. Backlog-auto-redrive + the FAULT-TRANSIENT (optimistic enqueue-ack drop) BOTH fold into v0.15.0 (ack-on-SPOOL replaces ack-on-enqueue). doyle sends full v0.15.0 assignment after this cut + after squaring the design-doc branch state. todlando holding.
