← back to Answer Cockpit
TK-11793: README — run, endpoints, rails, detail sources (pane-contents), verification
0cdcea15d2908ef7e7da76b51a8a0d075040e8b1 · 2026-09-15 18:56:14 -0700 · Steve Abrams
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Files touched
Diff
commit 0cdcea15d2908ef7e7da76b51a8a0d075040e8b1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Sep 15 18:56:14 2026 -0700
TK-11793: README — run, endpoints, rails, detail sources (pane-contents), verification
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---
README.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..01d62db
--- /dev/null
+++ b/README.md
@@ -0,0 +1,53 @@
+# Answer Cockpit — one needs-Steve card at a time, one button to continue
+
+Aggregates every needs-Steve iTerm session (dots 🔵 lightblue · 🟠 orange · 🟣 purple · 🟡 yellow)
+into one urgency-ordered stream, shows **one card at a time** tinted to its dot, and one primary
+button pushes the answer/continue **into that terminal's live pane** (osascript `write text` +
+a second Enter) and advances. Ticket **TK-11793**. Cost **$0 (local)**.
+
+## Run
+```
+bash start.sh # → http://127.0.0.1:9805 (admin / DW2024!)
+bash start.sh --stop
+```
+Binds `127.0.0.1` only (hard-coded — it types into live agents). `start.sh` unsets
+`CLAUDE_CODE_CHILD_SESSION`/`CLAUDE_PID` so the server never trips the colordots bridge rail.
+Optional launchd: `com.steve.answer-cockpit.plist` (install is a Steve paste; never passes `--test`).
+
+## Endpoints (Basic auth; every mutation is POST; body ≤ 16KB)
+| Route | Does |
+|---|---|
+| `GET /api/queue?orphans=1` | scan (4s cache) → needs-Steve items, detail pre-resolved, memos merged by TK |
+| `GET /api/item/:tty` | one item, fresh scan (post-answer confirm) |
+| `POST /api/answer {tty,text,expectKey,force?,repaint?,dry?}` | type + submit into the pane |
+| `POST /api/continue {tty,expectKey}` | types `continue` (orange, after Steve ran the paste himself) |
+| `POST /api/focus {tty}` | select window/tab/session + activate |
+| `POST /api/memo/decide {file,decision,note,tty?}` | approve→`_approved/` · block→`_rejected/` · revise→note; `_decisions.jsonl` + reversible ledger; types the decision into the linked pane |
+| `POST /api/memo/undo {file,decision}` | mirror of approvals-viewer `:9795` undo |
+| `GET /api/health` | heartbeat (PASS/WARN/FAIL) + last 20 audit lines |
+
+## Rails (never loosened)
+- Never executes shell from a card or memo — Copy is the only verb for `! ` pastes / ```` ```ungate-run ````.
+- tty must match `^ttys\d{3}$` **and** be in a fresh live scan; refuses the cockpit's own tty;
+ refuses green/pink unless `force:true`; refuses codex REPLs unless `force`.
+- `expectKey` (`tty|ticket|color`) must match the current card → 409 on a stale card.
+- Text is an escaped AppleScript string literal fed on **stdin** (never `-e` concat); `\r`/control
+ chars rejected; `\n` space-joined. Single-flight `mkdir` lock + 1.2s pacing (no double-type).
+- Every write-back **and every refusal** is audited to `data/audit.jsonl`. Unmeasured is never
+ green: an unavailable terminal API → `stale:true`, POSTs 503, heartbeat WARN; iTerm down → FAIL.
+
+## Detail sources (where the card text comes from)
+1. `~/.claude/answer-cockpit/map/<tty>.json` (a future hook can make everything `exact`).
+2. `~/.claude/sessions/<pid>.json` → sessionId → transcript (`exact`).
+3. `lsof` cwd → project dir → newest transcript, validated (`likely` / `ambiguous`).
+4. **Pane contents** (`confidence:"pane"`) — transcript saving is OFF for ~half the fleet
+ ("inherited CLAUDE_CODE_CHILD_SESSION marker"), so the iTerm pane's own screen is read via
+ osascript `contents of session`; the prompt-box chrome is cut, a queued input is surfaced,
+ and an on-screen AskUserQuestion menu (`❯ 1. …`) is parsed into option buttons. A 1-char-per-
+ line scrollback (narrow-width collapse) is flagged, not shown as if real.
+
+## Verified 2026-09-15
+negative tests 401/400/403/409 + LAN refused · write-back typed **and executed** on a throwaway
+plain-shell pane · live queue 6 == 6 vs `allcolordots` · headless-Chrome render · parser unit test
+(positive / negative / degenerate). The real-yellow option-click proof is deferred until a live
+AskUserQuestion menu exists (none was pending at build time).
← 19f8c3b TK-11793: pane-contents source — iTerm screen as detail when
·
back to Answer Cockpit
·
TK-11793: Cody HOLD fixes — real-TUI menu corroboration (foo 82ab1f4 →