v3 workflow: intent, phases, review, submission, enforcement, burn-in

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>
This commit is contained in:
2026-08-26 18:31:20 +04:00
parent 97a9c65302
commit 7f12c7fc37
78 changed files with 16417 additions and 352 deletions
+27 -6
View File
@@ -25,6 +25,11 @@ const (
Web Surface = "web"
MCP Surface = "mcp"
Maven Surface = "maven"
// Agent identifies a coding session running inside a harness pane. It may
// perform work and *request* lifecycle changes; it may never perform one.
// Everything Orchestra owns — phase, review, submission, completion, lease
// state — is denied to it by GatedWrite, at the endpoint and at the bus.
Agent Surface = "agent"
// System identifies the plane itself — the router, coordinator, provider
// adapters, and lease-expiry reclaim. Per invariant 2 ("the plane emits
// events, not the agent"), these are the only non-surface emitters and are
@@ -50,7 +55,7 @@ func CapabilityFor(s Surface) Capability {
return NotifyOnly
case TUI, Web, System:
return FullControl
case MCP, Maven:
case MCP, Maven, Agent:
return GatedWrite
default:
return Observe
@@ -79,6 +84,22 @@ func AuthorizeEvent(s Surface, typ string) error {
// credentials are exchanged once for this HttpOnly receipt.
const SessionCookie = "orchestra_session"
// HarnessTurnPath authenticates its own bearer token inside the handler, the
// way federation endpoints do. It needs an exemption from the surface gate
// below for the same reason they do: an unlabelled request defaults to the Web
// surface, which is session-gated, so a harness could never reach it.
const HarnessTurnPath = "/v1/harness/turn"
// GatedWritePaths are the only mutating paths a GatedWrite surface may reach.
// Each one records a request — an approval, a bounded question, a deferred
// finding — and none of them moves the lifecycle. Handlers re-check with
// AuthorizeEvent, so widening this list alone cannot grant authority.
func GatedWritePath(p string) bool {
return strings.HasSuffix(p, "/approval") ||
strings.HasSuffix(p, "/decision-request") ||
strings.HasSuffix(p, "/deferred")
}
// SessionPath is the one Web-surface endpoint exempt from the session gate,
// because it verifies login credentials and exchanges them for a cookie.
const SessionPath = "/v1/ui/session"
@@ -205,7 +226,7 @@ func HTTPWithSessions(tokens map[Surface]string, sessions *Sessions, next http.H
(r.Method == http.MethodGet && r.URL.Path == "/v1/tasks") ||
(r.Method == http.MethodPost && r.URL.Path == "/v1/artifacts") ||
(r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/v1/artifacts/"))
if federationRegistration || (worker && workerPath) {
if federationRegistration || r.URL.Path == HarnessTurnPath || (worker && workerPath) {
next.ServeHTTP(w, r)
return
}
@@ -246,10 +267,10 @@ func HTTPWithSessions(tokens map[Surface]string, sessions *Sessions, next http.H
http.Error(w, "notify-only surface", http.StatusForbidden)
return
}
if (s == MCP || s == Maven) && r.Method != http.MethodGet && r.Method != http.MethodHead && r.URL.Path != "/v1/events" {
// Gated clients may submit only approval requests; ordinary control
// endpoints must never become an accidental write path.
if !strings.HasSuffix(r.URL.Path, "/approval") {
if CapabilityFor(s) == GatedWrite && r.Method != http.MethodGet && r.Method != http.MethodHead && r.URL.Path != "/v1/events" {
// Gated clients may only ask; ordinary control endpoints must never
// become an accidental write path.
if !GatedWritePath(r.URL.Path) {
http.Error(w, "approval required", http.StatusForbidden)
return
}