Skip to content

Upgrade verbs: server-binary/extension/agents/skills — receipts, lock, abort paths, idempotence - #535

Merged
aarontrowbridge merged 7 commits into
mainfrom
526-upgrade-verbs
Aug 23, 2026
Merged

Upgrade verbs: server-binary/extension/agents/skills — receipts, lock, abort paths, idempotence#535
aarontrowbridge merged 7 commits into
mainfrom
526-upgrade-verbs

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

Closes #526.

The four upgrade chains as receipt-emitting idempotent runbooks (spec-20260823-094507 D2): pre-flight doctor gate (current→no-op, unknown→abort, stale/integrity-failure→proceed), git discipline (clean+ancestor, aborted-diverged; extension's clean-but-behind→ff-only), the full server-binary chain with opencode.prev rollback + sidecar rewrite on restore, flock-semantics lock (O_EXCL + dead-holder steal — macOS ships no flock(1)), append-only JSONL receipts, and the record-name alias (agent-cards-global→agents, CLI-side per spec D3).

Hermetic suites: 34 tests across the four verbs (idempotence stale→upgraded→no-op with enumerated digest sets; verification independence — doctor re-run vs receipt post records; abort paths; the restore path both ways). Typecheck clean; the 2 remaining failures are the proven pre-existing machine-state tests.

The live dispatch proof (review-blocking, per the issue's separability clause): the parent runs the real server-binary upgrade on the mini per docs/upgrade-live-dispatch.md and cites the appended JSONL receipt here. CI blocks hermetic only — as specced.

Part of #524.

The panel passes doctor's record names verbatim (spec D3 — an alias
map in the panel would be a fact doctor didn't say); the aliasing
belongs CLI-side. agent-cards-global/-staging → agents, normalized in
parseUpgradeArgs so downstream sees one vocabulary.
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: de5cf7b3-7299-4519-ae57-4df3e5cc5123

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

…n missing roots

The server-binary verb unwrapped ctx.roots without filling defaults:
on fixture paths the roots are injected; on the live CLI none were,
so ctx.roots.rootRepoFork was undefined and the join crashed. Defaults
are now deep-merged before use (the fix the live run surfaced).
@aarontrowbridge

Copy link
Copy Markdown
Member Author

Live dispatch — the honest record (parent-run, per docs/upgrade-live-dispatch.md):

The full live chain ran on the mini, and the surface is now current, healthy, and verified — but the happy-path receipt this PR's proof clause asks for is not obtainable today, because the surface is no longer stale. The receipts tell the real story:

  1. 19:21 — aborted-error (fixed in 5928fb7 + 2b83d011-committed followup): live dispatches crashed on unmerged root defaults — the exact live-only bug fixtures can't catch. Fixed, tested, pushed.
  2. 19:24 — restore-failed (the incident): the verb executed the ENTIRE chain live — env preflight, fork clean-but-behind ff-only to HEAD, bun build, smoke, freeze with prev preserved, kick, 120s health poll + re-kick retry — then detected real unhealthiness and ran the FULL restore: prev verified by sha, sidecar rewritten, restore-kick. The server was in a launchd flap (root cause: kick race, filed upgrade verb: kick race under launchd — wait for old pid exit, distinguish flap from boot #538 — not the binary: the same-source artifact runs clean, and even the restored prev flapped that window before recovering). The rollback machinery passed its first real-world test.
  3. Now — no-op, verification: true: with the fleet healthy and current (a coherent manual freeze of the same-source build landed during the incident window), the live re-run exits 0, writes a no-op receipt, touches nothing. Independent cross-checks: doctor=current, frozen sha == sidecar == running sha, no prev retained.

What's missing for the letter of the proof clause: an outcome: upgraded, verification: true receipt — unobtainable while the surface is already current (pre-flight correctly no-ops). It lands naturally at the next fork merge.

The review decision: (a) hold this PR until the next natural staleness event produces the upgraded receipt, or (b) accept the incident + no-op receipts as the live proof — arguably stronger evidence: the failure path is the one you can't fake. Tagging for a human call; CI is green-blocking regardless.

@aarontrowbridge

Copy link
Copy Markdown
Member Author

Live dispatch proof: ACCEPTED (Aaron, 2026-08-23). The incident receipt (full chain executed live + the rollback machinery proven in a real launchd-race failure, #538) + the no-op/verified receipt satisfy the proof clause — the failure path is the stronger evidence. The happy-path 'upgraded' receipt lands in the receipts store naturally at the next fork merge; the watchdog will report it.

@aarontrowbridge
aarontrowbridge marked this pull request as ready for review August 23, 2026 21:47
@aarontrowbridge
aarontrowbridge merged commit 331a657 into main Aug 23, 2026
8 checks passed
@aarontrowbridge
aarontrowbridge deleted the 526-upgrade-verbs branch August 23, 2026 21:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade verbs: server-binary/extension/agents/skills — receipts, lock, abort paths, idempotence

1 participant