<task-notification>
<task-id>b3ok5tzh4</task-id>
Monitor event: "« spt event »"
<event><EVENT-PART seq="1/4" id="b629110c" type="msg" from="perri">Resolution confirmed — serving the seam-carrying copy, not the stale _github cache:
- Before re-add: `claude-spt: Harness Pointer active (from C:\...\adapters\_github\SaberMage-spt-claude-code)` (the stale 0.5.0).
- After `spt adapter add adapter/claude-spt.toml`: `claude-spt: Harness Pointer active (from adapte</EVENT-PART>
<EVENT-PART seq="2/4" id="b629110c">r)` — the pointer now resolves my repo's adapter/ dir (relative path, repo-root/adapter), live (Pointer type = resolved-through, not cached).
- CAVEAT worth noting: my [adapter].version is still &quot;0.5.0&quot; on BOTH copies (I add seams without a version bump yet), so a version string does NOT distinguish them — the SOURCE PATH is t</EVENT-PART>
<EVENT-PART seq="3/4" id="b629110c">he distinguisher, and it's now my repo. (I'll bump the manifest version when this rides a real adapter release.)

Second wiring signal, also green: `spt endpoint run --help` on 0.13.0 exposes `--resume &lt;RESUME&gt;` (&quot;Resume a prior session id instead of minting a fresh one&quot;, conflicts with --create) — the [session.resume] </EVENT-PART>
<EVENT-PART seq="4/4" id="b629110c">role-selection path is live.

Proceeding to the dogfood now (real spt-hosted bringup → resume reattach + idle-translate delivery). Result incoming.</EVENT-PART></event>
</task-notification>


<owl_reachability_notice>
You have an active owl perch. When spawning subagents or doing work, use run_in_background: true so you stay reachable for incoming messages.
</owl_reachability_notice>


CAVEMAN MODE ACTIVE (full). Drop articles/filler/pleasantries/hedging. Fragments OK. Code/commits/security: write normal.


Both wiring signals green: resolution serves her repo's `adapter/` (not the stale `_github` 0.5.0), and `--resume` surfaced in `spt endpoint run --help` (conflicts with `--create`) → `[session.resume]` path live. Version-collision caveat (both copies "0.5.0", path is the distinguisher) noted — bump on real adapter release is right.

Short ack; dogfood is the real gate.


Bash

