---
name: v0130-milestone
description: "v0.13.0 milestone — spt-hosted message delivery redesign + control-loss/wedge bug cluster (grilled 2026-06-19, JIT plan + ADR-0022 authored)"
metadata: 
  node_type: memory
  type: project
  originSessionId: bfe20bf0-7829-4d00-b1b1-052a9c66e85b
---

v0.13.0 (one big milestone, operator chose) born from dogfooding v0.12.1/v0.12.2. JIT plan = `V0.13.0-DELIVERY-CONTROL-JIT.md`. Folds the gated v0.12.2 work (window-regression fix @15fdf58 + MD-output sweep @2435a74 + ATX header @b3bb387 on branch v0.12.2-cli-fixes) — NOT shipped separately.

**SPINE INVARIANT:** the broker must accept INJECTED keystrokes (v0.11.0 raw direct-inject today; the translation binary tomorrow) AND a live `spt rc` controller into the same PTY without control-loss, `ONLINE+CONTROLLED` latch, or wedge. The injection inlet is permanent (spt-claude-code REQUIRES keystroke injection) → root-cause + fix at the PTY-injection layer IN STEP with the delivery redesign.

**DELIVERY REDESIGN — ADR-0022 (grilled to completion, operator agreed all):** `[message-idle-translation-binary]` = scalar binary path, opt-in. Binary = PURE stdin→stdout FILTER; spt-core owns lifecycle (up/down w/ endpoint) + EVERY PTY write. stdin JSON-lines: `{type:init,endpoint_id,node}` · `{type:event,envelope:<EVENT>}` · `{type:input}` (content-free ping on operator keystroke, for binary's idle tracking). stdout JSON-lines: `{key}`/`{delay_ms}`/`{text}`. spt-core applies them to PTY ATOMICALLY (buffers controller input during sequence → ctrl+s stash/restore can't clobber = the coexistence mechanism). spt-core PREFERS poll listener if present. Idle-only; busy=hook-inject. CC choreography: ctrl+s→50ms→payload+\r→50ms→ctrl+s. Spec was recovered from CCS session 16531b26 (Q1→"A+" locked, rest deferred until now). NOTE: records live in `~/.ccs/instances/bigscreen/`, NOT `.claude` (I wasted a trace on the wrong dir).

**RCA done (both refuted-fix bugs):**
- P1 (fresh endpoint shows no project): ROOT = `info.cwd` NEVER set on bind. v0.12.1 merge_origin_project unions project_id_for_dir(info.cwd) but cwd is always None. Fix W3: thread cwd into establish_perch (cmd_bind reads own current_dir; bind_from_seed passes seed.cwd which it currently discards). v0.12.1 unit tested merge w/ a PROVIDED origin, never asserted cwd set = green-but-broken AGAIN.
- Wedge/control-loss: NOT concurrent-input (operator challenged + was right: 1 backspace worked then wedge). Single-threaded broker parks on a blocking PTY/loopback write after injection-induced harness output. W1 = REPRO-FIRST on real fixture (no theory), data-plane fix, REOPEN REQ-HAZARD-ATTACH-WEDGE (v0.12.1 prove-don't-change missed the injection trigger). driven_by stuck ONLINE+CONTROLLED bc wedged pump never delivers detach → W5 self-heal via reconcile (don't trust detach IPC). "controlled by <hex>" should be node NAME (node_label_display) = W4.

