docs: track AUDIT.md remediation progress

Record what's landed this pass (B1, B2, B4, B8, S1, S5, S6) and what's
still open, so the next session doesn't have to re-derive it from git log.
This commit is contained in:
kami
2026-07-27 19:44:42 +04:00
parent ca85b65557
commit 02d93fb63d
+56 -1
View File
@@ -1,6 +1,61 @@
# Orchestra progress
Updated: 2026-07-26
Updated: 2026-07-27
## AUDIT.md remediation — in progress
Working through `AUDIT.md`'s blocking/secondary defects in order of the
"suggested order of attack." Each item below is landed, tested, and
committed individually; see the git log for the exact commits.
Fixed so far:
- **B2** — adapters were looked up by `session.Harness` (the harness kind,
e.g. `"claude"`) in `Reconcile`/`expire`/`rotate`, but `AdapterFactory.Herdrs`
is keyed by herdr instance id (e.g. `"homesrv-claude"`). Every one of those
call sites silently no-opped. Added `Coordinator.adapterFor`, routed all
four call sites through it. Regression test registers an adapter under a
herdr-id key distinct from the harness kind and asserts rotation fires.
- **B1** — `CLIAdapter.Occupancy` called `a.Usage(s.PaneID)`, but the usage
readers want a filesystem path to session state, not a herdr pane id.
Added `herdr.Session.SessionFile` and per-harness resolution
(`ClaudeSessionFile` by newest-mtime under Claude Code's own project
directory; codex via the existing `CodexActiveUsage` sqlite discovery;
opencode refuses loudly — needs a live session id, not resolvable from the
worktree alone). A missing/unreadable session file is now a hard error,
surfaced via new `SessionHealth.Occupancy`/`OccupancyError` fields on
`GET /v1/tasks/{id}/health`, not a silent zero. **Still needs live
verification against a real Claude Code session** (the spec's own
acceptance bar for this phase) — not possible from this sandbox.
- **B4** — the router counted every `TaskReleased` (including rotation,
which *is* a `TaskReleased` carrying a valid `handoff_ref`) against
`MaxAttempts`, and double-counted by also incrementing on every
subsequent lease. A task that rotated twice hit the default
`MaxAttempts=3` and was killed. Now only a release without a
`handoff_ref` (expiry/crash) advances the counter.
- **B8** — `X-Orchestra-Surface: system` was reachable from an HTTP request
header in both `authz.HTTP` and `main.go`'s `surface` closure (the one
every handler actually calls). Since no deployment sets
`ORCHESTRA_SYSTEM_TOKEN`, this was an unauthenticated full-control bypass
reachable from any LAN caller. Both call sites now downgrade `system` to
`web` before doing anything else with it.
- **S1** — `Brief.From`/`To` and `GitSync.Branch`/`Head`/`Status` all shared
one JSON tag each (Go only honors the first `json:"..."` tag on a
combined field declaration). `go vet ./...` now passes clean.
- **S5** — `Store.Lease`/`ExpireLeases` set `Event.ID` to the task id, so
every lease of a task produced colliding event IDs. Now `domain.NewID()`.
- **S6** — the ingest dedup path returned `nil` (success) without
appending; `main.go` then returned an unrelated event with `201`. Added
`domain.ErrDuplicate` and `Store.TaskBySource`; `POST /v1/tasks` now
returns the existing task with `200` on a duplicate. Updated every other
`Append` caller (Gitea poll/webhook, JSONL ingest) to treat
`ErrDuplicate` as expected rather than a failure — without that, Gitea
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), B5/B6
(herdr protocol verification, Layer 3 wiring), B7 (quota projection has no
producer), S2S4, S7S11, and the Phase 0 live-herdr verification step that
several of the above still need. See `AUDIT.md` for the full plan.
## Current state