$OWL send perri <<'EOF'
Both signals green — resolution serves your repo adapter/ (path-distinguished, not the stale _github 0.5.0), and --resume surfaced on `endpoint run` (conflicts --create) = [session.resume] live. Version-caveat acknowledged: two manifests both "0.5.0" so PATH is the only distinguisher right now — fine for dogfood, bump on the real adapter release. (Worth a mental note: anything that resolves a manifest by VERSION rather than path would shadow-pick the stale copy — not a blocker today, just don't rely on version to pick.) Dogfood is the gate — send the result. On-call.
EOF

Ack perri resolution + --resume signals; await dogfood


➜ SENT:perri


actually that's my mistake. 12.1 did publish, 12.2 did not.


Acked. Perri running the real dogfood (spt-hosted bringup → resume reattach + idle-translate delivery). On-call for the result — nothing else open. Standing by.


<task-notification>
<task-id>b3ok5tzh4</task-id>
Monitor event: "« spt event »"
<event><EVENT-PART seq="1/5" id="8bbde41c" type="msg" from="perri">Acked — and acting on the version-shadow note: bumping my [adapter].version off 0.5.0 now so nothing that resolves by version can shadow-pick the stale _github copy. Good catch.

GAP FOUND (DX/parity, not a blocker — your triage call):
There is no author-time proof command for [message-idle-translation-bina</EVENT-PART>
<EVENT-PART seq="2/5" id="8bbde41c">ry] analogous to `spt adapter digest-proof`. digest-proof (ADR-0019) lets an author validate the [digest] extractor against a sample WITHOUT a live session (&quot;the answer to 'spt endpoint digest returns nothing'&quot;). The symmetric question for the translation binary — &quot;does my idle-translation binary emit the right keystrokes for </EVENT-PART>
<EVENT-PART seq="3/5" id="8bbde41c">an &lt;EVENT&gt;, and does the daemon apply them?&quot; — has no lightweight proof: the ONLY way to validate is a full real-claude spt-hosted PTY bringup + `spt send` while idle.

Suggested shape (if you agree it's worth a todlando): `spt adapter translate-proof &lt;adapter&gt; --event '&lt;EVENT…&gt;'` that spawns the declared [mes</EVENT-PART>
<EVENT-PART seq="4/5" id="8bbde41c">sage-idle-translation-binary], feeds it the init+event JSON-lines, and prints the emitted {key/text/delay_ms} command stream (+ drops/parse errors) — the author-time mirror of digest-proof. Would let adapter authors verify the binary contract without a live agent. Point me at a doc section if you think this is already covered another way.<br</EVENT-PART>
<EVENT-PART seq="5/5" id="8bbde41c">>
Meanwhile I'll validate via the real-claude bringup path. Result incoming.</EVENT-PART></event>
</task-notification>


Perri found a DX/parity GAP (not a blocker): no author-time proof command for `[message-idle-translation-binary]` analogous to `spt adapter digest-proof` (ADR-0019). Proposed `spt adapter translate-proof`. Per triage protocol — classify with evidence, not memory. Verify the asymmetry against v0.13.0 source (origin/main d263a94; my local worktree is on c84daff which lacks the v0.13.0 merge).


git fetch origin main 2>&1 | tail -1; echo "=== digest-proof exists? ==="; git grep -nE "digest.proof|digest_proof|DigestProof" origin/main -- 'crates/spt/src/**' 2>&1 | head -15; echo "=== any translate/translation proof cmd? ==="; git grep -nE "translate.proof|translate_proof|translation.proof|TranslateProof" origin/main -- 'crates/spt/src/**' 2>&1 | head -15; echo "=== spt adapter subcommands (d263a94) ==="; git grep -nE "enum AdapterCmd|enum AdapterCommand|Subcommand" origin/main -- 'crates/spt/src/**' 2>&1 | head -10

Verify digest-proof exists, no translate-proof analog


 * branch            main       -> FETCH_HEAD
=== digest-proof exists? ===
origin/main:crates/spt/src/cli.rs:577:    DigestProof {
origin/main:crates/spt/src/cli.rs:5651:        AdapterCmd::DigestProof { option, sample, session } => {
origin/main:crates/spt/src/cli.rs:5652:            cmd_adapter_digest_proof(&adapters, &option, sample.as_deref(), session.as_deref())
origin/main:crates/spt/src/cli.rs:5949:/// `spt adapter digest-proof <adapter> [--sample <log>] [--session <id>]` — run
origin/main:crates/spt/src/cli.rs:5958:fn cmd_adapter_digest_proof(
origin/main:crates/spt/src/cli.rs:6015:                "  tip: digest-proof fills {{id}} and {{session_id}} (use --session <id> to pin \
origin/main:crates/spt/src/cli.rs:6026:    println!("=== digest-proof: {option} ===");
origin/main:crates/spt/src/cli.rs:8487:        match parse(&["spt", "adapter", "digest-proof", "claude-spt", "--sample", "log.jsonl"])
origin/main:crates/spt/src/cli.rs:8493:                action: AdapterCmd::DigestProof { option, sample, session },
origin/main:crates/spt/src/cli.rs:8499:            _ => panic!("expected Adapter DigestProof"),
origin/main:crates/spt/src/cli.rs:8503:    // [unit->REQ-TERM-5] digest-proof runs the declared extractor over a sample
origin/main:crates/spt/src/cli.rs:8507:    fn adapter_digest_proof_gates_on_drops() {
origin/main:crates/spt/src/cli.rs:8526:            cmd_adapter_digest_proof(&adapters, "cc", Some(sample.to_str().unwrap()), None)
origin/main:crates/spt/src/cli.rs:8555:            cmd_adapter_digest_proof(&adapters, "plain", Some(good.to_str().unwrap()), None),
origin/main:crates/spt/src/cli.rs:8561:    // [unit->REQ-TERM-5] digest-proof fills the SAME keys the daemon fills at
=== any translate/translation proof cmd? ===
=== spt adapter subcommands (d263a94) ===
origin/main:crates/spt/src/api/mod.rs:24:use clap::{Args, Subcommand};
origin/main:crates/spt/src/api/mod.rs:54:#[derive(Subcommand)]
origin/main:crates/spt/src/cli.rs:17:use clap::{Parser, Subcommand};
origin/main:crates/spt/src/cli.rs:59:#[derive(Subcommand)]
origin/main:crates/spt/src/cli.rs:226:#[derive(Subcommand)]
origin/main:crates/spt/src/cli.rs:415:#[derive(Subcommand)]
origin/main:crates/spt/src/cli.rs:435:#[derive(Subcommand)]
origin/main:crates/spt/src/cli.rs:480:#[derive(Subcommand)]
origin/main:crates/spt/src/cli.rs:499:#[derive(Subcommand)]
origin/main:crates/spt/src/cli.rs:500:enum AdapterCmd {


Verified — the asymmetry is real:
- `digest-proof` EXISTS (`AdapterCmd::DigestProof`, `cmd_adapter_digest_proof`, cli.rs:577/5651, REQ-TERM-5/ADR-0019).
- **No** translate/translation proof command anywhere (empty grep).

Genuine **case-3** (missing feature for DX/parity) per the triage protocol — and a legit harness-agnostic primitive (proof for a manifest contract, mirrors digest-proof), fine for spt-core surface. Confirming to perri + dispatching todlando with the design (as a v0.13.x DX follow-on, non-blocking).


$OWL send perri <<'EOF'
TRIAGE: confirmed case-3 (real DX/parity gap), not docs. Verified vs v0.13.0 source (origin/main d263a94): digest-proof exists (AdapterCmd::DigestProof, cmd_adapter_digest_proof, REQ-TERM-5/ADR-0019); ZERO translate/translation-proof analog. Your proposed shape is right and it's a legit harness-agnostic primitive (proof for a manifest contract, mirrors digest-proof) — good for spt-core surface.

Dispatching todlando to build `spt adapter translate-proof` as a v0.13.x DX follow-on (non-blocking — keep validating via the real bringup now). SCOPE NOTE so expectations match: like digest-proof, it proves the EMIT half (your binary spawned + fed the daemon's exact init+EVENT JSON-lines → prints the {key/text/delay_ms} stream + drops/parse errors/nonzero-exit). It canNOT prove the daemon's atomic PTY APPLY half without a live session — that stays covered by the int gate + your real bringup. So translate-proof = "does my binary emit the right commands for this EVENT," the author-time mirror of digest-proof. Sound right? Flag if you expected the apply half in-scope.

Send your dogfood result when it lands; I'll fold any further gaps.
EOF
echo "---"
$OWL send todlando <<'EOF'
NEW DISPATCH (v0.13.x DX follow-on, NON-blocking — v0.13.0 already shipped clean). perri found a real DX/parity gap, I triaged it case-3 + verified vs source.

GAP: [message-idle-translation-binary] (ADR-0022, just shipped) has NO author-time proof command, unlike [digest] which has `spt adapter digest-proof` (ADR-0019, cmd_adapter_digest_proof @ cli.rs:5958, REQ-TERM-5). An adapter author can only validate their idle-translation binary via a full real-claude spt-hosted PTY bringup + `spt send` while idle. We want the symmetric author-time tool.

BUILD: `spt adapter translate-proof <adapter> --event '<EVENT…>' [--session <id>]`
- Resolve the adapter's [message-idle-translation-binary] (mirror how digest-proof resolves [digest]).
- Spawn + feed it EXACTLY as the daemon does at idle-delivery: same init JSON-line then the EVENT JSON-line(s). CRITICAL: reuse the REAL daemon-side driver/framing code (the W2 Layer B/C translation-binary driver), do NOT reimplement the protocol in the CLI — digest-proof's whole value is it runs the REAL extractor; a drifting reimpl would prove the wrong thing.
- Read stdout, print the emitted {key}/{text}/{delay_ms} command stream in author-readable form; surface parse errors, dropped/invalid records, and nonzero exit.
- Gate like digest-proof: nonzero exit if the binary errors / emits nothing / unparseable.
- Fill template keys ({id}/{session_id}) the same way digest-proof does (--session to pin).
- SCOPE: EMIT half only (author-time, no live session). It does NOT exercise the daemon's atomic PTY apply — say so in the --help so it doesn't overstate (apply stays covered by the W2 int gate).

TRACEABLE: new requirement → add a REQ (e.g. REQ-ADAPTER-TRANSLATE-PROOF) to traceable-reqs.toml FIRST, then satisfy (doc+impl+unit; an int if you can drive a sample binary). Branch off origin/main d263a94 (NOT the operator's worktree, they're on c84daff). Docs-drift gate: regen the CLI reference (xtask gen), keep M#/W#/REQ out of the clap help.

Ground in digest-proof's shape (cli.rs:5949-6026) + the ADR-0022 binary protocol before you design the exact arg surface; ping me your JIT plan or just build it and I'll gate. No rush — fold it whenever; v0.13.0 is out.
EOF

Confirm gap to perri; dispatch translate-proof build to todlando


➜ SENT:perri
---
➜ SENT:todlando


Both dispatched. **Status for you:**
- v0.13.0 shipped clean; perri's wiring validation green so far (resolver serves her repo manifest, `--resume` surfaced, validator accepts both new tables).
- perri found a DX/parity gap (not a blocker): `[message-idle-translation-binary]` has no author-time proof command, unlike `[digest]`'s `spt adapter digest-proof`. I verified the asymmetry against v0.13.0 source (case-3), confirmed it to perri, and **dispatched todlando to build `spt adapter translate-proof`** as a non-blocking v0.13.x follow-on (mint REQ, branch off d263a94, I gate). Flagged scope: emit-half proof only (mirrors digest-proof), not the daemon apply half.

Awaiting perri's real-bringup dogfood result + todlando's translate-proof. Nothing blocking. Standing by.


<task-notification>
<task-id>b3ok5tzh4</task-id>
Monitor event: "« spt event »"
<event><EVENT-PART seq="1/5" id="37fc0018" type="msg" from="todlando">JIT PLAN (translate-proof) — grounded vs source, will build &amp; ping you to gate. No blocker.

Branch feat/translate-proof off origin/main d263a94 (worktree spt-core-translate-proof; NOT operator's c84daff). Plan written to TRANSLATE-PROOF-JIT-PLAN.md.

Shape: mirror cmd_adapter_digest_proof (cli.rs:5</EVENT-PART>
<EVENT-PART seq="2/5" id="37fc0018">958, clap variant :577, dispatch :5651) but drive the REAL spt_daemon::translation driver — TranslationChild::spawn + send(Init) + send(Event{envelope}) + drain the KeyCmd channel; print {key}(+key_to_bytes)/{text}/{delay_ms}/{commit} author-readable; gate exit 1 on spawn-fail/empty/unparseable, exit 2 no-section. NO protocol reimpl (reuse t</EVENT-PART>
<EVENT-PART seq="3/5" id="37fc0018">ranslation.rs verbatim, copying the daemon call sites broker.rs:1548/:1552/:1044 + harnesshost.rs:143 for path-resolve + Init build). EMIT-half only; --help says it does NOT exercise the atomic PTY apply (W2 int still owns that).

Traceability: REQ-ADAPTER-TRANSLATE-PROOF added to traceable-reqs.toml FIRST, stages doc+impl+unit+int. Int </EVENT-PART>
<EVENT-PART seq="4/5" id="37fc0018">is feasible — xlate_choreo_fixture (CARGO_BIN_EXE) is the sample binary, emits the full choreo stream on {type:event}. Docs: ADR-0022 subsection + CLI-ref regen (xtask gen), M#/W#/REQ kept out of clap help.

Context is heavy from the wedge saga — communing + self-clearing to execute fresh per project workflow. Will land it and ping f</EVENT-PART>
<EVENT-PART seq="5/5" id="37fc0018">or your gate. (You said no rush; v0.13.0 is out.)</EVENT-PART></event>
</task-notification>


todlando's JIT plan nails every condition + grounds it in real call sites:
- Branch off d263a94, own worktree ✓
- Drives the REAL `spt_daemon::translation` driver (`TranslationChild::spawn` + Init + Event + drain KeyCmd), reusing `translation.rs` verbatim + copying daemon call sites (broker.rs:1548/:1552/:1044, harnesshost.rs:143) — **no protocol reimpl**, exactly the anti-drift criterion ✓
- EMIT-half only, --help disclaims the apply half ✓
- REQ-ADAPTER-TRANSLATE-PROOF first, doc+impl+unit+int; int via `xlate_choreo_fixture` as sample binary ✓
- CLI-ref regen, clap-help clean ✓

Approving — build it. (Note: the xlate_choreo_fixture XOFF bug was PTY-echo-only; irrelevant to the EMIT-half proof, so it's a clean sample.)


$OWL send todlando <<'EOF'
PLAN APPROVED — GO build. Hits every condition, and the grounding is exactly right: reuse translation.rs verbatim + copy the real daemon call sites (broker.rs:1548/:1552/:1044, harnesshost.rs:143) so the proof drives the SAME path the daemon does — that anti-drift fidelity is the whole point (it's why digest-proof is trustworthy). EMIT-half scope + --help disclaimer correct; REQ-first + int via xlate_choreo_fixture good. Minor FYI: the xlate_choreo_fixture XOFF-strand bug was PTY-echo-only (g2), irrelevant to an EMIT-half proof with no PTY — clean sample, proceed. Self-clear + execute fresh as planned; ping me when landed and I'll gate (full read + non-vacuous int verify). No rush.
EOF

Approve todlando translate-proof JIT plan


➜ SENT:todlando


Plan approved — todlando self-clears + builds `translate-proof`, will ping for my gate.

**Two async threads open:**
1. perri's real-bringup dogfood (resume reattach + idle-translate delivery) → gap-fold or int-promotion.
2. todlando's `translate-proof` build → my gate (full read + non-vacuous int verify).

Both non-blocking; v0.13.0 is out. Nothing actionable until one reports. Standing by.


<command-message>grill-me</command-message>
<command-name>/grill-me</command-name>
<command-args>over the v0.13.0 changelog. but ideally no grilling needed -- some of the lines aren't quite right. please check them against the design (CONTEXT.md) and the code, then let's go point-by-point with your suggested changes.</command-args>


Base directory for this skill: C:\Users\decid\.ccs\instances\bigscreen\skills\grill-me

Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.

Ask the questions one at a time.

If a question can be answered by exploring the codebase, explore the codebase instead.

ARGUMENTS: over the v0.13.0 changelog. but ideally no grilling needed -- some of the lines aren't quite right. please check them against the design (CONTEXT.md) and the code, then let's go point-by-point with your suggested changes.


v0.13.0 is already published — so any line fix is post-publish (docs-only: `CHANGELOG.md` on main + `gh release edit` notes, no retag). Let me ground the bullets against the *shipped* state (origin/main `d263a94`; the local worktree is on `c84daff` which diverged) — CONTEXT.md design + the actual commit scopes — before proposing changes.

Reading the shipped CHANGELOG myself + dispatching an Explore agent to pull verbatim CONTEXT.md wording and exact commit scopes.


Read shipped v0.13.0 CHANGELOG section


## [0.13.0] - 2026-06-21

A minor release: messages reach a hosted agent even when it's idle, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, agents can resume into their prior session, and the daemon no longer flashes a console window.

### Added

- **Messages now reach a hosted agent that isn't actively reading.** An adapter can declare a `[message-idle-translation-binary]`; when a message arrives for a daemon-hosted agent sitting idle at its prompt, the daemon injects it through that binary instead of leaving it unseen until the agent next reads.
- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
- **Windows special keys in `spt rc`.** Arrow keys, Home/End, Delete, function keys and other special keys are translated to terminal sequences and reach the agent — previously only plain characters got through.
- **`spt rc` forwards mouse scroll** to the agent's terminal.
- **Agents can resume into their previous session.** An adapter can declare a `[session.resume]` native-resume role so relaunching an agent reattaches its prior session instead of starting cold; the resume picker now shows each row's working directory and local-time title.

### Fixed

- **Pasting or typing into a busy agent no longer freezes the daemon.** A large paste or input burst against a hosted agent could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).
- **`spt rc --view` viewers survive a high-output agent.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.
- **`spt rc` no longer races a just-started agent.** Attach now waits for the endpoint to come online, instead of failing when you attach immediately after `spt endpoint run`.
- **The daemon no longer flashes or respawns a console window on Windows.**
- **Windows Backspace and Ctrl+Backspace now behave correctly in `spt rc`** — character-delete and word-delete, no longer swapped.

### Changed

- **The `spt endpoint run` picker is clearer.** It opens directly on an existing pick, auto-attaches, shows the controlling node name, and produces clean bring-up output.
- **Human-prose command output renders Markdown.** Prose output (how-to topics and similar) now shows styled headers and emphasis in a terminal and clean plain text when piped — matching the v0.12.1 `--help` fix.

## [0.12.1] - 2026-06-18


Agent

Ground v0.13.0 changelog vs design+code

Prompt:
I'm fact-checking the v0.13.0 CHANGELOG of the `spt` CLI (Rust project spt-core) against the authoritative design (CONTEXT.md) and the actual code/commits. The shipped state is git ref `d263a94` (origin/main). The local working tree is on a DIVERGED commit (c84daff), so DO NOT read working-tree files — read everything from d263a94 via `git show d263a94:<path>` and inspect commits via `git show <sha>` / `git log`.

For EACH topic below, return: (a) the authoritative term/wording CONTEXT.md uses, quoted VERBATIM with the file:line; (b) the precise user-facing scope of the cited commit(s) from their diff — what actually changed, in what command/surface, on what platform. Be precise about wording nuances (these feed changelog corrections). Quote, don't paraphrase, where wording matters.

TOPICS:

1. IDLE MESSAGE DELIVERY / translation binary (ADR-0022). Commits: c73eb6a, 611205c, 7166f52, 79f5a40, f9fe5bb, 5b51cb5. Questions: What is the EXACT trigger condition CONTEXT.md/ADR-0022 defines for routing a message through the `[message-idle-translation-binary]` — is it "agent is idle / not actively reading", a commit-deadline, a controller-present check, or something else? What does CONTEXT.md call this feature (exact name)? Does it apply to ALL hosted agents or only ones declaring the table? Quote the CONTEXT.md/ADR passage.

2. SESSION RESUME (REQ-SESSION-RESUME-TEMPLATE). Commits: 153c9c9, b30b4a6, 96d0780, 52cd081. Questions: What does CONTEXT.md call `[session.resume]` (a "role"? a "template"? a manifest table?) and what exactly does it do? Is "native-resume role" accurate? What exactly did the picker change — per-row cwd, local-time title, dropped tz token? Quote.

3. CONTROLLER/VIEWER hardening. Commits: 677c3e7 (b4 decouple), ff2e3ab (skip-to-live), d79f02e (viewer snap forward gap), f0c2ee0 (controller resume-from-floor), 9b0025b + 0dc7018 (controller-writer reorder). Questions: Precisely, what does a VIEWER do now on (i) eviction and (ii) ring-roll-behind forward gap — "skip to live" vs "snap forward"? What does a CONTROLLER do when it falls behind (resume-from-floor / ControllerIrrecoverablyBehind)? Is the claim "a slow controller can no longer starve a concurrent viewer" exactly what 677c3e7 (b4) did? Does CONTEXT.md define controller vs viewer (one blocking controller, exactly-once)? Quote the CONTEXT controller/viewer model lines.

4. WINDOWS rc INPUT. Commits: f7cf380 (ctrl+V/right-click paste), bf32b8c (key→xterm VT translator), 394fc5e (input-flood ack deadlock + ctrl+V→WT-native + forward scroll, REQ-RC-MOUSE-FORWARD), dc07c39/fbd6c98/95f742f (W7 backspace/ctrl+backspace). Questions: Does the key-VT translator explicitly cover Delete/arrows/Home/End/Fn (list what the diff handles)? For backspace: what was the actual bug and fix — 95f742f says "SWAP Windows delete bytes so Ctrl+Backspace = word-delete" and fbd6c98 "narrow-normalize Backspace 0x08->0x7f"; is "Backspace and Ctrl+Backspace no longer swapped" an accurate description, or is the fix something else (normalize 0x08->0x7f, swap delete bytes)? Quote the commit messages + key diff lines.

5. HELP/PROSE MARKDOWN. Commits: 2435a74 (route human-prose command OUTPUT through help Markdown renderer), b3bb387 (render ATX # headers). Question: confirm v0.13.0 EXTENDS the renderer to prose command output (the --help renderer itself shipped in v0.12.1). What surfaces exactly?

6. DAEMON CONSOLE WINDOW. Commits: 082f5ed (broker FreeConsole self-detach, REQ-HAZARD-WMI-DAEMON-WINDOW reopened), 15fdf58 (daemon start no console window, v0.12.1 WMI regression). Question: precise scope — does the daemon "flash" a window, "respawn" one, both? Platform? Quote.

Return a tight per-topic report. Verbatim quotes + file:line / sha. No recommendations — just the ground truth.


<owl_reachability_notice>
You have an active owl perch. Launch this Agent with run_in_background: true so you stay reachable for incoming messages while it works.
</owl_reachability_notice>


Async agent launched successfully.
agentId: a3a0b8a98a10aecba (internal ID - do not mention to user. Use SendMessage with to: 'a3a0b8a98a10aecba' to continue this agent.)
The agent is working in the background. You will be notified automatically when it completes.
Do not duplicate this agent's work — avoid working with the same files or topics it is using. Work on non-overlapping tasks, or briefly tell the user what you launched and end your response.
output_file: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\9d0930b3-34c1-4dce-943f-72ccdc8fb726\tasks\a3a0b8a98a10aecba.output
Do NOT Read or tail this file via the shell tool — it is the full subagent JSONL transcript and reading it will overflow your context. If the user asks for progress, say the agent is still running; you'll get a completion notification.

Ground v0.13.0 changelog vs design+code

Prompt:
I'm fact-checking the v0.13.0 CHANGELOG of the `spt` CLI (Rust project spt-core) against the authoritative design (CONTEXT.md) and the actual code/commits. The shipped state is git ref `d263a94` (origin/main). The local working tree is on a DIVERGED commit (c84daff), so DO NOT read working-tree files — read everything from d263a94 via `git show d263a94:<path>` and inspect commits via `git show <sha>` / `git log`.

For EACH topic below, return: (a) the authoritative term/wording CONTEXT.md uses, quoted VERBATIM with the file:line; (b) the precise user-facing scope of the cited commit(s) from their diff — what actually changed, in what command/surface, on what platform. Be precise about wording nuances (these feed changelog corrections). Quote, don't paraphrase, where wording matters.

TOPICS:

1. IDLE MESSAGE DELIVERY / translation binary (ADR-0022). Commits: c73eb6a, 611205c, 7166f52, 79f5a40, f9fe5bb, 5b51cb5. Questions: What is the EXACT trigger condition CONTEXT.md/ADR-0022 defines for routing a message through the `[message-idle-translation-binary]` — is it "agent is idle / not actively reading", a commit-deadline, a controller-present check, or something else? What does CONTEXT.md call this feature (exact name)? Does it apply to ALL hosted agents or only ones declaring the table? Quote the CONTEXT.md/ADR passage.

2. SESSION RESUME (REQ-SESSION-RESUME-TEMPLATE). Commits: 153c9c9, b30b4a6, 96d0780, 52cd081. Questions: What does CONTEXT.md call `[session.resume]` (a "role"? a "template"? a manifest table?) and what exactly does it do? Is "native-resume role" accurate? What exactly did the picker change — per-row cwd, local-time title, dropped tz token? Quote.

3. CONTROLLER/VIEWER hardening. Commits: 677c3e7 (b4 decouple), ff2e3ab (skip-to-live), d79f02e (viewer snap forward gap), f0c2ee0 (controller resume-from-floor), 9b0025b + 0dc7018 (controller-writer reorder). Questions: Precisely, what does a VIEWER do now on (i) eviction and (ii) ring-roll-behind forward gap — "skip to live" vs "snap forward"? What does a CONTROLLER do when it falls behind (resume-from-floor / ControllerIrrecoverablyBehind)? Is the claim "a slow controller can no longer starve a concurrent viewer" exactly what 677c3e7 (b4) did? Does CONTEXT.md define controller vs viewer (one blocking controller, exactly-once)? Quote the CONTEXT controller/viewer model lines.

4. WINDOWS rc INPUT. Commits: f7cf380 (ctrl+V/right-click paste), bf32b8c (key→xterm VT translator), 394fc5e (input-flood ack deadlock + ctrl+V→WT-native + forward scroll, REQ-RC-MOUSE-FORWARD), dc07c39/fbd6c98/95f742f (W7 backspace/ctrl+backspace). Questions: Does the key-VT translator explicitly cover Delete/arrows/Home/End/Fn (list what the diff handles)? For backspace: what was the actual bug and fix — 95f742f says "SWAP Windows delete bytes so Ctrl+Backspace = word-delete" and fbd6c98 "narrow-normalize Backspace 0x08->0x7f"; is "Backspace and Ctrl+Backspace no longer swapped" an accurate description, or is the fix something else (normalize 0x08->0x7f, swap delete bytes)? Quote the commit messages + key diff lines.

5. HELP/PROSE MARKDOWN. Commits: 2435a74 (route human-prose command OUTPUT through help Markdown renderer), b3bb387 (render ATX # headers). Question: confirm v0.13.0 EXTENDS the renderer to prose command output (the --help renderer itself shipped in v0.12.1). What surfaces exactly?

6. DAEMON CONSOLE WINDOW. Commits: 082f5ed (broker FreeConsole self-detach, REQ-HAZARD-WMI-DAEMON-WINDOW reopened), 15fdf58 (daemon start no console window, v0.12.1 WMI regression). Question: precise scope — does the daemon "flash" a window, "respawn" one, both? Platform? Quote.

Return a tight per-topic report. Verbatim quotes + file:line / sha. No recommendations — just the ground truth.


/grill-me over the v0.13.0 changelog. but ideally no grilling needed -- some of the lines aren't quite right. please check them against the design (CONTEXT.md) and the code, then let's go point-by-poi…


Shipped CHANGELOG captured (matches the published release notes). Explore agent grounding each bullet against CONTEXT.md + commit diffs (running in background — I stay reachable for perri/todlando).

My pre-read suspicions on which lines aren't quite right (to confirm against evidence):
- **#10 Backspace** — fix was "swap delete bytes so Ctrl+Backspace = word-delete" + "normalize 0x08→0x7f"; "no longer swapped" may invert the actual mechanism.
- **#5 session.resume** — "native-resume role" wording may not match CONTEXT's term (table vs role vs template).
- **#1 idle delivery** — "sitting idle at its prompt, not actively reading" may be looser than the real trigger (commit-deadline / InjectFloor).
- **#7 viewer** — "snaps forward or skips to live" conflates two distinct mechanisms (eviction→skip-to-live vs ring-roll→snap-forward); controller resume-from-floor unmentioned.

Holding the point-by-point until the agent returns verbatim ground truth. Standing by.


<task-notification>
<task-id>a3a0b8a98a10aecba</task-id>
<tool-use-id>toolu_01EcdsuNRKgojP2Fo3fQaWRK</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\9d0930b3-34c1-4dce-943f-72ccdc8fb726\tasks\a3a0b8a98a10aecba.output</output-file>
<status>completed</status>
<summary>Agent "Ground v0.13.0 changelog vs design+code" came to rest</summary>
<note>A task-notification fires each time this agent comes to rest with no live background children of its own. The user can send it another message and resume it, so the same task-id may notify more than once.</note>
<result>Now I have all the information. Let me compile my findings:

---

## Fact-Check Report: v0.13.0 CHANGELOG Against CONTEXT.md, ADRs, and Commits

### 1. IDLE MESSAGE DELIVERY / translation binary (ADR-0022)

**Authoritative Term & Trigger Condition (CONTEXT.md:39):**
> "Idle delivery into an spt-hosted PTY goes through an opt-in adapter **translation binary** (`[message-idle-translation-binary]`, ADR-0022): a pure stdin→stdout filter spt-core lifecycle-manages — it reads the `<EVENT>` feed on stdin, emits keystroke-commands (`{key}`/`{delay_ms}`/`{text}`) on stdout, and spt-core applies them to the PTY **atomically** (controller input buffered during the sequence, so injection coexists with a live `spt rc`). The v0.11.0 raw `payload+\r` inject is the degenerate no-choreography case."

CONTEXT.md:39 defines the trigger as **"agent is idle"** — the binary reads a content-free ping (`{type:"input"}`) to track "user-idle state" (ADR-0022 section "stdin", "a content-free ping each time the operator types, so the binary can track user-idle state"). The translation binary itself decides idle gating via its own buffering — **not a commit-deadline, controller presence, or hardcoded spt-core condition**. Feature name: **"translation binary"** (or `[message-idle-translation-binary]` — the manifest table name).

**User-Facing Scope of Commits:**
- **c73eb6a**: Manifest field `IdleTranslationBinary{path}` + schema validation. Cargo gate: `REQ-MSG-IDLE-TRANSLATION-BINARY [doc->impl->unit]`.
- **611205c**: Daemon protocol + child lifecycle (ToBinary JSON stdin, KeyCmd stdout, send-keys byte map, bounded reap).
- **7166f52, 79f5a40, f9fe5bb, 5b51cb5**: Brokers integration (spt-core applies keystroke sequence atomically to PTY, controller input buffered during sequence).

**Applies to:** spt-hosted endpoints **declaring** `[message-idle-translation-binary]` in their manifest (opt-in).

---

### 2. SESSION RESUME (REQ-SESSION-RESUME-TEMPLATE)

**Authoritative Term (docs/MANIFEST.md:97):**
> "**`[session.resume]` — the agent's own-session NATIVE resume.** `self` is the agent's own session; `resume` is its native-resume sibling (mirroring `psyche_init`→`psyche_resume`). spt-core selects `[session.resume]` over `[session.self]` **only** when a bringup carries a prior session (`spt endpoint run --resume <session>`, or the picker's *Resume from history*) **and** the adapter declares the role. An adapter with **no** `[session.resume]` falls back to `[session.self]` (full back-compat)."

This is a **manifest role** (a section like `[session.self]`, not a "template" in prose). **"native-resume role"** is accurate — the manifest-declared role that the adapter uses for native resume (e.g., Claude Code's `claude -r <session_id> …`).

**Picker Changes (153c9c9):**
- **Per-row cwd:** `SessionEntry.cwd` added (serde-default None; written at boundary/bind/ready; old rows deserialize as None).
- **Local-time title:** `ResumeRow::title()` reformatted to local time with `%z` offset (chrono `%Z` unreliable cross-platform).
- **No dropped tz token:** The `%z` offset is the timezone representation in the picker title.
- **Template selection:** `prepare_harness_spawn(is_resume)` selects `[session.resume]` when `is_resume=true` AND declared; else falls back to `[session.self]` (full back-compat).

---

### 3. CONTROLLER/VIEWER Hardening

**Authoritative Model Definition (CONTEXT.md:343):**
> "The broker's per-session `OutputLog` is the fan-out hub: ONE authoritative **controller** (advances the brain-resume cursor `delivered_through`) plus ANY NUMBER of read-only **viewers**, each an isolated bounded queue + writer thread evicted on overflow (a wedged viewer never stalls the drain, controller, or child — `REQ-HAZARD-VIEWER-ISOLATION`). The controller is **no longer a *blocking* writer**: since b4 it is a NON-BLOCKING `try_send` that DROPS on a full channel (`CONTROLLER_CHANNEL_DEPTH`), so a slow controller can never throttle the drain and starve a concurrent viewer (`REQ-HAZARD-VIEWER-STARVE-UNDER-CONTROLLER-BACKPRESSURE`). Exactly-once for the controller is preserved by RE-FETCH, not by blocking: a controller that falls behind its own echo and drops frames hits a forward `output gap`, and the serve loop RESUMES-FROM-FLOOR — re-subscribes from the frozen `delivered_through` so the broker replays the dropped frames from the ring (`REQ-HAZARD-CONTROLLER-GAP-RESUME`, a re-fetch — NOT the viewer's snap, which would skip frames and violate the controller's exactly-once resume)... An evicted viewer **skips to live** instead of dying silently: the broker signals the eviction (a marker distinct from session-exit EOF) and the viewer re-subscribes from the current ring floor — rate-limited so a hopelessly-behind `--view` under a sustained output flood sees intermittent live bursts (tail -f reconnect), never a frozen viewport or an evict→resubscribe CPU spin. Viewer-only, so it never touches the authoritative resume cursor (`REQ-VIEWER-SKIP-TO-LIVE-ON-EVICT`)... A viewer also tolerates a forward ring-roll gap **before** any eviction: if it falls behind the live ring under a hard flood and reads a seq past its cursor (the ring rolled the intervening frames out between reads, with no eviction marker), it **snaps to that live seq** (accept-and-advance via snap-above, armed at the initial viewer attach) instead of fataling on the gap — composing with skip-to-live, which recovers *after* eviction, and staying viewer-only so the controller keeps its strict exactly-once reject-gap (`REQ-HAZARD-VIEWER-RING-ROLL-SNAP`)."

**Precise Behavior:**
- **Viewer on eviction:** **skips to live** (re-subscribes from ring floor, rate-limited 200ms); signals a KIND_VIEWER_EVICTED marker (distinct from EOF).
- **Viewer on ring-roll forward gap (pre-eviction):** **snaps to that live seq** (accept-and-advance via snap-above cursor, armed at initial attach); does NOT fatal; stays subscribed.
- **Controller on gap:** **resumes-from-floor** (re-fetches from broker's frozen `delivered_through`, replays dropped frames from ring); does NOT snap (snap-above is viewer-only, would violate exactly-once).

**Claim Accuracy:** "a slow controller can no longer starve a concurrent viewer" — **YES, exact.** 677c3e7 (b4) changed controller from **blocking** `try_send` with sleep-poll to **non-blocking** `try_send` that DROPS on full channel (end result: drop-on-full, drain no longer sleeps, viewer receives output in real-time).

**Controller Model (CONTEXT.md:343):** ONE authoritative controller (advances `delivered_through`), exactly-once via re-fetch (RESUMES-FROM-FLOOR), blocking **before b4** (sleep-poll), non-blocking **after b4** (try_send DROPS). **Viewer model:** read-only, never advances `delivered_through`, isolated bounded queue, evicted on overflow (SKIP-TO-LIVE or SNAP-ABOVE).

**Commits & Scope:**
- **677c3e7 (b4 decouple):** Controller delivery non-blocking try_send (DROPS on full), drain never sleeps.
- **ff2e3ab (skip-to-live):** Viewer eviction signal + re-subscribe from floor, rate-limited.
- **d79f02e (viewer snap forward gap):** Viewer snaps pre-eviction ring-roll gaps via snap-above cursor.
- **f0c2ee0 (controller resume-from-floor):** Controller re-fetches from `delivered_through` on gap, replays ring.
- **9b0025b + 0dc7018 (controller-writer reorder):** Epoch gate for controller_writer initial-batch, dedup-cursor reset on re-subscribe (P1b race fix).

---

### 4. WINDOWS rc INPUT

**Key-VT Translator Coverage (bf32b8c commit message + diff):**
> "Backspace / Ctrl+Backspace — the W7 swap, native in the translator."

```c
KeyCode::Backspace => vec![if ctrl { 0x08 } else { 0x7f }],
KeyCode::Delete => csi_tilde(3, modp),
KeyCode::Insert => csi_tilde(2, modp),
KeyCode::PageUp => csi_tilde(5, modp),
KeyCode::PageDown => csi_tilde(6, modp),
KeyCode::Up => csi_final(b'A', modp),
KeyCode::Down => csi_final(b'B', modp),
KeyCode::Right => csi_final(b'C', modp),
KeyCode::Left => csi_final(b'D', modp),
KeyCode::Home => csi_final(b'H', modp),
KeyCode::End => csi_final(b'F', modp),
KeyCode::F(n) => f_key(n, modp),
```

**Explicit Coverage:** Backspace/Ctrl+Backspace (swap), Delete, Insert, Home, End, arrows (Up/Down/Right/Left), PgUp/PgDn, F-keys.

**Backspace/Ctrl+Backspace History & Fix:**
- **dc07c39 (W7):** Enabled ENABLE_VIRTUAL_TERMINAL_INPUT → Backspace=0x7f (char-delete), Ctrl+Backspace=0x08 (word-delete) — **broke detach** (0x02 wrapped in win32-input-mode, never seen raw).
- **fbd6c98 (W7 reverted):** Reverted VT-input, narrow-normalize: stayed raw byte pump, `0x08 -> 0x7f` one-way in `normalize_key_byte` AFTER detach state machine consumes 0x02. Result: Backspace=char-delete, Ctrl+Backspace stayed char-delete (word-delete lost).
- **95f742f (W7 SWAP):** Upgraded one-way normalize to **SWAP** (`0x08 <-> 0x7f`). Commit message: "One-way 0x08->0x7f map upgraded to a SWAP (0x08<->0x7f). CC reads ^H as backward-kill-word and DEL as char-delete, so swapping the input bytes gives Backspace=char-delete AND Ctrl+Backspace=word-delete (native Win11)."
- **bf32b8c (key-VT translator):** Backspace/Ctrl+Backspace **native in the translator** (not normalize_key_byte, which is superseded): `if ctrl { 0x08 } else { 0x7f }`.

**Accurate Description:** "Backspace and Ctrl+Backspace no longer swapped" is **INCORRECT**. The fix is: **swap the input bytes** (0x08 <-> 0x7f) via **either** a one-way normalize with a SWAP operation (fbd6c98 thru bf32b8c historical path) **or** natively in the key-VT translator (bf32b8c final). Current state (bf32b8c): Backspace→0x7f, Ctrl+Backspace→0x08 (the translator's conditional). This is **"swap bytes so Ctrl+Backspace becomes word-delete"**, not "no longer swapped".

---

### 5. HELP/PROSE MARKDOWN

**Authoritative Scope (2435a74 commit message):**
> "REQ-CLI-HELP-MARKDOWN only hooked clap `--help`, so command OUTPUT still printed raw Markdown (how-to topic text, subnet status hint footers, the daemon "not running" line, the ENDPOINT_RUN_STARTED attach hint, the daemon's SUBNET_DETACHED startup line — 13 prose surfaces). Apply the same pure, line-bounded `helpfmt::render` at each emit site, color-gated by the OUTPUT STREAM's own tty."

**Surfaces Rendered in v0.13.0:**
- `cmd_how_to` (topics header, topic text, NO_SUCH_TOPIC error)
- `render_subnet_status` (HINT_FOOTER, standalone_text, pump_stall_warning, daemon_offline_hint, inbound_block_hint)
- Daemon-status "not running" line
- ENDPOINT_RUN_STARTED hint
- SUBNET_DETACHED startup line

**Extension Claim:** v0.12.1 shipped `REQ-CLI-HELP-MARKDOWN` on clap `--help` only. v0.13.0 **extends** the renderer to prose command OUTPUT (the 13 surfaces above). The renderer itself (bold/**`code`**/**[links]** + v0.13.0 ATX headers) applies to all surfaces consistently.

**b3bb387:** Adds ATX header support (`#{1,6} ` → strip marker, bold in color mode). Closes the last raw-marker in how-to output (headers showed raw `#` post-2435a74 because the renderer didn't handle them yet).

---

### 6. DAEMON CONSOLE WINDOW

**Scope & Platform (082f5ed + 15fdf58):**

**15fdf58 (v0.12.1 regression):**
> "the WMI job-neutral daemon launch set CREATE_NO_WINDOW on the launching powershell but NOT on the Win32_Process.Create call — which does not inherit it — so the spawned cmd.exe env-forwarding wrapper popped a console window on every `spt daemon start`."
>
> "FIX: pass a Win32_ProcessStartup (CreateFlags=DETACHED_PROCESS 0x8 — no console, hence no window — + ShowWindow=SW_HIDE) as ProcessStartupInformation."

**Precise Scope:** Windows; the daemon wrapper (WMI job-neutral launch path via `cmd.exe`) was **respawning** a console window (popping a visible window each time `spt daemon start` ran). Platform: **Windows only** (Win32_Process, ConPTY).

**082f5ed (v0.12.2 insufficient fix):**
> "The v0.12.2 fix (@15fdf58) was INSUFFICIENT. It set DETACHED_PROCESS on the cmd WRAPPER, but the WMI/schtasks rungs run `cmd /c set… & start "" /b spt daemon run`, and `start /b` then launches the inner BROKER (a console-subsystem exe) with no console to inherit — so the broker ALLOCATES ITS OWN conhost = a visible window."
>
> "FIX (broker self-detach, launch-agnostic): the auto-start ladder appends a hidden `--detached` flag to the daemon-run args (spawn_detached, every rung); cmd_daemon_run calls daemon::detach_console() at startup when set — FreeConsole() then NULLs the three std handles."

**Precise Scope:** Windows; both **respawn** (15fdf58: wrapper window on each `daemon start`) **and** **flash** (082f5ed: broker allocating conhost window during startup on auto-start paths). 082f5ed is the full fix (broker self-detach via FreeConsole).

---

**Summary Table**

| Topic | CONTEXT.md Authority | Commit Scope | Wording Notes |
|-------|---------------------|--------------|---|
| 1. Idle Translation Binary | CONTEXT.md:39; ADR-0022 Scope | c73eb6a (manifest), 611205c (protocol) | Feature: "translation binary"; trigger: agent idle (binary-decided via content-free ping tracking) |
| 2. Session Resume | MANIFEST.md:97 | 153c9c9 main; b30b4a6+ | Role type: "[session.resume]" manifest role; picker: per-row cwd + local-time title (%z) |
| 3. Controller/Viewer | CONTEXT.md:343 | 677c3e7 (b4), ff2e3ab, d79f02e, f0c2ee0, 9b0025b, 0dc7018 | Viewer evict: skip-to-live; pre-evict gap: snap-above; controller gap: resume-from-floor; no blocking post-b4 |
| 4. RC Input Keys | bf32b8c (translator) | Covers: Delete, Insert, Home, End, arrows, F-keys, Backspace (swap 0x08↔0x7f) | Backspace fix: SWAP bytes, native in translator; claim "no longer swapped" is imprecise |
| 5. Help/Prose Markdown | 2435a74 commit | Extends renderer to 13 command-output surfaces (how-to, subnet status, daemon hints); b3bb387 adds ATX headers | v0.12.1 shipped `--help` only; v0.13.0 extends to prose output |
| 6. Daemon Window | 15fdf58 (v0.12.1), 082f5ed (v0.12.2→) | Windows only; respawn (wrapper) + flash (broker startup); full fix: FreeConsole self-detach | Scope: Windows; both respawn and flash eliminated by broker FreeConsole |</result>
<usage><subagent_tokens>67370</subagent_tokens><tool_uses>43</tool_uses><duration_ms>219564</duration_ms></usage>
</task-notification>


<owl_messages>
<owl_message from="doyle-w400" priority="info">[WORKING_PERCH_NOTICE] Subagent working perch created.
Perch: doyle-w400
Agent type: Explore
To message it: $OWL send doyle-w400 doyle</owl_message>
</owl_messages>

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

<owl_reachability_notice>
You have an active owl perch. When spawning subagents or doing work, use run_in_background: true so you stay reachable for incoming messages.
</owl_reachability_notice>


Ground truth in. I checked all 12 bullets against CONTEXT.md + commit diffs. **Two lines are wrong, one is optional polish, the other nine are accurate.** Point-by-point:

---

**❌ #1 (Added — idle delivery) — WRONG, reword.**
Shipped: *"Messages now reach a hosted agent that isn't actively reading… instead of leaving it unseen until the agent next reads."*
Problem: messages **already** reached daemon-hosted agents since **v0.11.0** (raw inject — see the v0.11.0 entry "`spt send` now delivers… injects the message"). So "instead of leaving it unseen" misstates the baseline. Per CONTEXT.md:39 the real v0.13.0 delta is *how*: an opt-in adapter **translation binary** turns the `<EVENT>` into a keystroke sequence (`{key}`/`{text}`/`{delay_ms}`) that spt-core applies **atomically**, so delivery **coexists with a live `spt rc`** — vs the old raw `payload`+Enter ("the degenerate no-choreography case").
Suggested:
> **Idle message delivery can be choreographed by the adapter.** An adapter can declare a `[message-idle-translation-binary]`: spt-core feeds an incoming message's `<EVENT>` to that binary, which emits a keystroke sequence (`{key}`/`{text}`/`{delay_ms}`), and spt-core applies it to the hosted agent's terminal atomically — so the message is entered as proper input and coexists with a live `spt rc` session, instead of the earlier raw text-plus-Enter injection.

(And the section's top summary line "messages reach a hosted agent even when it's idle" should soften similarly — it implies they didn't before.)

---

**❌ #10 (Fixed — Backspace) — WRONG (inverted), reword.**
Shipped: *"…character-delete and word-delete, **no longer swapped**."*
Problem: the fix **is a swap** (95f742f: "0x08↔0x7f SWAP"; bf32b8c translator: `if ctrl {0x08} else {0x7f}`). Before the fix both keys did char-delete (word-delete was lost); the swap makes Ctrl+Backspace word-delete. "No longer swapped" is backwards.
Suggested:
> **Windows Backspace and Ctrl+Backspace now do the right thing in `spt rc`.** Backspace deletes a character and Ctrl+Backspace deletes the previous word (Windows-native), instead of both deleting only a character.

---

**⚠ #7 (Fixed — viewers) — accurate, optional polish.**
"snaps forward or skips to live" correctly pairs to the two real mechanisms (ring-roll→snap-above; eviction→skip-to-live, CONTEXT.md:343) and "slow controller can't starve a viewer" is exact (b4). Fine as-is. Optional: it doesn't mention the controller's own resume-from-floor recovery — but that's controller-internal, arguably out of scope for a user changelog. Leave unless you want it added.

---

**✅ Verified accurate (no change):** #2 paste, #3 special keys (Delete *is* covered), #4 mouse scroll, #5 `[session.resume]` ("native-resume role" matches MANIFEST.md:97), #6 paste-wedge, #8 attach-online race, #9 console window (covers both flash + respawn, Windows), #11 picker, #12 prose markdown ("matching v0.12.1 --help fix" is correct — v0.12.1 shipped --help only).

---

Since v0.13.0 is published, applying these = docs-only (CHANGELOG.md on origin/main `d263a94` + `gh release edit` notes, **no retag**). Want me to apply **#1 + #10** (and the #1 summary-line tweak) as the fix set, or adjust any wording first?


<task-notification>
<task-id>b3ok5tzh4</task-id>
Monitor event: "« spt event »"
<event><EVENT-PART seq="1/8" id="d5dc1850" type="msg" from="todlando">LANDED — translate-proof pushed for your gate. Branch feat/translate-proof @ a05ef2c (off origin/main d263a94). 7 files, +705/-42.

WHAT: `spt adapter translate-proof &lt;adapter&gt; --event '&lt;EVENT&gt;' [--session &lt;id&gt;]` — author-time EMIT-half proof for [message-idle-translation-binary], mirrors </EVENT-PART>
<EVENT-PART seq="2/8" id="d5dc1850">cmd_adapter_digest_proof. Drives the REAL spt_daemon::translation driver VERBATIM (TranslationChild::spawn + send(Init{endpoint_id=option, node=os_hostname}) + send(Event{envelope}) + drain KeyCmd until {commit}/5s budget). Prints author-readable (Key+key_to_bytes hex / Text / Delay / Commit) + counts. {id}-&gt;option, {session_id}-&gt;--sessi</EVENT-PART>
<EVENT-PART seq="3/8" id="d5dc1850">on||placeholder filled into the envelope. Exit 0 ok / 1 spawn-fail|empty|no-commit|unparseable / 2 no-section. TranslationChild Drop = bounded reap.

SCOPE: EMIT-half only; --help states it does NOT exercise the atomic PTY apply / controller buffering (W2 inject_control_wedge int still owns that).

TRACEABILITY: REQ-ADAPTER-TRANSLA</EVENT-PART>
<EVENT-PART seq="4/8" id="d5dc1850">TE-PROOF added to traceable-reqs.toml FIRST, doc+impl+unit+int all tagged + [OK].

TESTS: 2 unit (parse + commit-gate) + 1 int that drives the REAL spt binary against a REAL external translation binary end-to-end (happy-&gt;exit0+XLATE_OK+commit:yes, nocommit-variant-&gt;exit1+NO_COMMIT, no-section-&gt;exit2).

I VERIFIED INDEPENDE</EVENT-PART>
<EVENT-PART seq="5/8" id="d5dc1850">NTLY (re-ran every gate myself, did not trust the build): clippy -p spt --all-targets -D warnings clean; unit 2/2; int 1/1; traceable-reqs check exit 0; xtask doc-drift check OK; CLI-ref regenerated (xtask gen), no M#/W#/REQ tokens leaked into clap help.

TWO HONEST FLAGS for your read:
1. The int fixture: CARGO_BIN_EXE_xlate_choreo_f</EVENT-PART>
<EVENT-PART seq="6/8" id="d5dc1850">ixture is only set for the crate declaring the bin, so I re-homed the fixture into the spt crate as a [[bin]] with source under tests/ (never ships from src/; release build is `cargo build -p spt --bin spt` = excluded; same pattern as mock-session). It is NOT a verbatim copy of the daemon fixture — it's EMIT-focused, dropping the daemon copy</EVENT-PART>
<EVENT-PART seq="7/8" id="d5dc1850">'s PTY-echo / XLATE_FIXTURE_STDIN_LOG machinery (W1 coexistence concerns, irrelevant to a PTY-less EMIT proof, per your own XOFF-strand note). Header comment says so accurately.
2. Path resolution uses spt_runtime::runtime::resolve_program_in_dir(path, install_dir) — the real resolver, matching digest-proof's REQ-INSTALL-11 stance.
<br</EVENT-PART>
<EVENT-PART seq="8/8" id="d5dc1850">>Subagent built it; I reviewed the full diff + re-ran all gates before committing. Over to your gate (full read + non-vacuous int verify). No rush.</EVENT-PART></event>
</task-notification>


translate-proof landed (todlando @ a05ef2c) for my gate — but I'm mid-changelog-fix with you and the gate is a careful full-read job. Queuing it behind this. Quick ack to todlando.


Bash

$OWL send todlando <<'EOF'
Received — translate-proof @ a05ef2c queued for my gate. I'm mid-task with the operator (v0.13.0 changelog wording corrections, post-publish docs-fix); I'll do the full-read + non-vacuous int verify right after that closes. Your two honest flags noted up front (re-homed EMIT-focused fixture as a spt [[bin]] under tests/, excluded from release build; resolve_program_in_dir real resolver) — I'll verify both at gate. No rush ack'd; nothing blocked on you. Will ping the gate verdict.
EOF

Ack todlando translate-proof, queue gate


Back to the changelog — still holding on your call: apply the **#1 + #10** fix set (plus the #1 summary-line softening) as the post-publish docs-fix, or adjust any wording first? translate-proof gate is parked behind this; nothing blocked.


some points: -idle message delivery already happened through the relay poll, for harness-hosted endpoints. -for spt-hosted endpoints, it would default to PTY injection. now, all idle message delivery goes through the relay poll -as such, the "idle message translation binary" concept was introduced, specifically for spt-hosted endpoints. spt brings up the endpoint adapter's IMTB alongside the endpoint. the IMTB is responsible for running the relay poll and handling its incoming messages. it can optionally output keypresses, delays, and string injection for spt-core to run against the endpoint's PTY. --- "agents can resume into their previous session" isn't an addition, but a fix. the resume option was there before, but it always started a new session. should be more like "Agent endpoints track session history and offer explicit session resume via `spt endpoint run`." it also talks about "native-resume role", which is a bit semantically confusing. "The adapter manifest can now declare a `[session.resume]` command so [...]" --- "Pasting or typing into a busy agent no longer [...]" is also confusing. should be more like "Pasting or typing into an spt-hosted endpoint no longer [...]"


some points: -idle message delivery already happened through the relay poll, for harness-hosted endpoints. -for spt-hosted endpoints, it would default to PTY injection. now, all idle message delivery goes through the relay poll -as such, the "idle message translation binary" concept was introduced, specifically for spt-hosted endpoints. spt brings up the endpoint adapter's IMTB alongside the endpoint. the IMTB is responsible for running the relay poll and handling its incoming messages. it can optionally output keypresses, delays, and string injection for spt-core to run against the endpoint's PTY. --- "agents can resume into their previous session" isn't an addition, but a fix. the resume option was there before, but it always started a new session. should be more like "Agent endpoints track session history and offer explicit session resume via `spt endpoint run`." it also talks about "native-resume role", which is a bit semantically confusing. "The adapter manifest can now declare a `[session.resume]` command so [...]" --- "Pasting or typing into a busy agent no longer [...]" is also confusing. should be more like "Pasting or typing into an SPT-hosted endpoint no longer [...]" -"viewers survive a high-output agent" should be "viewers survive a high-output terminal" --- otherwise agree with your suggestions


Integrated your corrections. Full corrected `[0.13.0]` section below — the four reworked bullets are marked. Key structural change: **session resume moves Added → Fixed** (it's a fix, per your note).

---

## [0.13.0] - 2026-06-21

A minor release: idle message delivery for spt-hosted endpoints now runs through an adapter translation binary, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, session resume actually resumes a prior session, and the daemon no longer flashes a console window.

### Added

- **`[reworked]` Idle message delivery for spt-hosted endpoints now uses a translation binary.** An adapter can declare a `[message-idle-translation-binary]`; spt-core brings it up alongside the endpoint, where it polls the relay for incoming messages and optionally emits keypresses, delays, and text injection that spt-core applies to the endpoint's terminal. Idle delivery now flows through the relay poll for every endpoint, instead of spt-hosted endpoints falling back to direct PTY injection.
- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
- **Windows special keys in `spt rc`.** Arrow keys, Home/End, Delete, function keys and other special keys are translated to terminal sequences and reach the agent — previously only plain characters got through.
- **`spt rc` forwards mouse scroll** to the agent's terminal.

### Fixed

- **`[reworked: agent→spt-hosted endpoint]` Pasting or typing into an spt-hosted endpoint no longer freezes the daemon.** A large paste or input burst could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).
- **`[moved from Added + reworked]` Session resume actually resumes now.** Agent endpoints track session history and offer explicit session resume via `spt endpoint run` (`--resume <session>` or *Resume from history*); the adapter manifest can now declare a `[session.resume]` command so the relaunch reattaches the prior session instead of always starting a new one. The run picker now shows each row's working directory and local time.
- **`[reworked: agent→terminal]` `spt rc --view` viewers survive a high-output terminal.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.
- **`spt rc` no longer races a just-started agent.** Attach now waits for the endpoint to come online, instead of failing when you attach immediately after `spt endpoint run`.
- **The daemon no longer flashes or respawns a console window on Windows.**
- **`[reworked: inverted→outcome]` Windows Backspace and Ctrl+Backspace now do the right thing in `spt rc`.** Backspace deletes a character and Ctrl+Backspace deletes the previous word (Windows-native), instead of both deleting only a character.

### Changed

- **The `spt endpoint run` picker is clearer.** It opens directly on an existing pick, auto-attaches, shows the controlling node name, and produces clean bring-up output.
- **Human-prose command output renders Markdown.** Prose output (how-to topics and similar) now shows styled headers and emphasis in a terminal and clean plain text when piped — matching the v0.12.1 `--help` fix.

---

**Apply plan (docs-only, no retag):** (1) commit the CHANGELOG.md edit to origin/main via a throwaway worktree off `d263a94` (won't touch your c84daff main worktree); (2) `gh release edit v0.13.0` notes to match.

Confirm the text and I'll apply both. Anything still off?


some points: -idle message delivery already happened through the relay poll, for harness-hosted endpoints. -for spt-hosted endpoints, it would default to PTY injection. now, all idle message delivery…


proceed


Applying. First verify origin/main is still `d263a94` (FF safety), then set up a throwaway worktree off it (leaves your c84daff main worktree untouched).


echo "=== origin/main now ==="; git rev-parse origin/main 2>&1; echo "=== create throwaway worktree off d263a94 ==="; git worktree add --detach "C:/Users/decid/Documents/projects/spt-core-changelog-fix" d263a94 2>&1 | tail -3

Verify origin/main and create changelog worktree


=== origin/main now ===
d263a940b12fa8d0411c25f45d816acfa117e0dc
=== create throwaway worktree off d263a94 ===
Preparing worktree (detached HEAD d263a94)
HEAD is now at d263a94 release: v0.13.0 — bump 0.12.1->0.13.0 + changelog + regen CLI reference


Worktree ready at d263a94 (FF-safe). Read its CHANGELOG.md to edit the `[0.13.0]` block.


1	# Changelog
2
3	All notable **user-facing** changes to `spt` — what a person running the CLI
4	notices or does differently. The `## [<version>]` section of each release
5	becomes that release's GitHub Release notes verbatim (see
6	`docs/RELEASE-RUNBOOK.md`). This project follows
7	[Keep a Changelog](https://keepachangelog.com) and semantic versioning
8	(pre-1.0: breaking changes bump the minor).
9
10	## [Unreleased]
11
12	## [0.13.0] - 2026-06-21
13
14	A minor release: messages reach a hosted agent even when it's idle, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, agents can resume into their prior session, and the daemon no longer flashes a console window.
15
16	### Added
17
18	- **Messages now reach a hosted agent that isn't actively reading.** An adapter can declare a `[message-idle-translation-binary]`; when a message arrives for a daemon-hosted agent sitting idle at its prompt, the daemon injects it through that binary instead of leaving it unseen until the agent next reads.
19	- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
20	- **Windows special keys in `spt rc`.** Arrow keys, Home/End, Delete, function keys and other special keys are translated to terminal sequences and reach the agent — previously only plain characters got through.
21	- **`spt rc` forwards mouse scroll** to the agent's terminal.
22	- **Agents can resume into their previous session.** An adapter can declare a `[session.resume]` native-resume role so relaunching an agent reattaches its prior session instead of starting cold; the resume picker now shows each row's working directory and local-time title.
23
24	### Fixed
25
26	- **Pasting or typing into a busy agent no longer freezes the daemon.** A large paste or input burst against a hosted agent could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).
27	- **`spt rc --view` viewers survive a high-output agent.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.
28	- **`spt rc` no longer races a just-started agent.** Attach now waits for the endpoint to come online, instead of failing when you attach immediately after `spt endpoint run`.
29	- **The daemon no longer flashes or respawns a console window on Windows.**
30	- **Windows Backspace and Ctrl+Backspace now behave correctly in `spt rc`** — character-delete and word-delete, no longer swapped.
31
32	### Changed
33
34	- **The `spt endpoint run` picker is clearer.** It opens directly on an existing pick, auto-attaches, shows the controlling node name, and produces clean bring-up output.
35	- **Human-prose command output renders Markdown.** Prose output (how-to topics and similar) now shows styled headers and emphasis in a terminal and clean plain text when piped — matching the v0.12.1 `--help` fix.
36
37	## [0.12.1] - 2026-06-18
38
39	A patch release fixing the live-agent lifecycle in a real terminal: attaching to a running agent, keeping it alive when you close the terminal, and the daemon staying responsive now all work as intended. Also polishes `spt endpoint list`, the run picker, and `spt --help`.
40
41	### Fixed
42
43	- **Attaching to a running agent now shows its output.** `spt rc <id>` against an agent started with `spt endpoint run` now delivers the agent's terminal output immediately, instead of connecting to a blank screen.
44	- **Closing the terminal that started an agent no longer kills it.** When `spt endpoint run` launches the background daemon for you, closing that terminal tab or window now leaves the agent running and re-attachable with `spt rc <id>`.
45	- **A crashed agent with a disconnected viewer no longer freezes the daemon.** A dead agent process combined with an abruptly-closed `spt rc` could previously wedge the daemon so new agents wouldn't start; the daemon now stays responsive and marks the dead agent offline.

# Changelog

All notable **user-facing** changes to `spt` — what a person running the CLI
notices or does differently. The `## [<version>]` section of each release
becomes that release's GitHub Release notes verbatim (see
`docs/RELEASE-RUNBOOK.md`). This project follows
[Keep a Changelog](https://keepachangelog.com) and semantic versioning
(pre-1.0: breaking changes bump the minor).

## [Unreleased]

## [0.13.0] - 2026-06-21

A minor release: messages reach a hosted agent even when it's idle, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, agents can resume into their prior session, and the daemon no longer flashes a console window.

### Added

- **Messages now reach a hosted agent that isn't actively reading.** An adapter can declare a `[message-idle-translation-binary]`; when a message arrives for a daemon-hosted agent sitting idle at its prompt, the daemon injects it through that binary instead of leaving it unseen until the agent next reads.
- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
- **Windows special keys in `spt rc`.** Arrow keys, Home/End, Delete, function keys and other special keys are translated to terminal sequences and reach the agent — previously only plain characters got through.
- **`spt rc` forwards mouse scroll** to the agent's terminal.
- **Agents can resume into their previous session.** An adapter can declare a `[session.resume]` native-resume role so relaunching an agent reattaches its prior session instead of starting cold; the resume picker now shows each row's working directory and local-time title.

### Fixed

- **Pasting or typing into a busy agent no longer freezes the daemon.** A large paste or input burst against a hosted agent could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).
- **`spt rc --view` viewers survive a high-output agent.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.
- **`spt rc` no longer races a just-started agent.** Attach now waits for the endpoint to come online, instead of failing when you attach immediately after `spt endpoint run`.
- **The daemon no longer flashes or respawns a console window on Windows.**
- **Windows Backspace and Ctrl+Backspace now behave correctly in `spt rc`** — character-delete and word-delete, no longer swapped.

### Changed

- **The `spt endpoint run` picker is clearer.** It opens directly on an existing pick, auto-attaches, shows the controlling node name, and produces clean bring-up output.
- **Human-prose command output renders Markdown.** Prose output (how-to topics and similar) now shows styled headers and emphasis in a terminal and clean plain text when piped — matching the v0.12.1 `--help` fix.

## [0.12.1] - 2026-06-18

A patch release fixing the live-agent lifecycle in a real terminal: attaching to a running agent, keeping it alive when you close the terminal, and the daemon staying responsive now all work as intended. Also polishes `spt endpoint list`, the run picker, and `spt --help`.

### Fixed

- **Attaching to a running agent now shows its output.** `spt rc <id>` against an agent started with `spt endpoint run` now delivers the agent's terminal output immediately, instead of connecting to a blank screen.
- **Closing the terminal that started an agent no longer kills it.** When `spt endpoint run` launches the background daemon for you, closing that terminal tab or window now leaves the agent running and re-attachable with `spt rc <id>`.
- **A crashed agent with a disconnected viewer no longer freezes the daemon.** A dead agent process combined with an abruptly-closed `spt rc` could previously wedge the daemon so new agents wouldn't start; the daemon now stays responsive and marks the dead agent offline.


Now replace the `[0.13.0]` block with the corrected version.


Edit

A minor release: messages reach a hosted agent even when it's idle, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, agents can resume into their prior session, and the daemon no longer flashes a console window.

### Added

- **Messages now reach a hosted agent that isn't actively reading.** An adapter can declare a `[message-idle-translation-binary]`; when a message arrives for a daemon-hosted agent sitting idle at its prompt, the daemon injects it through that binary instead of leaving it unseen until the agent next reads.
- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
- **Windows special keys in `spt rc`.** Arrow keys, Home/End, Delete, function keys and other special keys are translated to terminal sequences and reach the agent — previously only plain characters got through.
- **`spt rc` forwards mouse scroll** to the agent's terminal.
- **Agents can resume into their previous session.** An adapter can declare a `[session.resume]` native-resume role so relaunching an agent reattaches its prior session instead of starting cold; the resume picker now shows each row's working directory and local-time title.

### Fixed

- **Pasting or typing into a busy agent no longer freezes the daemon.** A large paste or input burst against a hosted agent could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).
- **`spt rc --view` viewers survive a high-output agent.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.
- **`spt rc` no longer races a just-started agent.** Attach now waits for the endpoint to come online, instead of failing when you attach immediately after `spt endpoint run`.
- **The daemon no longer flashes or respawns a console window on Windows.**
- **Windows Backspace and Ctrl+Backspace now behave correctly in `spt rc`** — character-delete and word-delete, no longer swapped.

A minor release: idle message delivery for spt-hosted endpoints now runs through an adapter translation binary, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, session resume actually resumes a prior session, and the daemon no longer flashes a console window.

### Added

- **Idle message delivery for spt-hosted endpoints now uses a translation binary.** An adapter can declare a `[message-idle-translation-binary]`; spt-core brings it up alongside the endpoint, where it polls the relay for incoming messages and optionally emits keypresses, delays, and text injection that spt-core applies to the endpoint's terminal. Idle delivery now flows through the relay poll for every endpoint, instead of spt-hosted endpoints falling back to direct PTY injection.
- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
- **Windows special keys in `spt rc`.** Arrow keys, Home/End, Delete, function keys and other special keys are translated to terminal sequences and reach the agent — previously only plain characters got through.
- **`spt rc` forwards mouse scroll** to the agent's terminal.

### Fixed

- **Pasting or typing into an spt-hosted endpoint no longer freezes the daemon.** A large paste or input burst could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).
- **Session resume actually resumes now.** Agent endpoints track session history and offer explicit session resume via `spt endpoint run` (`--resume <session>` or *Resume from history*); the adapter manifest can now declare a `[session.resume]` command so the relaunch reattaches the prior session instead of always starting a new one. The run picker now shows each row's working directory and local time.
- **`spt rc --view` viewers survive a high-output terminal.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.
- **`spt rc` no longer races a just-started agent.** Attach now waits for the endpoint to come online, instead of failing when you attach immediately after `spt endpoint run`.
- **The daemon no longer flashes or respawns a console window on Windows.**
- **Windows Backspace and Ctrl+Backspace now do the right thing in `spt rc`.** Backspace deletes a character and Ctrl+Backspace deletes the previous word (Windows-native), instead of both deleting only a character.


The file C:/Users/decid/Documents/projects/spt-core-changelog-fix/CHANGELOG.md has been updated successfully. (file state is current in your context — no need to Read it back)

A minor release: messages reach a hosted agent even when it's idle, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, agents can resume into their prior session, and the daemon no longer flashes a console window.

### Added

- **Messages now reach a hosted agent that isn't actively reading.** An adapter can declare a `[message-idle-translation-binary]`; when a message arrives for a daemon-hosted agent sitting idle at its prompt, the daemon injects it through that binary instead of leaving it unseen until the agent next reads.
- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
- **Windows special keys in `spt rc`.** Arrow keys, Home/End, Delete, function keys and other special keys are translated to terminal sequences and reach the agent — previously only plain characters got through.
- **`spt rc` forwards mouse scroll** to the agent's terminal.
- **Agents can resume into their previous session.** An adapter can declare a `[session.resume]` native-resume role so relaunching an agent reattaches its prior session instead of starting cold; the resume picker now shows each row's working directory and local-time title.

### Fixed

- **Pasting or typing into a busy agent no longer freezes the daemon.** A large paste or input burst against a hosted agent could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).
- **`spt rc --view` viewers survive a high-output agent.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.
- **`spt rc` no longer races a just-started agent.** Attach now waits for the endpoint to come online, instead of failing when you attach immediately after `spt endpoint run`.
- **The daemon no longer flashes or respawns a console window on Windows.**
- **Windows Backspace and Ctrl+Backspace now behave correctly in `spt rc`** — character-delete and word-delete, no longer swapped.

A minor release: idle message delivery for spt-hosted endpoints now runs through an adapter translation binary, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, session resume actually resumes a prior session, and the daemon no longer flashes a console window.

### Added

- **Idle message delivery for spt-hosted endpoints now uses a translation binary.** An adapter can declare a `[message-idle-translation-binary]`; spt-core brings it up alongside the endpoint, where it polls the relay for incoming messages and optionally emits keypresses, delays, and text injection that spt-core applies to the endpoint's terminal. Idle delivery now flows through the relay poll for every endpoint, instead of spt-hosted endpoints falling back to direct PTY injection.
- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
- **Windows special keys in `spt rc`.** Arrow keys, Home/End, Delete, function keys and other special keys are translated to terminal sequences and reach the agent — previously only plain characters got through.
- **`spt rc` forwards mouse scroll** to the agent's terminal.

### Fixed

- **Pasting or typing into an spt-hosted endpoint no longer freezes the daemon.** A large paste or input burst could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).
- **Session resume actually resumes now.** Agent endpoints track session history and offer explicit session resume via `spt endpoint run` (`--resume <session>` or *Resume from history*); the adapter manifest can now declare a `[session.resume]` command so the relaunch reattaches the prior session instead of always starting a new one. The run picker now shows each row's working directory and local time.
- **`spt rc --view` viewers survive a high-output terminal.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.
- **`spt rc` no longer races a just-started agent.** Attach now waits for the endpoint to come online, instead of failing when you attach immediately after `spt endpoint run`.
- **The daemon no longer flashes or respawns a console window on Windows.**
- **Windows Backspace and Ctrl+Backspace now do the right thing in `spt rc`.** Backspace deletes a character and Ctrl+Backspace deletes the previous word (Windows-native), instead of both deleting only a character.

-A minor release: messages reach a hosted agent even when it's idle, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, agents can resume into their prior session, and the daemon no longer flashes a console window.

+A minor release: idle message delivery for spt-hosted endpoints now runs through an adapter translation binary, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, session resume actually resumes a prior session, and the daemon no longer flashes a console window.

-- **Messages now reach a hosted agent that isn't actively reading.** An adapter can declare a `[message-idle-translation-binary]`; when a message arrives for a daemon-hosted agent sitting idle at its prompt, the daemon injects it through that binary instead of leaving it unseen until the agent next reads.

+- **Idle message delivery for spt-hosted endpoints now uses a translation binary.** An adapter can declare a `[message-idle-translation-binary]`; spt-core brings it up alongside the endpoint, where it polls the relay for incoming messages and optionally emits keypresses, delays, and text injection that spt-core applies to the endpoint's terminal. Idle delivery now flows through the relay poll for every endpoint, instead of spt-hosted endpoints falling back to direct PTY injection.

-- **Agents can resume into their previous session.** An adapter can declare a `[session.resume]` native-resume role so relaunching an agent reattaches its prior session instead of starting cold; the resume picker now shows each row's working directory and local-time title.

-- **Pasting or typing into a busy agent no longer freezes the daemon.** A large paste or input burst against a hosted agent could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).

-- **`spt rc --view` viewers survive a high-output agent.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.

+- **Pasting or typing into an spt-hosted endpoint no longer freezes the daemon.** A large paste or input burst could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).

+- **Session resume actually resumes now.** Agent endpoints track session history and offer explicit session resume via `spt endpoint run` (`--resume <session>` or *Resume from history*); the adapter manifest can now declare a `[session.resume]` command so the relaunch reattaches the prior session instead of always starting a new one. The run picker now shows each row's working directory and local time.

+- **`spt rc --view` viewers survive a high-output terminal.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.

-- **Windows Backspace and Ctrl+Backspace now behave correctly in `spt rc`** — character-delete and word-delete, no longer swapped.

+- **Windows Backspace and Ctrl+Backspace now do the right thing in `spt rc`.** Backspace deletes a character and Ctrl+Backspace deletes the previous word (Windows-native), instead of both deleting only a character.


CHANGELOG corrected in worktree. Commit (docs-only) + push to main.


Bash

WT="C:/Users/decid/Documents/projects/spt-core-changelog-fix"
git -C "$WT" add CHANGELOG.md
git -C "$WT" commit -m "docs(changelog): correct v0.13.0 notes (post-publish, docs-only)

Fix wording verified against CONTEXT.md + commit diffs:
- IMTB: reframe to the real delta (spt-hosted idle delivery now via the
  adapter translation binary over the relay poll; was direct PTY injection),
  not 'messages now reach idle agents' (they did since v0.11.0).
- Session resume: move Added->Fixed (resume always minted a new session);
  '[session.resume] command', drop confusing 'native-resume role'.
- Backspace: 'no longer swapped' was inverted (the fix IS a 0x08<->0x7f swap);
  state the outcome (Ctrl+Backspace word-deletes, Backspace char-deletes).
- 'busy agent'->'spt-hosted endpoint'; viewer 'high-output agent'->'terminal'.

No code/tag change; release notes for v0.13.0 updated to match.

Co-authored by: doyle" 2>&1 | tail -4
echo "=== push to main ==="
git -C "$WT" push origin HEAD:main 2>&1 | tail -5

Commit changelog fix and push to main


[detached HEAD cfb25b7] docs(changelog): correct v0.13.0 notes (post-publish, docs-only)
 1 file changed, 6 insertions(+), 6 deletions(-)
=== push to main ===
To https://github.com/SaberMage/spt-core.git
   d263a94..cfb25b7  HEAD -> main


Pushed to main (`d263a94..cfb25b7`). Now sync the GH release notes. Check current format first, then update to match.


gh release view v0.13.0 --repo SaberMage/spt-releases --json body -q .body 2>&1 | head -20

View current v0.13.0 release notes format


A minor release: messages reach a hosted agent even when it's idle, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, agents can resume into their prior session, and the daemon no longer flashes a console window.

### Added

- **Messages now reach a hosted agent that isn't actively reading.** An adapter can declare a `[message-idle-translation-binary]`; when a message arrives for a daemon-hosted agent sitting idle at its prompt, the daemon injects it through that binary instead of leaving it unseen until the agent next reads.
- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
- **Windows special keys in `spt rc`.** Arrow keys, Home/End, Delete, function keys and other special keys are translated to terminal sequences and reach the agent — previously only plain characters got through.
- **`spt rc` forwards mouse scroll** to the agent's terminal.
- **Agents can resume into their previous session.** An adapter can declare a `[session.resume]` native-resume role so relaunching an agent reattaches its prior session instead of starting cold; the resume picker now shows each row's working directory and local-time title.

### Fixed

- **Pasting or typing into a busy agent no longer freezes the daemon.** A large paste or input burst against a hosted agent could wedge the daemon's input path so every new attach died; input now runs on a dedicated per-session writer and never blocks the daemon (this also covers the effect-journal stall on interactive input).
- **`spt rc --view` viewers survive a high-output agent.** A viewer no longer dies when the output backlog rolls over or it is briefly evicted — it snaps forward or skips to live instead of failing — and a slow controller can no longer starve a concurrent viewer.
- **`spt rc` no longer races a just-started agent.** Attach now waits for the endpoint to come online, instead of failing when you attach immediately after `spt endpoint run`.
- **The daemon no longer flashes or respawns a console window on Windows.**
- **Windows Backspace and Ctrl+Backspace now behave correctly in `spt rc`** — character-delete and word-delete, no longer swapped.

### Changed


Release body = section sans the `## [0.13.0]` header. Extract the corrected body + update the release notes.


WT="C:/Users/decid/Documents/projects/spt-core-changelog-fix"
NOTES="C:/Users/decid/AppData/Local/Temp/v013-notes.md"
git -C "$WT" show HEAD:CHANGELOG.md | awk '/^## \[0.13.0\]/{f=1;next} /^## \[0.12.1\]/{f=0} f' | sed '/./,$!d' > "$NOTES"
echo "=== notes file (head) ==="; head -6 "$NOTES"; echo "..."; echo "=== tail ==="; tail -4 "$NOTES"
echo "=== updating release notes ==="
gh release edit v0.13.0 --repo SaberMage/spt-releases --notes-file "$NOTES" 2>&1 | tail -3
echo "EXIT=$?"

Extract corrected body and update GH release notes


=== notes file (head) ===
A minor release: idle message delivery for spt-hosted endpoints now runs through an adapter translation binary, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, session resume actually resumes a prior session, and the daemon no longer flashes a console window.

### Added

- **Idle message delivery for spt-hosted endpoints now uses a translation binary.** An adapter can declare a `[message-idle-translation-binary]`; spt-core brings it up alongside the endpoint, where it polls the relay for incoming messages and optionally emits keypresses, delays, and text injection that spt-core applies to the endpoint's terminal. Idle delivery now flows through the relay poll for every endpoint, instead of spt-hosted endpoints falling back to direct PTY injection.
- **Windows paste in `spt rc`.** Ctrl+V and right-click now paste the local clipboard into the attached agent as a single bracketed paste.
...
=== tail ===

- **The `spt endpoint run` picker is clearer.** It opens directly on an existing pick, auto-attaches, shows the controlling node name, and produces clean bring-up output.
- **Human-prose command output renders Markdown.** Prose output (how-to topics and similar) now shows styled headers and emphasis in a terminal and clean plain text when piped — matching the v0.12.1 `--help` fix.

=== updating release notes ===
https://github.com/SaberMage/spt-releases/releases/tag/v0.13.0
EXIT=0


Both surfaces synced. Clean up the throwaway worktree + verify the release notes took.


echo "=== verify release notes updated ==="; gh release view v0.13.0 --repo SaberMage/spt-releases --json body -q .body 2>&1 | head -3
echo "=== remove worktree ==="; git worktree remove "C:/Users/decid/Documents/projects/spt-core-changelog-fix" --force 2>&1 && echo "removed"; git worktree list 2>&1 | tail -3

Verify release notes and remove worktree


=== verify release notes updated ===
A minor release: idle message delivery for spt-hosted endpoints now runs through an adapter translation binary, `spt rc` gains real paste, key, and mouse support on Windows and stays attached under heavy output, session resume actually resumes a prior session, and the daemon no longer flashes a console window.

### Added
=== remove worktree ===
removed
C:/Users/decid/Documents/projects/spt-core-opbuild          082f5ed (detached HEAD) prunable
C:/Users/decid/Documents/projects/spt-core-translate-proof  a05ef2c [feat/translate-proof]
C:/Users/decid/Documents/projects/spt-core-wedgeval         805727c [wedge-trace-v4]


**Changelog fix applied — done.** Both surfaces live:
- `CHANGELOG.md` on origin/main @ `cfb25b7` (docs-only commit, no retag).
- GH release notes v0.13.0 updated + verified (intro now reads "idle message delivery for spt-hosted endpoints… through an adapter translation binary").
- Throwaway worktree removed; your c84daff main worktree untouched.

6 line-changes shipped: IMTB reframe, session-resume Added→Fixed, backspace de-inverted, "busy agent"→"spt-hosted endpoint", viewer "agent"→"terminal", + summary line.

Now chaining to the parked **translate-proof gate** (todlando @ a05ef2c). Fetching + full-reading the diff.


git fetch origin feat/translate-proof 2>&1 | tail -1; echo "=== stat (off d263a94) ==="; git diff --stat d263a94 a05ef2c 2>&1; echo "=== REQ added? ==="; git show a05ef2c:traceable-reqs.toml 2>&1 | grep -A6 "REQ-ADAPTER-TRANSLATE-PROOF" | head -12

Fetch translate-proof, stat diff, check REQ


 * branch            feat/translate-proof -> FETCH_HEAD
=== stat (off d263a94) ===
 crates/spt/Cargo.toml                              |  10 +
 crates/spt/src/cli.rs                              | 333 +++++++++++++++++++++
 crates/spt/tests/fixtures/xlate_choreo_fixture.rs  |  90 ++++++
 crates/spt/tests/translate_proof.rs                | 154 ++++++++++
 docs-site/src/cli/reference.md                     | 120 +++++---
 ...-spt-hosted-idle-delivery-translation-binary.md |  34 +++
 traceable-reqs.toml                                |   6 +
 7 files changed, 705 insertions(+), 42 deletions(-)
=== REQ added? ===
id = "REQ-ADAPTER-TRANSLATE-PROOF"
title = "`spt adapter translate-proof <adapter> --event <envelope> [--session <id>]` — the author-time EMIT-half proof tool for `[message-idle-translation-binary]` (ADR-0022), symmetric to `spt adapter digest-proof` (REQ-TERM-5). It spawns and feeds the adapter's declared translation binary EXACTLY as the daemon does at idle-delivery — running the REAL `spt_daemon::translation` driver VERBATIM (no protocol reimplementation): `TranslationChild::spawn` the binary, send the `{type:\"init\",endpoint_id,node}` line then the `{type:\"event\",envelope}` line, and read back the emitted `{key}`/`{text}`/`{delay_ms}`/`{commit}` keystroke-command stream — then prints it author-readable (each Key with its `key_to_bytes` rendering, Text quoted, Delay in ms, Commit marker) with counts. It fills the SAME `{id}`→option and `{session_id}`→(--session, else a placeholder) keys into the `--event` envelope the daemon fills at runtime, so an envelope that proofs here feeds faithfully live. EMIT-half ONLY: it proves the binary's spawn+feed+emit contract; it does NOT exercise the daemon's atomic PTY apply / controller-buffering (that stays covered by the W2 inject_control_wedge int gate) — `--help` says so. Exit codes mirror digest-proof: 0 ok, 1 on spawn-fail / zero commands / no-commit-or-output / unparseable, 2 when the adapter declares no `[message-idle-translation-binary]` section. The `TranslationChild` Drop does the bounded no-zombie reap. (v0.13.x)"
required_stages = ["doc", "impl", "unit", "int"]

# ── W3: a fresh spt-hosted endpoint shows under its own project (info.cwd on bind) ──
[[requirements]]
id = "REQ-HAZARD-BIND-CWD-UNSET"


REQ added, 4 stages, description matches the design. Full-read the core: locate the cli.rs impl + read the int test, the `[[bin]]` decl (release-exclusion claim), and the fixture.


echo "=== cli.rs translate-proof anchors ==="; git show a05ef2c:crates/spt/src/cli.rs | grep -nE "translate.proof|translate_proof|TranslateProof|fn cmd_adapter_translate" | head -20
echo "=== Cargo.toml [[bin]] (fixture exclusion) ==="; git show a05ef2c:crates/spt/Cargo.toml | grep -nB1 -A8 "xlate_choreo_fixture"
echo "=== fixture header (emit-focused claim) ==="; git show a05ef2c:crates/spt/tests/fixtures/xlate_choreo_fixture.rs | head -25

Locate cli impl, verify bin exclusion, read fixture header


=== cli.rs translate-proof anchors ===
600:    TranslateProof {
5679:        AdapterCmd::TranslateProof { option, event, session } => {
5680:            cmd_adapter_translate_proof(&adapters, &option, &event, session.as_deref())
6089:/// `spt adapter translate-proof <adapter> --event <envelope> [--session <id>]` —
6108:fn cmd_adapter_translate_proof(
6210:    println!("=== translate-proof: {option} ===");
8808:    // `adapter translate-proof <opt> --event <env> [--session <id>]` — `--event`
8811:    fn adapter_translate_proof_parses() {
8815:            "translate-proof",
8825:                action: AdapterCmd::TranslateProof { option, event, session },
8831:            _ => panic!("expected Adapter TranslateProof"),
8837:            "translate-proof",
8849:                action: AdapterCmd::TranslateProof { session, .. },
8851:            _ => panic!("expected Adapter TranslateProof"),
8855:            parse(&["spt", "adapter", "translate-proof", "claude-spt"]).is_err(),
8875:    // [unit->REQ-ADAPTER-TRANSLATE-PROOF] translate-proof drives the REAL
8882:    fn adapter_translate_proof_gates_on_commit() {
8915:            cmd_adapter_translate_proof(&adapters, "cc", event, None),
8923:            cmd_adapter_translate_proof(&adapters, "cc", event, Some("sessA")),
8937:            cmd_adapter_translate_proof(&adapters, "plain", event, None),
=== Cargo.toml [[bin]] (fixture exclusion) ===
15-# excludes it. `cargo test -p spt` builds it and exposes
16:# `CARGO_BIN_EXE_xlate_choreo_fixture` to the integration tests (the same
17-# cross-crate fixture-bin pattern as `mock-session`).
18-[[bin]]
19:name = "xlate_choreo_fixture"
20:path = "tests/fixtures/xlate_choreo_fixture.rs"
21-
22-[dependencies]
23-spt-proto = { path = "../spt-proto" }
24-spt-store = { path = "../spt-store" }
25-spt-msg = { path = "../spt-msg" }
26-spt-runtime = { path = "../spt-runtime" }
27-spt-live = { path = "../spt-live" }
28-spt-daemon = { path = "../spt-daemon" }
=== fixture header (emit-focused claim) ===
//! Test-only ADR-0022 translation-binary fixture for the `spt` crate's
//! `translate-proof` tests — an EMIT-focused sibling of
//! `crates/spt-daemon/src/bin/xlate_choreo_fixture.rs` (the W2 Layer G fixture).
//! It emits the SAME ADR-0022 choreography on `{type:"event"}`, but drops the
//! daemon copy's PTY-echo / `XLATE_FIXTURE_STDIN_LOG` machinery (that exists for
//! the W1 inject-control coexistence test, which has a live PTY) — irrelevant to
//! this EMIT-half proof, which has no PTY. Re-homed here because
//! `CARGO_BIN_EXE_xlate_choreo_fixture` is only set for the crate that DECLARES
//! the bin: the daemon's copy serves `spt-daemon`'s `inject_control_wedge.rs`,
//! this copy serves the `spt` crate's `tests/translate_proof.rs` so the int drives
//! a REAL external binary through the real `spt adapter translate-proof` command.
//! Declared as a `[[bin]]` whose source lives under `tests/` so it never ships
//! from `src/` (CI's release build is `cargo build -p spt --bin spt`, so it is
//! excluded there). 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 reader sees them promptly):
//!   `{"key":"ctrl+s"}` `{"delay_ms":50}` `{"text":"XLATE_OK"}` `{"key":"enter"}`
//!   `{"delay_ms":50}` `{"key":"ctrl+s"}` then `{"commit":true}`.


Read the core impl + the int test in full, and verify the release build only ships `spt` (fixture-exclusion claim).


echo "=== cmd_adapter_translate_proof impl ==="; git show a05ef2c:crates/spt/src/cli.rs | sed -n '6089,6212p'

Read translate-proof impl