fix(herdr): B5 — replace invented pane.kill/release/rotation_signal with real methods
Verified against a live herdr instance (192.168.1.105:9245) that pane.kill,
pane.release, and pane.rotation_signal never existed in the protocol, as
AUDIT.md's B5 suspected. Real method list captured in deploy/herdr-schema.json.
- Kill now calls the real pane.close({pane_id}).
- RotationSignal interface/method/call-site deleted; no real equivalent exists.
- Release now refuses loudly instead of calling a nonexistent method — the
real pane.release_agent can't return a handoff_ref either way (herdr
doesn't write handoffs, the agent does), so a real fix needs Phase 4
handoff production first.
Also documents Phase 0 findings in AUDIT.md/progress.md, and adds
CLAUDE.md/AGENTS.md with project-specific knowledge (herdr protocol facts,
deployment topology, a currently-stuck live task, the federation fork) for
future sessions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
This commit is contained in:
@@ -473,3 +473,67 @@ If you want one thing to do today: **Phase 0**, then **B2** (a ~20-line fix
|
||||
that makes three subsystems reachable), then **B1**. Those three turn a system
|
||||
that cannot rotate into one that can, and everything else in the plan is
|
||||
building on top rather than repairing underneath.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0 — done, 2026-07-27
|
||||
|
||||
B1, B2, B4, B8, S1, S5, S6 were already fixed and landed as of this session
|
||||
(confirmed by reading the current code, not just trusting progress.md — see
|
||||
`adapterFor` in `internal/orchestrator/orchestrator.go:190` and
|
||||
`CLIAdapter.Occupancy` in `internal/herdr/adapter.go:197`).
|
||||
|
||||
This box (homesrv) turned out to have live TCP reachability to the real herdr
|
||||
instance at `192.168.1.105:9245` (workpc) the whole time — the `unavailable:
|
||||
connection refused` lines in `journalctl -u orchestra.service` are for
|
||||
`homesrv-*` herdrs dialing `192.168.1.104:9245`, which has no local herdr
|
||||
running; `workpc-*` herdrs were connecting fine but main.go never logs a
|
||||
success, only a failure, so there was no positive signal either way. Also
|
||||
found: **a real task is stuck live right now** — workspace `wA`, task
|
||||
`06FT6CKD9Y98AZRX6X8K3QXFZG`, opencode agent, pane `wA:p1`, `agent_status:
|
||||
"blocked"` — almost certainly stuck because `Release`/rotation could never
|
||||
reach it (see below).
|
||||
|
||||
Ran the actual Phase 0 steps against this live instance (raw JSON-RPC probes
|
||||
over TCP, params-omitted/empty-object tricks to read Rust serde's
|
||||
missing-field errors — no `herdr` CLI available locally, so `herdr api schema
|
||||
--json` itself wasn't run, but the equivalent info was extracted this way).
|
||||
Full method list and findings committed to `deploy/herdr-schema.json`.
|
||||
|
||||
**Confirmed, with a real server response, not just static reading of
|
||||
adapter.go:**
|
||||
- `pane.release`, `pane.kill`, `pane.rotation_signal` — **none of these exist**
|
||||
in the real protocol. Confirms B5's suspicion exactly.
|
||||
- Real replacement for `pane.kill` is `pane.close({pane_id})` — same shape,
|
||||
drop-in. **Fixed** in `internal/herdr/adapter.go`.
|
||||
- Real replacement for `pane.release` is `pane.release_agent({pane_id,
|
||||
source, agent})` — structurally different, and per B5's own analysis it
|
||||
cannot return a `handoff_ref` regardless (herdr doesn't write handoffs, the
|
||||
agent does, §6.1). Wiring this for real needs Phase 4's handoff-production
|
||||
path first. `CLIAdapter.Release` now returns a loud error naming exactly
|
||||
that instead of calling a method that doesn't exist. **Not a full fix** —
|
||||
Phase 4 still owns making Release do something real.
|
||||
- `pane.rotation_signal` doesn't exist and never will (herdr has no rotation
|
||||
concept) — deleted `RotationSignal` interface, its `CLIAdapter` method, and
|
||||
the call site in `Coordinator.rotate`, per this doc's own instruction
|
||||
("Delete ... unless the schema proves it exists").
|
||||
- `agent.get`, `pane.read`, `agent.prompt`, `worktree.create`, `worktree.open`,
|
||||
`agent.start` — all confirmed real, no changes needed there.
|
||||
- Protocol version confirmed live: `17`, matching `config.jsonc`'s
|
||||
`"protocol": "17"` (returned as a bare JSON number by the server; the
|
||||
existing string-fallback parse in `CheckProtocol` happens to handle that
|
||||
correctly already).
|
||||
|
||||
`go build ./...`, `go vet ./...`, `go test ./...` all pass after these
|
||||
changes.
|
||||
|
||||
**Still open from B5** (not attempted this pass — larger, needs design, not
|
||||
just a method-name swap):
|
||||
- `agent.prompt` inline `wait` on `CLIAdapter.Lease` (still `wait=0`, per B5's
|
||||
note that only `Bootstrap` passes a real wait).
|
||||
- `Release`'s real implementation, which depends on Phase 4 (§6) handoff
|
||||
production existing at all.
|
||||
- The stuck live task (`06FT6CKD9Y98AZRX6X8K3QXFZG`) was deliberately **not**
|
||||
manipulated directly (no `pane.close`/`pane.release_agent` call against it)
|
||||
— killing or releasing a real running agent from an audit session without
|
||||
the user present is exactly the kind of action that warrants asking first.
|
||||
|
||||
Reference in New Issue
Block a user