**WAVES:** W0 design (ADR-0022 ✓ + CONTEXT:39 reword ✓ + mint REQs) · W1 keystone wedge+control (repro-first) · W2 keystone delivery redesign · W3 P1 cwd · W4 picker UX (skip 1st screen+'n', auto-attach+`h` headless, node-name, output cleanup drop `pid=Some()` leak+internals) · W5 driven_by self-heal · W6 perri translation-binary handoff · SIDE: correct v0.12.1 changelog docs-only (operator OK'd — "appears under its own project" was false). Version v0.13.0 MINOR.

STATUS (2026-06-19, doyle): KICKED OFF. Design committed @0179d09. **Branch RENAMED v0.12.2-cli-fixes → v0.13.0-delivery-control.** W0 DONE @e715fa0 — 5 seed REQs minted (REQ-HAZARD-INJECT-CONTROL-COEXIST=W1 keystone · REQ-MSG-IDLE-TRANSLATION-BINARY=W2 · REQ-HAZARD-BIND-CWD-UNSET=W3 · REQ-PICKER-UX-V013=W4 · REQ-HAZARD-DRIVEN-BY-SELFHEAL=W5; all stages=[] until each wave builds; traceable-reqs check EXIT=0). SIDE TASK DONE both surfaces — CHANGELOG.md v0.12.1 false clause dropped (on branch) + LIVE release notes corrected via `gh release edit v0.12.1 -R SaberMage/spt-releases` (no retag; releases live in spt-releases NOT spt-core). **W1 DISPATCHED to todlando** (repro-first, no theory; gate the root before the patch — I want the repro-mechanism ping first). NEXT (doyle): gate W1 repro+fix; then dispatch the parallelizable batch W3/W4/W5 + W2 (W2 depends W0=done); W6 perri after W2. See [[v0121-realharness-reopen]] [[v0121-help-md]] [[v0121-release]].

**DIAGNOSE 2026-06-19 (operator dogfooding, two rc/PTY bugs, doyle /diagnose, committed @0fcde06):**
- PART 1 (sluggish/stall/wedge input in rc) = the W1 cluster, ROOT CODE-LOCATED: `Broker::append` (broker.rs:205-227) fans live output to the CONTROLLER on a SYNCHRONOUS BLOCKING write_frame INLINE in the session drain thread (authoritative D4-1 cursor path), while VIEWERS use a dedicated writer thread + bounded evicting sync_channel (add_viewer:273/viewer_writer). Backed-up controller socket / full 64KB loopback duplex → drain thread blocks → output stalls → echo stalls (perceived input lag) → wedge. **FIRES ON NORMAL INTERACTIVE rc USE under heavy output, NOT only injection** — widens W1 repro. Fix dir: controller onto a dedicated writer like viewers BUT preserve the authoritative cursor (block the writer not the drain, deadline-bound the wedge, never silently evict). Folded into REQ-HAZARD-INJECT-CONTROL-COEXIST (title sharpened). Operator's "dedicated thread per session" hypothesis = right direction.
**W1 LANDED + GATE-PASS (doyle, 2026-06-19) @8b5583e** — controller delivery moved OFF the drain thread onto a dedicated controller_writer thread + bounded channel (viewer_writer pattern but AUTHORITATIVE): append→Option<ControllerJob> releases the log lock; ControllerJob::deliver = bounded off-lock send (CONTROLLER_WRITE_DEADLINE=5s → clear_controller, never park, never silent-evict); delivered_through now Arc<AtomicU64> advanced only-on-success+monotonic; controller_epoch guards stale deadline-evict through displace; clear_controller = THE single unlatch (W5 reuses — shared helper). Ring replay = writer's initial batch → SUBSUMES the inline-replay block (REQ-HAZARD-ENDPOINT-RUN-ATTACH-OUTPUT Option-b deeper root, now closed). Gate: read diff + flipped non-vacuous test (a_backed_up_controller_does_not_wedge_the_session asserts sessions_answered=true), ran on Windows = 2 passed/0 failed, clippy --workspace --all-targets -D warnings clean, REQ activated [impl,unit,int], traceable EXIT=0. (b)/(c) parks BENIGN on Windows ConPTY (absorbs 4MiB inject), real only Unix forkpty → DEFERRED to W2's atomic-write substrate (doyle ruling @66dadef tracks it under REQ-MSG-IDLE-TRANSLATION-BINARY; cfg(unix) park-b assert keeps it live on gravity-linux). **INSTALL GAP**: W1 fix + W7 hexdump NOT in PATH binary (C:\...\spt-core\bin\spt.exe stale 06-18); ship must rebuild+install but NOT over a running daemon (Win lock) — via daemon stop / release path.
- PART 2 (Backspace whole-word-deletes in Claude Code) = NEW bug, **REQ-HAZARD-RC-INPUT-KEY-ENCODING (W7, seeded stages=[]; confirm-hexdump @f05566b)**. BYTE CONFIRMED 2026-06-19 (operator real-WT capture via target\debug\spt.exe; first try hit STALE installed binary = empty log → re-pointed at the debug build): **Backspace=0x08 (^H), Ctrl+Backspace=0x7f (DEL)** = the INVERTED-from-VT mapping = ENABLE_VIRTUAL_TERMINAL_INPUT-OFF signature. CC maps ^H→backward-kill-word = the whole-word delete. FIX RULED = (a) enable ENABLE_VIRTUAL_TERMINAL_INPUT on rc stdin console (Win), NOT normalize 0x08→0x7f (normalize would conflate Backspace+Ctrl+Backspace since Ctrl+Backspace is already 0x7f; VT-input keeps both distinct+correct AND fixes whole key map). Impl: save+restore console input mode like RawGuard; cfg(windows); verify ctrl-b(0x02) detach still works. Dispatched to todlando.

**W7 FIX ATTEMPT #1 FAILED — GATE FAIL (doyle, real-capture, 2026-06-19).** todlando landed VT-input enable @dc07c39 (RawGuard sets ENABLE_VIRTUAL_TERMINAL_INPUT, restores on drop). Operator re-capture (on doyle's ISOLATED-WORKTREE clean build — see below) PROVED it BACKFIRED: on Windows Terminal, ENABLE_VIRTUAL_TERMINAL_INPUT yields **win32-input-mode** (6-field `ESC[Vk;Sc;Uc;Kd;Cs;Rc_` key-down/up records), NOT clean xterm VT. Backspace = `ESC[8;14;8;1;32;1_` (Vk=8 VK_BACK, Uc=8), NOT 0x7f. TWO regressions: (1) ctrl-b detach BROKE — 0x02 now wrapped in win32-input-mode (`ESC[66;48;2;…_`), parse_stdin_chunk's raw-0x02 matcher never fires; (2) win32-input-mode forwarded to CC (which negotiates its own broker-ConPTY input mode) = garbage. RULING: REVERT dc07c39 + NARROW NORMALIZE instead — stay a raw byte pump, map lone 0x08→0x7f in the forward path (Backspace→char-delete ✓), leave 0x02/everything else; Ctrl+Backspace(0x7f here)→stays char-delete (ACCEPTED minor loss) OR →0x17 if CC word-deletes on ctrl+w (verify, don't assume). LESSON: ENABLE_VIRTUAL_TERMINAL_INPUT is the WRONG lever on Windows Terminal (→win32-input-mode); gate keystroke fixes with a REAL operator capture, never ship on unit/clippy alone (cargo test/clippy don't even rebuild the bin). W7 still OPEN, fix attempt #2 (revert+normalize) dispatched.

**TECHNIQUE — isolated-worktree clean build for operator captures:** the shared checkout (doyle + todlando both edit C:\...\spt-core) gave non-deterministic builds — todlando's mid-flight W3 startup.rs WIP caused a transient E0061 in doyle's `cargo build -p spt`, and `cargo test`/`clippy -p spt` DON'T rebuild target\debug\spt.exe (lib+test targets only) so the operator nearly re-captured a STALE binary. FIX: `git worktree add --detach <tmp> <commit>` + `cargo build -p spt` there → a clean deterministic binary pinned to exactly the commit, isolated from concurrent WIP. Going forward todlando does WIP/W5+ in dedicated worktrees so main stays green.

Operator re-capture confirmed flip on attempt #1=NO (backfired); attempt #2 pending.

**KEY W7 RECONTEXT (operator, 2026-06-19):** after the VT flip CC input was NORMAL — Backspace + all keys behaved correctly (CC UNDERSTANDS win32-input-mode); the ONLY real regression was rc ctrl-b DETACH (0x02 wrapped). The wedge they still saw = the W1 daemon-side bug in their RUNNING daemon = the STALE installed binary (no 8b5583e); fresh rc client can't fix the old broker. So "win32-input-mode=garbage to CC" was WRONG. Net ruling unchanged (revert+normalize ships — harness-agnostic; win32-input-mode assumes app opt-in), but FOLLOW-UP logged on REQ-HAZARD-RC-INPUT-KEY-ENCODING: investigate clean xterm VT (Backspace→0x7f, arrows→ESC[, ctrl-b→0x02 RAW = agnostic + full fidelity + detach survives) vs narrow-normalize (backspace-only; arrows/Home/End stay legacy). Whether Windows Terminal can be driven to legacy xterm VT not win32-input-mode = the open question.

**W3 GATE — doyle caught a clippy FAIL (2026-06-19):** c4fae19 fix is CORRECT (matches RCA, REQ [impl,unit,int], traceable EXIT=0, source read) BUT establish_perch is now 8/7 args → clippy::too_many_arguments → CI workspace-clippy RED. todlando's check was `cargo build` (not clippy) → slipped. Re-confirms ci-clippy-preflight-workspace lesson: run `cargo clippy --workspace --all-targets -- -D warnings` (the EXACT CI form), build≠clippy. todlando fixing via #[allow]+justification (struct refactor deferred).

**SESSION-END STATE (2026-06-19, doyle; operator + todlando winding down):** W1 ✅ banked 8b5583e. W3 ✅ FULL GATE-PASS + CLOSED — clippy fix f1ae5c6 (#[allow]+justification on establish_perch), doyle re-ran exact CI `cargo clippy --workspace --all-targets -D warnings`=CLEAN, units 3/3 green on-machine (198 passed/0 failed), REQ [impl,unit,int], traceable EXIT=0. The refuted v0.12.1 P1 delivered for real. W7 = CODE-GATE PASS (fbd6c98 revert+narrow-normalize: VT-input fully reverted, normalize_key_byte 0x08→0x7f, 0x02 detach untouched, cfg(windows), unit normalize_maps_backspace_but_leaves_detach_and_others ok, KNOWN-HAZARDS 7.13 rewritten) — stays OPEN only for the operator re-capture (expect Backspace→7f + ctrl-b detach WORKS, arrows still legacy). Isolated worktree spt-w7verify REMOVED (clean). NEXT-SESSION TODO (doyle gate): (1) gate todlando's W3-clippy-fix commit (workspace clippy green); (2) gate W7 revert+normalize commit → isolated-worktree rebuild → operator re-captures (expect Backspace→7f + ctrl-b d detach WORKS); (3) W5 (thin clear_controller reconcile-reuse) + W4 (picker UX) — todlando builds in dedicated worktrees; (4) W2 keystone (translation-binary, ADR-0022) + W6 perri handoff still queued (the feature spine, not yet dispatched); (5) clean-VT-vs-win32-input-mode W7 follow-up investigation. ISOLATED WORKTREE spt-w7verify still exists at dc07c39 (clean up or reuse). Operator's running DAEMON is stale (no W1 fix) — wedge persists for them until a daemon rebuild+install+restart. rc = raw verbatim byte pump (spawn_stdin_reader rc.rs:152); ZERO console-mode setup in tree → Windows crossterm raw mode leaves ENABLE_VIRTUAL_TERMINAL_INPUT off → legacy console emits ^H (0x08) for Backspace not VT DEL (0x7f) → CC maps ^H→backward-kill-word. CONFIRM byte via SPT_RC_DEBUG_KEYS hexdump (HITL) BEFORE fix; fix = enable VT input on Win (preferred, fixes whole key map) or normalize 0x08→0x7f. Both folded to todlando (W1 widened + W7 sibling). Awaiting his root-confirm + byte before either patch.
