feat(harness): single-select answers auto-confirm (reviewer_select persists)

F — reviewer_select options may now carry a `decision` payload {type, subject,
detail?, rationale?} plus an optional `advance`. Picking such an option IS the
confirmation: the gate persists it directly (tht decision add) and optionally
advances, with no redundant reviewer_decide/reviewer_confirm follow-up gate.
Options without a payload stay ask-only; back/exit/Other never persist.

Pure logic extracted + exported for unit tests: resolveSelectOutcome (classifies
the response) and decisionAddArgs (shared with reviewer_decide, DRY). Gate JS
suite 33/33 (gate_select_decision.test.js, +5); harness pytest 269 unchanged.

Contract docs updated together: reviewer_select tool description, SKILL.md
(widget summary, disciplines 2-3, Phase-1 single-pick), and the CLAUDE.md gate
note. Live verification (model truly emits reviewer_select+decision, decision in
review_decisions.jsonl, no follow-up gate) deferred to workstream G — it is
model-behavior-dependent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 18:01:50 +02:00
co-authored by Claude Opus 4.8
parent b056ff334f
commit cef9ae4368
5 changed files with 159 additions and 52 deletions
+18 -10
View File
@@ -81,8 +81,8 @@ Opens frontend at http://localhost:5173 → backend :8787.
## UI/UX redesign + Resume — IN PROGRESS (2026-06-30, evening)
Approved multi-workstream plan: **`~/.claude/plans/foamy-forging-dahl.md`** (read it to resume).
Memory: `thothii-ui-redesign-inprogress.md`. **D + E merged @ `0eeb3f7` (pushed); B + C
implemented + live-verified (not yet committed as of this update).**
Memory: `thothii-ui-redesign-inprogress.md`. **D + E merged @ `0eeb3f7` (pushed); B + C @ `b056ff3`
(live-verified); F implemented + committed (live check deferred to G). All on `main`, not yet pushed.**
- **D — DONE** (`c12bdcd`): session display `name` = 3-5 Italian keywords via **YAKE** (no LLM),
derived in `tht session new` (CLI layer); `create_session` core unchanged (`name=None` default).
@@ -92,26 +92,34 @@ implemented + live-verified (not yet committed as of this update).**
model-stream tail**; `WorkingSpinner` extracted to its own module; the separate spinner button
+ orphaned `Transcript.tsx` removed. Frontend 87/87, tsc clean. **Live visual check DONE
(2026-06-30):** inline spinner opens the panel; 5-line collapsed tail; expand → full transcript.
- **B — DONE** (uncommitted): `WorkflowBar` is now colored **dots** F1..F8, no phase-name text
- **B — DONE** (`b056ff3`): `WorkflowBar` is now colored **dots** F1..F8, no phase-name text
(amber-translucent=running, green=done, red=error, gray=pending; green connectors lead the active
dot). Each dot carries `data-state`. Error is lightweight: store `phaseError` set when an `info`
`level=error` arrives during the phase, cleared on the next `ui_request` (`sessionStore.ts`).
**All four states live-verified** via Playwright.
- **C — DONE** (uncommitted): right sidebar — single-line denser rows (inline status dot + name,
- **C — DONE** (`b056ff3`): right sidebar — single-line denser rows (inline status dot + name,
`py-1`), a 3-level type hierarchy via **`/impeccable`** (L1 `SESSIONS` red/bold/wide-tracking ·
L2 section + group headers muted uppercase · L3 names normal-case), and the **"No group" label
removed** (ungrouped sessions render after the last group; guarded so the empty-state still
teaches when there are no groups). **Live-verified.** (Resume in `SessionMenu` stays with A1.)
- **Tests:** frontend **93/93** (was 87; +3 store `phaseError`, +2 `WorkflowBar` dot-state, +1
AppShell no-"No group"), `tsc -b` clean.
- **F (pending):** single-select answers **auto-confirm** — `reviewer_select` persists the
decision directly on a concrete choice (no redundant `reviewer_decide` gate); contract change
(update its tool desc + `SKILL.md` + the `CLAUDE.md` note). back/exit/Other stay non-persisting.
- **F — DONE** (uncommitted; live check deferred to G): single-select answers **auto-confirm**.
`reviewer_select` options may carry a `decision` payload (`{type, subject, detail?, rationale?}`)
and an optional `advance`; picking such an option persists the decision directly via
`tht decision add` (shared `decisionAddArgs` helper, also used by `reviewer_decide`) — no redundant
`reviewer_decide`/`reviewer_confirm` gate. Options without a payload stay ask-only; back/exit/Other
never persist. Pure logic extracted to `resolveSelectOutcome`/`decisionAddArgs` (exported, unit-
tested). Contract docs updated: `reviewer_select` tool desc + `SKILL.md` (widget summary,
disciplines 2-3, Phase-1 single-pick) + the `CLAUDE.md` gate note. Gate JS **33/33**, harness 269.
**Live verification (model actually uses `reviewer_select`+decision, no follow-up gate, decision in
`review_decisions.jsonl`) deferred to G** — it is model-behavior-dependent.
- **A (pending, riskiest):** Resume command + **FIX the resume cold-start stall** (open item #1).
- **G (later):** cross-model behavior matrix (Qwen3.6 / GLM 5.2 / Deepseek V4 / others).
- **G (later):** cross-model behavior matrix (Qwen3.6 / GLM 5.2 / Deepseek V4 / others) — also the
home for F's live verification.
**Next chunk:** **F** (single-select auto-confirm — harness gate/SKILL contract change), then **A**
(Resume in the kebab + the resume cold-start stall fix, diagnosis-first). **G** (cross-model) later.
**Next chunk:** **A** (Resume in the kebab + the resume cold-start stall fix, diagnosis-first).
**G** (cross-model, incl. F's live check) later.
## Live verification + reviewer_select fix (2026-06-30, afternoon)