The v3 stack, previously an uncommitted working tree, plus this session's two units and the burn-in instrument. This commit is the burn-in build identity: coordinator and worker must both report this revision before a task is created. Workflow (earlier sessions, uncommitted until now): human decision events and reduction, source cursors and reconcile-before-launch, turn-boundary reconciliation, internal/agentctx as the single renderer, ace-fca phases with sealed artifacts, the trajectory gate, bounded grilling, independent review, task pr enforcement, and human review reflection. Capability restrictions at the agent boundary: an authz.Agent surface at GatedWrite may ask and may not act. It also fixes two bugs the unit exposed -- gated surfaces could not reach the two endpoints written for them, and RequestHumanDecision would block an unowned task while rejecting a question from the session that did own it. Turn-boundary reconcile-failure escalation: a streak of consecutive failures asks the session to hand off, fenced on the lease epoch, with reconcile_failure as a real handoff reason. The worker was dropping the coordinator's verdict on the floor; it now acts on it. Burn-in: herdr.WriteLaunchContext dumps the exact agentctx.Build result to <worktree>/.orchestra/launch.md at every launch, local and federated. BURNIN.md is the runbook. deploy/build.sh stamps both binaries from one commit. go build, go vet and go test ./... pass, 20 packages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.1 KiB
Orchestra — session notes & next steps, 2026-07-31
Scope of this session: acted on REVIEW.md (the 2026-07-30 senior review), then
on seven operator review comments left on Gitea PR #1. Two commits on
webui-and-audit-reconciliation, pushed, not merged at time of writing.
Nothing was deployed. No live herdr or pane was touched.
What landed
56f5aac — reconcile docs, module graph, token compare, health
| Finding | Action |
|---|---|
| REVIEW.md 1 | CLAUDE.md/AGENTS.md federation drift fixed; clients/ tracked (later reversed — see below) |
| REVIEW.md 2 | progress.md references removed from CLAUDE.md, AGENTS.md, rotation_test.go, deploy/hooks/orchestra-codex-poll.sh |
| REVIEW.md 4 | web/go.mod stub added — ends the parent module's package graph at web/ |
| REVIEW.md 5 | orchestra-worker untracked (still on disk); both binaries gitignored |
| REVIEW.md 7 | subtle.ConstantTimeCompare in cmd/orchestra/main.go |
| REVIEW.md 3 | (already fixed in the review's own pass — SessionHealth.LastError + Observed) |
97a9c65 — delete Design A, hook completion path, retired deploy files
Deleted: clients/ (3 files), deploy/hooks/ (3 scripts),
deploy/config.example.json, deploy/orchestra.service, deploy/redeploy.sh,
deploy/docker-api-entrypoint.sh, the /v1/harness/complete route, the
unmounted harnessCompletion handler, and that handler's test.
Changed: Dockerfile.api now ENTRYPOINT ["/app/orchestra"]; docs updated
across CLAUDE.md, AGENTS.md, AUDIT.md, deploy/DEPLOYMENT.md,
deploy/orchestra.env.example, deploy/config.example.jsonc, .gitignore.
Ground truth established this session
Worth keeping — each of these corrected a documented claim.
-
orchestra-workerowns completion, end to end. It watches for.orchestra/donein the worktree, confirms viaAgentStatusthat the agent is not busy (a marker alone is intent, not proof), then finalizes and posts through/v1/federation/*with both lease epoch and expected version.cmd/orchestra-worker/main.go:385-412. -
The
deploy/hooks/scripts were vestigial, not partly-needed. They used a different, older convention (.orchestra-report.md) and posted to/v1/harness/complete, which was already a 410 stub — so that path could not have completed a task. It never fired because the live OpenCode QA run went through the worker./v1/harness/turnis a separate, still-live endpoint and was not touched. -
Env vars reach the API container via
env_file: .envin~/docker-apps/orchestra-web-ui/compose.yaml— that is where the Gitea/ntfy/web tokens and the bcrypt operator hash live. Only a single file,config.jsonc, is bind-mounted into/etc/orchestra/(viacompose.override.yaml). CLAUDE.md previously claimed the container mounted/etc/orchestra:roand that its entrypoint sourced the env file. Both wrong. -
ORCHESTRA_DATA/ORCHESTRA_PORTare baked into the image atDockerfile.apiline 17, independent of compose — which is why deleting the entrypoint script is behavior-neutral. -
teacannot infer this repo.originisssh://git@192.168.1.104:2222/...while the login knowsgitea.kvmx.ru, so everyteacall needs--login homesrv --repo kami/orchestra. Also: this Gitea rejectstea pr reply(405) andtea pr resolve("comment is not a review comment"), so review threads must be answered with a conversation comment and resolved in the browser. -
zsh does not word-split unquoted variables —
$FLAGSholding--login homesrv --repo kami/orchestraarrives as one argument.
REVIEW.md is less reliable than it claims
Its second pass asserts every independently checkable claim held up. Six did not. Treat it as a strong lead, not a verified record.
AUDIT.mdnever contained the false "Design B has zero clients" claim —AGENTS.mdwas the real second copy.- The non-local-herdr guardrail is at
orchestrator.go:312, not:309. - The
progress.mdreference list misseddeploy/hooks/orchestra-codex-poll.sh:6. - Finding 5's "untrack both" was half-actionable;
orchestrawas already gitignored. - Finding 4's blast radius was overstated —
Dockerfile.apibuilds./cmd/orchestraby explicit path and.dockerignorealready excludednode_modules, so it was a local/CI break, never a production-image break. - It claims that pass "corrected a comment that still described the retired
/v1/harness/completeas handling completion." It had not;main.go:556-561still did, and was fixed in97a9c65.
It also missed TOKEN_MINIMAL_WORKFLOW_PLAN.md and WEB_UI_PLAN.md entirely.
Next steps, in order
1. Rebuild the deployed image — nothing above is live yet
cd /home/kami/docker-apps/orchestra-web-ui
revision=$(git -C /home/kami/apps/orchestra rev-parse HEAD)
build_time=$(date -u +%Y-%m-%dT%H:%M:%SZ)
docker compose -f compose.yaml -f compose.live.yaml build \
--build-arg BUILD_REVISION="$revision" \
--build-arg BUILD_TIME="$build_time" \
--build-arg BUILD_DIRTY=false orchestra-api
docker compose -f compose.yaml -f compose.live.yaml up -d --build
docker logs orchestra-api | tail -30
Watch this one. It is the first container boot without
docker-api-entrypoint.sh. Expected: the process starts, reads config from the
bind-mounted config.jsonc, and picks up secrets from .env. Confirm
provenance afterwards at GET /v1/admin/diagnostics — its build object
should match 97a9c65, not an older revision.
2. Vikunja 350 — the single controlled live OpenCode continuity run
Still the project's real blocker: every "Closed" row in AUDIT.md rests on unit
tests. Prerequisites:
- Probe herdr reachability directly.
main.gologs connection failures only and never logs success, so absence of a log line means up, not down. - Check whether the stuck task is still stuck: workspace
wA, id06FT6CKD9Y98AZRX6X8K3QXFZG, opencode, panewA:p1,agent_status: "blocked". Code fixes do not unstick an orphaned pane; it needs a manual kill/restart, andCLAUDE.mdrequires asking before destructive herdr calls.
3. Vikunja 353 — constant-time compares in internal/federation
federation.go:368 (per-worker bearer token, checked on every authenticated
worker call — hottest path), :343 (admission shared secret). :346 is a
re-registration equality check, arguably not an auth decision. Use the inline
subtle.ConstantTimeCompare idiom from internal/authz/authz.go:111,241, and
preserve the empty-token-means-disabled semantics.
Note internal/provider/provider.go:333 is already correct (hmac.Equal).
4. Reconcile TOKEN_MINIMAL_WORKFLOW_PLAN.md against AUDIT.md
534 lines, dated 2026-07-29, status "proposed" — describes the target
unattended workflow (Vikunja ingest → router → worker syncs checkout →
immutable TASK.md → deterministic gates → push → Vikunja reflection) with an
explicit model-token boundary. Never audited. WEB_UI_PLAN.md is in the same
position. Decide for each: current plan, or obsolete.
5. Vikunja 351 — extract main.go's route closures (deferred)
97a9c65 removed ~80 lines, so this is marginally less pressing. Do it
incrementally, next time a route is added.
Dead code left deliberately in place
herdr.ClaudeStopHookUsage (internal/herdr/occupancy.go:106) and
herdr.OpenCodeStatus (:263) have no non-test callers now that the hook
scripts are gone. Kept as quota-source plumbing a future harness path may
want. If nothing claims them, they are a clean deletion.
Still-open assumption
REVIEW.md assumed clients/herdr-bridge.go was deployed; the operator
confirmed on 2026-07-31 that it is not, now that workers carry cross-machine
work. The deletion in 97a9c65 rests on that confirmation, not on a probe —
all six herdrs were unreachable as of 2026-07-29 and no probe was run this
session. If a bridge process turns up running on homesrv, it is running from an
installed binary with no source in the repo; recover it from 56f5aac, which
tracked the files before 97a9c65 removed them.