Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.0 KiB
Handoff — burn-in, run 1 closed, run 2 not started
Written 2026-08-26, late. Read with BURNIN.md (the runbook and the findings
ledger), AUDIT.md, and CLAUDE.md. This session stopped adding workflow
features and started running real tasks. Everything below was observed live, not
inferred.
Deployed state
| Half | Revision | Evidence |
|---|---|---|
| Coordinator, homesrv container | 77a2b32 |
docker logs orchestra-api prints it at startup, /readyz ready |
| Worker, workpc systemd | 77a2b32 |
journalctl -u orchestra-worker, both harnesses serving |
Burn-in identity is 77a2b32. Both halves report it, which was the precondition
for a conformance run. deploy/build.sh [outdir] [rev] builds both from a
detached worktree of that revision, so a shared checkout cannot leak
uncommitted work into a stamped binary.
Deploying the coordinator:
ssh kami@192.168.1.104
repo=/home/kami/apps/orchestra; rev=$(git -C $repo rev-parse HEAD)
bt=$(git -C $repo show -s --format=%cI $rev); tree=/tmp/orchestra-build-$rev
git -C $repo worktree add --detach --quiet $tree $rev
docker build --build-arg BUILD_REVISION=$rev --build-arg BUILD_TIME=$bt \
--build-arg BUILD_DIRTY=false -f $tree/Dockerfile.api \
-t orchestra-web-ui-orchestra-api $tree
git -C $repo worktree remove --force $tree
cd /home/kami/docker-apps/orchestra-web-ui
docker compose up -d --no-deps --force-recreate orchestra-api
Do not use docker compose build: its context is the live checkout, which is
shared. Installing the worker needs root, so it is always the operator's step.
Another session owns 18 uncommitted paths
An auth and frontend session worked in this same checkout and has finished, but
its work is uncommitted: internal/authn/*, web/*,
internal/webui/assets/*, AGENTS.md, deploy/DEPLOYMENT.md,
deploy/orchestra.env.example, AUDIT.md, and an extension to
deploy/build.sh that also builds cmd/orchestra-user. Do not commit those on
its behalf, and do not use git add -A. Commit by path.
The deployed coordinator does not contain that work. Deploying it means committing it first.
One thing to check: this session's first commit, 7f12c7f, predates that
discipline and used git add -A. It swept in whatever was uncommitted then,
including web/src and internal/authn.
Where the burn-in stands
Run 1 is closed as a diagnostic, not a conformance run. Task
06G3YR34117MAYT6KEAC9RJHD0 from issue kami/test-e2e#1 needed three manual
leases, and its authority was rendered before the issue-body fix. It was
released with reason abandoned diagnostic run and sits at attempt: 3, so the
router will fail it.
What it proved anyway: .orchestra/launch.md renders authority order, the
ambiguity ladder, the phase brief, the standing decision set and a verified git
state; an opencode agent respected frame and changed no code; and a bad base
checkout nacked cleanly back to queued with no orphan pane.
Run 2 has not started. Every precondition is met except creating the task.
Do this first
- Create one ordinary issue in
kami/test-e2e, with a real body. The body is the goal and acceptance; the title alone is not enough. - Do not lease it by hand. Autonomous assignment is the thing under test.
- Watch, in this order:
GET /v1/router/health— if the task is not assigned within a minute, this names the gate that refused it. That is the finding; stop there.journalctl -u orchestra-worker -f— launch, nack or error.cat /tmp/test-e2e-worktrees/<task-id>/.orchestra/launch.md— the highest value artifact. Ask only whether the agent knows what the task wants, what was most recently decided, which phase it is in, what is merely history, and what to do next.
- Compare that against what the model does. Classify before changing anything: authority, context-selection, lifecycle, adapter/harness, model-following, or operator-policy. A prompt change is only ever the answer to a model-following failure.
Success criteria for run 2, in order: issue ingested, router assigns
workpc-opencode on its own, Store.Lease, pre-lease reconcile against
gitea:test-e2e only, agent launches, launch.md carries a body-derived goal
and acceptance, frame behaves, and the phase advances with no manual
lifecycle intervention.
Findings ledger
Fixed this session, all verified by test and most seen live:
- F1, authority: a federated worker could not read
GET /v1/tasks/<id>/intent, so every federated launch died with a 401.2753a8d. - F2, authority:
Gitea.eventdropped the issue body, so every Gitea task ran on its title withAcceptance: Not stated.09e572f. - F3, hygiene: the launch dump left
.orchestra/untracked in a worktree whose own context claimed a clean tree.a0209a2. - F5, lifecycle: every router eligibility gate now records a
router.RejectionatGET /v1/router/health, including tasks skipped for retry backoff. No gate was weakened.0ead6d2,4fbf3ac. - F7, security: an unset token means no check, so a full-control surface without a credential was an open control plane. Startup now refuses.
ORCHESTRA_TUI_TOKENis set.0ead6d2. - F8, correctness: reconciliation is bound to
task.Source, so a comment on one repository can no longer become an authoritative decision for a same-numbered task in another.0ead6d2. - F11, outage:
ValidateEventcompareduntil_nsagainsttime.Now(), so an expired lease event failed validation andstore.Openrefused the log tail. The API was in a restart loop. Validation is time-independent now.77a2b32.
Open, in the order this session would take them:
- F6, observability: worker health reports
active_task: nullwhile the store shows the task leased and herdr shows a live agent in its worktree. - F4, adapter quality:
harness "opencode" has no session-file resolver, so activity and thrash triggers are permanently degraded on opencode. Acceptable for a boring-success baseline; milestone and occupancy paths still work. - F9, lifecycle: releasing a leased task through
POST /v1/tasks/<id>/releaserequires supplyingharness_idandlease_epoch, becauseStore.Appendfences the event and the endpoint passes the body through. There is no operator escape hatch. - F10, hygiene: a coordinator-side release under a live worker leaves the worker renewing a lease it no longer holds.
- Unset gated tokens:
ORCHESTRA_MCP_TOKEN,ORCHESTRA_MAVEN_TOKENandORCHESTRA_AGENT_TOKENare all empty, so those surfaces need no credential. Bounded by capability to reads plus the three request endpoints, which is why startup does not refuse. Worth closing.
Things that will bite
snapshot.jsonlags the event log. It showed 30 tasks while/v1/tasksshowed 34. Read the API orevents.jsonl, never the snapshot, when checking live state.- The MCP surface is a read-only diagnostic today.
curl -H 'X-Orchestra-Surface: mcp' .../v1/tasksworks with no credential, which is how this session read live state without the operator login. Mutations need the TUI token from.envon homesrv. /tmpis tmpfs./tmp/test-e2e(a non-bare clone, originssh://git@gitea.kvmx.ru:2222) and/tmp/test-e2e-worktreesdo not survive a reboot, and/tmphas a 10-day sweep. A bare clone fails withfast-forward base checkout: fatal: this operation must be run in a work tree.- The three queued
corrextasks will never lease. No worker declares that project./v1/router/healthsays so plainly now. - 23 blocked test-e2e tasks are July leftovers. They have been inert across
hours of
ResumeAnsweredBlockers, so they are not a hazard, only noise. - A pane can push. Panes run as
kami, and pushing uses kami's registered SSH identity over port 2222. Isolation needs a separate unix user, not an environment scrub. - Ingest is now
kami/test-e2e, notcorrex.ORCHESTRA_GITEA_REPOwas switched for the burn-in; the previous.envis kept as.env.pre-burnin-20260826. The project id must equal the repo name.