fix(aos): refresh the repository plan in silence instead of blocking the launch #1367

Merged
coilyco-ops merged 1 commit from aos/claude/mt75-quiet-plan into main 2026-08-29 01:16:48 +00:00
Owner

Kai could not launch at all tonight. This makes the sealed-plan check quiet and non-blocking.

What actually wedged

The plan sealed 3b6d851a while origin/main had moved to 4d3c00f7, and the canonical checkout was two commits behind. Regeneration seals from the checked-out revision and re-validates against origin/main, so it kept sealing the old digest and failing against the new one. It could never converge on its own, which is why the error repeated after regeneration and told the operator to pull.

The change

A stale digest is now a refresh trigger rather than a refusal:

  • mismatch regenerates once and reloads
  • unavailable, failed, or still-mismatched leaves the loaded plan in place and launches anyway
  • nothing is printed on any of those paths

The one exception is a refresh that could not run at all, which still says so in one line. That case leaves every later launch stale too, so silence there would hide the thing that matters.

Where the converge chatter was coming from

catalog, roster, wrote, linked, cascade, skills — those six lines are agent-compose's, but they reached a launching human through this file, which piped the child's stdout and stderr straight to the operator. They are now captured for the error instead.

That means the noise is gone from acompose without touching the agent-compose repository at all, which matters because that repo is scoped to another seat.

Why not delete the gate, which was the original ask

agent-compose compose --reapply is invoked from exactly one place: this file. The gate is therefore also the only automatic refresh of the repository plan on a native launch.

Deleting it outright would have traded tonight's wedge for a plan that goes quietly stale after every policy change. Tonight is the case: after the eval→science / tpm→director / devrel→advocate rename in #1357, a gate-less launch would have kept composing against a plan still naming devrel, and the failure would surface somewhere further from its cause. Kai chose this shape once that was on the table.

Tests

Three tests encoded stopping as the contract and now encode launching:

  • TestAPersistentMismatchStillLaunches
  • TestUnavailableRegenerationStillLaunches — asserts the one-line notice
  • TestFailedRegenerationStillLaunches — asserts the cause reaches the operator

One is new: TestARefreshedPlanPrintsNothing pins that a refreshed launch emits nothing at all, which is the property this PR exists for and the one most likely to be undone by accident.

A fourth test caught a real bug mid-change: my first version called regenerateRepositoryPlan directly and bypassed the runPlanRegeneration seam the tests stub, so the reload silently did nothing.

Verification

Full aos-cli suite green (243s), go vet clean, pre-commit run --all-files green.

Not included

The same six lines still print when someone runs agent-compose compose by hand. That is agent-compose/internal/converge, scoped to the Applied Scientist seat, and goes to Evie as a separate brief.

Kai could not launch at all tonight. This makes the sealed-plan check quiet and non-blocking. ## What actually wedged The plan sealed `3b6d851a` while `origin/main` had moved to `4d3c00f7`, and the canonical checkout was two commits behind. Regeneration seals from the **checked-out** revision and re-validates against **origin/main**, so it kept sealing the old digest and failing against the new one. It could never converge on its own, which is why the error repeated after regeneration and told the operator to pull. ## The change A stale digest is now a refresh trigger rather than a refusal: * mismatch regenerates once and reloads * unavailable, failed, or still-mismatched leaves the loaded plan in place and **launches anyway** * nothing is printed on any of those paths The one exception is a refresh that could not run at all, which still says so in one line. That case leaves every later launch stale too, so silence there would hide the thing that matters. ## Where the converge chatter was coming from `catalog`, `roster`, `wrote`, `linked`, `cascade`, `skills` — those six lines are `agent-compose`'s, but they reached a launching human through **this file**, which piped the child's stdout and stderr straight to the operator. They are now captured for the error instead. That means the noise is gone from `acompose` without touching the `agent-compose` repository at all, which matters because that repo is scoped to another seat. ## Why not delete the gate, which was the original ask `agent-compose compose --reapply` is invoked from **exactly one place**: this file. The gate is therefore also the only automatic refresh of the repository plan on a native launch. Deleting it outright would have traded tonight's wedge for a plan that goes quietly stale after every policy change. Tonight is the case: after the `eval→science / tpm→director / devrel→advocate` rename in #1357, a gate-less launch would have kept composing against a plan still naming `devrel`, and the failure would surface somewhere further from its cause. Kai chose this shape once that was on the table. ## Tests Three tests encoded *stopping* as the contract and now encode *launching*: * `TestAPersistentMismatchStillLaunches` * `TestUnavailableRegenerationStillLaunches` — asserts the one-line notice * `TestFailedRegenerationStillLaunches` — asserts the cause reaches the operator One is new: `TestARefreshedPlanPrintsNothing` pins that a refreshed launch emits nothing at all, which is the property this PR exists for and the one most likely to be undone by accident. A fourth test caught a real bug mid-change: my first version called `regenerateRepositoryPlan` directly and bypassed the `runPlanRegeneration` seam the tests stub, so the reload silently did nothing. ## Verification Full `aos-cli` suite green (243s), `go vet` clean, `pre-commit run --all-files` green. ## Not included The same six lines still print when someone runs `agent-compose compose` by hand. That is `agent-compose/internal/converge`, scoped to the Applied Scientist seat, and goes to Evie as a separate brief.
fix(aos): refresh the repository plan in silence instead of blocking the launch
All checks were successful
ci / aos-cli-tests (pull_request) Successful in 25s
ci / aos-eval-tests (pull_request) Successful in 7s
ci / gate (pull_request) Successful in 46s
8a6290d25a
Kai hit the gate tonight and could not launch at all. The plan sealed
3b6d851a while origin/main had moved to 4d3c00f7, and the checkout was two
commits behind, so regeneration sealed from the checked-out revision and
re-validated against origin/main. It could never converge on its own.

The check now triggers a refresh rather than a refusal. A stale digest
regenerates once and reloads; unavailable, failed, or still-mismatched
leaves the loaded plan in place and launches anyway, because a stale plan
is a worse launch rather than an impossible one.

Silent on every path but one. The converge report is Agent Compose talking
to itself on a good run, so it is captured for the error rather than piped
to the operator, which is where `catalog`, `roster`, `wrote`, `linked`,
`cascade` and `skills` were reaching a launching human from. A refresh that
could not run still says so in one line, since that case leaves every later
launch stale too.

Deleting the gate outright was the ask, and it would have cost more than it
looked. `agent-compose compose --reapply` is invoked from exactly one place,
this file, so the gate also owns the only automatic refresh on a native
launch. Removing it would have traded tonight's wedge for a plan that goes
quietly stale after every policy rename, which is the same failure further
from its cause.

Three tests encoded stopping as the contract and now encode launching. One
new test asserts a refreshed launch prints nothing at all.

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
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!1367
No description provided.