# JIT Plan — `spt adapter translate-proof` (v0.13.x DX, doyle dispatch, NON-blocking)

**Worktree:** `C:/Users/decid/Documents/projects/spt-core-translate-proof` — branch `feat/translate-proof` off `origin/main` **d263a94** (= v0.13.0 release; NOT operator's main worktree @ c84daff).

## Goal
Author-time **EMIT-half** proof command for `[message-idle-translation-binary]` (ADR-0022), symmetric to `spt adapter digest-proof` (REQ-TERM-5). Spawn + feed the adapter's translation binary EXACTLY as the daemon does at idle-delivery (`init` line → `event` line), read back the `{key}`/`{text}`/`{delay_ms}`/`{commit}` stream, print author-readable, gate nonzero on spawn-fail / empty / unparseable. EMIT half ONLY — does NOT exercise the daemon's atomic PTY apply (atomic apply stays covered by the W2 int gate). Say so in `--help`.

## Reuse the REAL driver — NO protocol reimpl (doyle hard constraint)
`spt_daemon::translation` (`crates/spt-daemon/src/translation.rs`):
- `TranslationChild::spawn(path: &str, cmds: Sender<KeyCmd>) -> io::Result<Self>` — spawns filter, reader thread parses `KeyCmd` off stdout → channel, bad line → stderr `TRANSLATION_BIN_BAD_LINE`, Drop = bounded reap (no zombie).
- `child.send(&ToBinary::Init { endpoint_id, node })`, then `child.send(&ToBinary::Event { envelope })`.
- `KeyCmd::{ Key{key}, Text{text}, Delay{delay_ms}, Commit{commit} }`; `key_to_bytes(&str) -> Option<Vec<u8>>` for the author-readable byte render.
- Daemon call sites to MIRROR: `broker.rs:1548` (spawn), `:1552` (Init build), `:1044` (Event send); `harnesshost.rs:143` (path resolution off the manifest section). **READ broker.rs:1540-1560 + harnesshost.rs:140-150 in execute** to copy exactly how `path` is resolved (relative to install_dir) and how Init `endpoint_id`/`node` are built + whether `{id}`/`{session_id}` templating applies.

## digest-proof shape to mirror (`crates/spt/src/cli.rs`)
- clap variant `AdapterCmd::DigestProof { option, sample, session }` @ **:577**; dispatch @ **:5651**; impl `cmd_adapter_digest_proof` @ **:5958**; tests @ **:8487+**.
- Pattern: `registry::resolve_option(adapters, option)` → `(install_dir, manifest)`; read manifest section (None → `*_NO_SECTION` exit 2); fill keys `{id}=option`, `{session_id}=session||"proof-session"`; run the REAL engine; print parsed + gate. Exit codes: **0** ok, **1** error/drop/empty, **2** no-section.

## Steps
1. **traceable-reqs.toml FIRST** (rule 3): add `REQ-ADAPTER-TRANSLATE-PROOF` after the REQ-TERM-5 block (~line 459). `required_stages = ["doc","impl","unit","int"]`. Title: author-time translate-proof tool symmetric to digest-proof — runs the REAL `spt_daemon::translation` driver over an `--event`, EMIT-half only (no atomic PTY apply). Run `traceable-reqs check` — expect exit 1 (stages unsatisfied) until evidence lands; that's fine mid-build, MUST be 0 before commit.
2. **cli.rs clap**: add `TranslateProof { option, event, session }` near `:577` (`--event` required, `--session` optional). Dispatch near `:5651` → `cmd_adapter_translate_proof(&adapters, &option, &event, session.as_deref())`.
3. **cli.rs impl** `cmd_adapter_translate_proof` (model on `cmd_adapter_digest_proof`): resolve_option → install_dir+manifest; `manifest.message_idle_translation_binary` (None → `TRANSLATE_PROOF_NO_SECTION:{option}` exit 2); resolve binary path under install_dir (mirror harnesshost/daemon); `mpsc::channel::<KeyCmd>()`; `TranslationChild::spawn`; `send(Init{...})`; `send(Event{ envelope: event })`; drain `rx.recv_timeout` loop until `Commit` OR overall idle-timeout (~5s); print `=== translate-proof: {option} ===`, each cmd author-readable (Key → name + `key_to_bytes` hex bytes; Text → quoted; Delay → `{n}ms`; Commit → marker), counts; **gate** exit 1 if spawn-fail / zero cmds / no commit-or-output. Tag `// [impl->REQ-ADAPTER-TRANSLATE-PROOF]`. `--help` text: states EMIT-half, no atomic apply; NO M#/W#/REQ tokens in clap help (docs-drift gate).
4. **Unit tests** (cli.rs tests mod near `:8487`): (a) clap parse test for `TranslateProof`; (b) gate test driving `xlate_choreo_fixture` (`env!("CARGO_BIN_EXE_xlate_choreo_fixture")`) as the adapter binary via a temp registry — emits the choreo stream on `{type:event}` → assert ok-on-output vs nonzero-on-empty. Tag `// [unit->REQ-ADAPTER-TRANSLATE-PROOF]`.
5. **Int**: drive the real `xlate_choreo_fixture` end-to-end through the command (new `crates/spt/tests/translate_proof.rs` or fold into an existing adapter-proof int). It emits `ctrl+s`/`delay`/`text:XLATE_OK`/`enter`/`delay`/`ctrl+s`/`commit` on `{type:event}` — perfect EMIT proof. Tag `// [int->REQ-ADAPTER-TRANSLATE-PROOF]`.
6. **Doc**: ADR-0022 (`docs/adr/`) — add a `translate-proof` subsection (author-time, EMIT-half, symmetric to digest-proof). Tag `<!-- [doc->REQ-ADAPTER-TRANSLATE-PROOF] -->`.
7. **Docs-drift gate**: regen CLI reference (`cargo xtask gen` or the repo's doc-gen; help-md strips MD markers per recent commits). Confirm no drift.
8. **Verify**: `cargo clippy -p spt --all-targets -- -D warnings` clean; new unit+int green; `traceable-reqs check` exit 0; CLI-ref regen no drift.
9. **Commit** (trailer `Co-authored by: SUBNET SPT_DEV`), `git push origin feat/translate-proof`, ping doyle (`$OWL send doyle`) to gate.

## Sample binary
`crates/spt-daemon/src/bin/xlate_choreo_fixture.rs` — pure stdin→stdout JSON-lines filter; on `{type:event}` emits the CC stash/restore choreography; `XLATE_FIXTURE_MODE=nocommit` drops the final `{commit}` (use for the no-commit gate variant); appends stdin lines to `XLATE_FIXTURE_STDIN_LOG`.
