fix(harness): add automatic TaskCompleted producer (B3, partial)

POST /v1/harness/complete lets a Claude Code Stop hook report task
completion instead of relying on a human hitting the manual endpoint.
The hook only fires on an explicit .orchestra-report.md marker (not
every turn boundary); the server builds the receipt itself from the
real transcript via herdr.ClaudeUsage rather than trusting a
self-reported number. Codex/opencode producers and the turn-decision
endpoint are still unbuilt — see AUDIT.md/progress.md for scope.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
This commit is contained in:
kami
2026-07-27 21:24:17 +04:00
parent 63cda5557e
commit f8a397a14c
4 changed files with 167 additions and 3 deletions
+26 -3
View File
@@ -52,9 +52,32 @@ Fixed so far:
polling would error out of its scan loop on the first already-ingested
issue in every batch.
Not yet started: B3 (no `TaskCompleted` producer / no Stop hook), B6 (Layer 3
wiring), B7 (quota projection has no producer), S2S4, S7S11. See
`AUDIT.md` for the full plan.
- **B3 (partial)** — added `POST /v1/harness/complete`, the first automatic
`TaskCompleted` producer (previously only a human calling
`/v1/tasks/{id}/complete` could ever complete a task). A Claude Code Stop
hook (`deploy/hooks/orchestra-stop.sh`) fires on every turn boundary but
only reports completion if the agent has written a `.orchestra-report.md`
marker at the worktree root first — an ordinary turn boundary is a no-op,
so this doesn't fire completion prematurely. The server reads the
transcript locally via `herdr.ClaudeUsage` to build the `receipt` itself
(input/cache/output token counts) rather than trusting a self-reported
number, and uploads the report body to CAS for `report_ref`. Guarded by an
optional `ORCHESTRA_HARNESS_TOKEN` bearer check; the event is appended with
`Surface: system` set directly in Go (not derived from a request header —
consistent with the B8 fix that system must never be header-controlled).
**Not done:** Codex/opencode equivalents (Claude-only for now — Codex would
need `CodexActiveUsage`, opencode `OpenCodeUsage`/`OpenCodeStatus`, wired
the same way), and the turn-boundary decision endpoint
(`continue`/`prepare_handoff`/`rotate_now`/`refuse`) from Phase 2 items 12
is still unbuilt — only the completion half of Phase 2 landed. No test
added for the new HTTP handler; `cmd/orchestra/main.go` has zero test
coverage for any handler (pre-existing gap, everything lives inline in
`main()`) so this follows the existing (untested) pattern rather than
introducing a one-off test harness.
Not yet started: B6 (Layer 3 wiring), B7 (quota projection has no producer),
Codex/opencode completion producers, the turn-decision endpoint, S2S4,
S7S11. See `AUDIT.md` for the full plan.
**Phase 0 done (2026-07-27):** this box has live TCP reachability to the real
herdr instance at `192.168.1.105:9245` — verified by hand (raw JSON-RPC