feat(native): verify sealed plan provenance and regenerate once on mismatch #1309

Merged
coilyco-ops merged 2 commits from aos/claude/vt77 into main 2026-08-27 04:04:17 +00:00
Owner

Closes #1215. Advances #903.

What this does

Agent Compose seals each policy source's identity, revision, and policy SHA-256 into the repository plan. AOS decoded those fields and made no decision from them, so a plan compiled from policy that had since moved was indistinguishable at launch from one compiled a minute ago.

Native startup now fetches each policy source, verifies the seal, and stops before any worktree exists when one regeneration cannot fix a mismatch.

Decisions worth reviewing

The digest triggers, the revision only reports. This follows the director note on #903 rather than that issue's literal wording. A repository that holds policy also takes ordinary commits, and gating on revision drift would regenerate an already-correct plan at every launch. Revision drift is still reported.

Two commits are checked because two are read. The sealed digest is of the working-tree file, and session worktrees are cut from origin/main, so that is where a session's own policy comes from. Verifying the worktree base is how "session policy cannot be newer than repository selection" is enforced here, rather than by basing policy-source worktrees on the sealed revision. Basing them on the seal would start every session in a policy-holding repository several commits behind main, and grow without bound, for no benefit once the digest gate passes.

The retry budget is exactly one. Regeneration that is unavailable, fails, or still leaves provenance mismatched stops the launch rather than retrying.

Regeneration names the home that owns the plan. It derives HOME from the plan file it just read, so a session shadow cannot compose into its own HOME and leave the canonical plan stale.

The fetch is best-effort. A host off the network still launches; the digest comparison stays the gate. Fail-closed applies to verification, not to network reachability.

Tests

plan_provenance_test.go covers the three failure modes #1215 names, plus the passing control: regeneration unavailable, regeneration failing, regeneration succeeding but still mismatched, a successful regeneration, a missing policy source, a stale policy checkout caught at the worktree base, revision drift reported and not gated, and the JSON deprecation boundary. The stopped-launch cases assert no session worktree was created.

The existing native test helper now seals provenance that actually verifies, so every launch test exercises the gate rather than bypassing it.

Not done

docs/ is at its 40-doc cap and every native-* page is at its 120-line cap, so this could not take its own page. The provenance section went into docs/native-session-start.md, which meant reflowing that page denser to buy the room. Flagged in the issue thread rather than left implied.

🤖 Generated with Claude Code

Closes #1215. Advances #903. ## What this does Agent Compose seals each policy source's identity, revision, and policy SHA-256 into the repository plan. AOS decoded those fields and made no decision from them, so a plan compiled from policy that had since moved was indistinguishable at launch from one compiled a minute ago. Native startup now fetches each policy source, verifies the seal, and stops before any worktree exists when one regeneration cannot fix a mismatch. ## Decisions worth reviewing **The digest triggers, the revision only reports.** This follows the director note on #903 rather than that issue's literal wording. A repository that holds policy also takes ordinary commits, and gating on revision drift would regenerate an already-correct plan at every launch. Revision drift is still reported. **Two commits are checked because two are read.** The sealed digest is of the working-tree file, and session worktrees are cut from `origin/main`, so that is where a session's own policy comes from. Verifying the worktree base is how "session policy cannot be newer than repository selection" is enforced here, rather than by basing policy-source worktrees on the sealed revision. Basing them on the seal would start every session in a policy-holding repository several commits behind main, and grow without bound, for no benefit once the digest gate passes. **The retry budget is exactly one.** Regeneration that is unavailable, fails, or still leaves provenance mismatched stops the launch rather than retrying. **Regeneration names the home that owns the plan.** It derives `HOME` from the plan file it just read, so a session shadow cannot compose into its own `HOME` and leave the canonical plan stale. **The fetch is best-effort.** A host off the network still launches; the digest comparison stays the gate. Fail-closed applies to verification, not to network reachability. ## Tests `plan_provenance_test.go` covers the three failure modes #1215 names, plus the passing control: regeneration unavailable, regeneration failing, regeneration succeeding but still mismatched, a successful regeneration, a missing policy source, a stale policy checkout caught at the worktree base, revision drift reported and not gated, and the JSON deprecation boundary. The stopped-launch cases assert no session worktree was created. The existing native test helper now seals provenance that actually verifies, so every launch test exercises the gate rather than bypassing it. ## Not done `docs/` is at its 40-doc cap and every `native-*` page is at its 120-line cap, so this could not take its own page. The provenance section went into `docs/native-session-start.md`, which meant reflowing that page denser to buy the room. Flagged in the issue thread rather than left implied. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(native): verify sealed plan provenance and regenerate once (#1215)
All checks were successful
ci / aos-eval-tests (pull_request) Successful in 7s
ci / ward-doctor (pull_request) Successful in 7s
ci / aos-cli-tests (pull_request) Successful in 26s
ci / gate (pull_request) Successful in 57s
18b81f8683
Agent Compose seals each policy source's identity, revision, and policy
SHA-256 into the repository plan. AOS decoded those fields and decided
nothing from them, so a plan compiled from policy that had since moved was
indistinguishable at launch from one compiled a minute ago.

Native startup now fetches each policy source, verifies the seal, and stops
before any worktree exists when one regeneration cannot fix a mismatch.

The digest is the trigger and the revision only reports, per the director
note on #903: a repository holding policy also takes ordinary commits, and
gating on revision drift would regenerate a correct plan at every launch.

Two commits are checked because two are read. The seal is of the working-tree
file, and session worktrees are cut from origin/main, so verifying the base is
what keeps session policy no newer than the repository selection without
stranding sessions on the sealed commit's code.

The retry budget is exactly one. Regeneration that is unavailable, fails, or
still mismatches stops the launch rather than retrying. It takes HOME from the
plan it read, since a shadow composing into its own HOME would leave the
canonical plan stale.

The v1 JSON reader now warns and carries a 2026-10-01 removal boundary, and a
plan that seals no provenance is never authoritative, so cleanup stays off for
it exactly as for an absent plan.

Refs #903

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Agent-Role: platform
Merge remote-tracking branch 'origin/main' into aos/claude/vt77
All checks were successful
ci / aos-eval-tests (pull_request) Successful in 11s
ci / ward-doctor (pull_request) Successful in 5s
ci / aos-cli-tests (pull_request) Successful in 23s
ci / gate (pull_request) Successful in 47s
29b44b126a
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os!1309
No description provided.