fix(herdr): close Phase 4 item 2 — actually ask the agent for a handoff
Release already validated and uploaded a §6.1 handoff, but nothing ever told the agent the .orchestra-handoff.json convention existed, so the file it waited on never got written. rotate() now prompts the agent once via a new optional herdr.HandoffRequester capability (CLIAdapter.RequestHandoff) when the file is missing, and defers Release until it appears, mirroring the .orchestra-report.md/B3 ask pattern rather than inventing a handoff. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
This commit is contained in:
@@ -717,7 +717,28 @@ cooperation):
|
||||
record the deviation" as the alternative to half-implementing that. Taking
|
||||
that option rather than bolting on an undesigned notification path.
|
||||
|
||||
**Still open from Phase 4**: item 2 (handoff production / stop-hook write of
|
||||
`.orchestra-handoff.json` for non-Claude harnesses is untouched; Claude's
|
||||
own stop-hook convention exists per B3/B5 but nothing yet drives Codex/
|
||||
opencode to write one).
|
||||
**Phase 4 item 2 — closed 2026-07-27.** The remaining gap after B5 was not
|
||||
"which harness" (Release was always harness-agnostic) — it was that *nothing,
|
||||
for any harness*, ever told the agent the `.orchestra-handoff.json` convention
|
||||
existed. `Coordinator.rotate` (internal/orchestrator/orchestrator.go) now
|
||||
checks whether the resolved adapter implements a new optional
|
||||
`herdr.HandoffRequester` capability; if `HandoffFile` isn't present in the
|
||||
worktree yet, it calls `RequestHandoff` once (`herdr.Session.HandoffRequested`
|
||||
guards against re-prompting every tick) and skips `Release` for that tick,
|
||||
leaving the lease intact — exactly the same "ask, don't invent" shape as B3's
|
||||
`.orchestra-report.md` convention. `CLIAdapter.RequestHandoff`
|
||||
(internal/herdr/adapter.go) sends a prompt naming the exact §6.1 JSON shape
|
||||
(`meta.id`, `anchor.git_sha`/`branch`/`dirty[].{path,sha256}`) and explicitly
|
||||
tells the agent not to fabricate the SHA/hashes. Once the file exists, the
|
||||
existing Release path (validate → scratch-commit dirty files → upload → CAS
|
||||
→ `pane.release_agent`) is unchanged. Covered by
|
||||
`TestRotationRequestsHandoffBeforeReleasing`
|
||||
(internal/orchestrator/rotation_test.go), which asserts `Release` is never
|
||||
called while the file is absent and fires once it's written. `go build`,
|
||||
`go vet`, `go test ./...` all pass.
|
||||
|
||||
Not attempted here (separate, deployment-level question, not a code gap):
|
||||
whether Codex's/opencode's own turn-boundary mechanism actually surfaces this
|
||||
in-pane prompt to the agent before it exits the way Claude Code's Stop hook
|
||||
does — that's Phase 2 item 4 territory (native Face B per harness), not
|
||||
Phase 4.
|
||||
|
||||
Reference in New Issue
Block a user