carlos / platform Public

plan: R1 is three deliveries, not one

Found after the branch merged, while setting up the roll.

roll-console.sh builds ./cmd/console for the box and a NATIVE carlos used
only to drive ship/promote locally (its lines 52-53). It never touches the
box's root /opt/carlos/carlos binary — and §4b's restart recovery lives in
internal/release/adopt.go and internal/host/agent.go, which ARE that root
binary.

So R1 as written delivered the console half and silently left the adoption
fix on the shelf. The consequence is specific rather than tidy: R5's first
carlos deploy -app console would run against the OLD adoption pass, so a
failed deploy would recover through the exact defect §4b exists to fix.

Also names update-platform-binary.sh as the one tenant-visible step in the
runbook, since it restarts carlos-edge, and says to do one box at a time
and prove the edge is serving a real tenant before moving on.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 1aa28f9231a03809a42779b12ab64449e9de057b parent c135ccc
1 file changed, +25 −7
  • docs/superpowers/plans/2026-08-23-console-as-an-app.md +25 −7
diff --git a/docs/superpowers/plans/2026-08-23-console-as-an-app.md b/docs/superpowers/plans/2026-08-23-console-as-an-app.md
index 7661f6014..37318863a 100644
--- a/docs/superpowers/plans/2026-08-23-console-as-an-app.md
+++ b/docs/superpowers/plans/2026-08-23-console-as-an-app.md
@@ -1890,13 +1890,31 @@ Flagship's readings are in the spec's appendix. **Tito's are not, and it is depl
### R1 — Deliver the code by the legacy path, one last time
-```
-roll-console.sh <clean-checkout-at-merge-sha> both
-```
-
-Tasks 1–10 are console code; they reach the boxes only this way. **Without this, R5 runs against a console that predates its own probe and cannot succeed.** Also cut a CLI release carrying the new watch, or use a locally built `carlos` for R5–R6.
-
-Verify: `/proc/<pid>/exe` names the merge sha on both boxes, and `curl -s https://<origin>/healthz` returns `ok <sha>` — the first proof Task 5 is live.
+**THREE deliveries, not one.** Corrected 2026-08-28, after the branch merged and
+setting up the roll exposed the gap: `roll-console.sh` builds `./cmd/console` for
+the box and a *native* `carlos` used only to drive ship/promote locally (its lines
+52–53). **It never touches the box's root `/opt/carlos/carlos` binary.**
+
+| Delivery | Carries | How |
+|---|---|---|
+| console | the control-plane flag and its refusal doors, #79, the claim flags, `/healthz`, the ship-door checks, the probe echo | `roll-console.sh <clean-checkout> <box>` |
+| **root binary** | **§4b's restart recovery and its flap bound** — they live in `internal/release/adopt.go` and `internal/host/agent.go` | build `linux/arm64` with the version ldflag, upload to `s3://<deployment-bucket>/bootstrap/carlos`, then `update-platform-binary.sh <profile> <instance> <bucket> <sha256>` |
+| CLI | the build-probe watch, the dirty-tree guard | a release, or a locally built `carlos` for R5–R6 |
+
+Skipping the root-binary delivery is not cosmetic. R5's first
+`carlos deploy -app console` would run against the OLD adoption pass — so if that
+deploy failed, the recovery path would be the exact defect §4b exists to fix: the
+rollback leaving the console down and the next pass stamping over it. Deliver all
+three before R5.
+
+`update-platform-binary.sh` **restarts `carlos-edge`**, the front door for every
+tenant on the box — the one tenant-visible step in this runbook. Do one box at a
+time and verify the edge is serving a real tenant route before moving on.
+
+Verify: `/proc/<pid>/exe` names the sha for the console; `carlos version` on the box
+names it for the root binary; `systemctl is-active carlos-edge carlos-adopt.timer`;
+a real tenant hostname still answers 200; and `curl -s https://<origin>/healthz`
+returns `ok <sha>` — the first proof Task 5 is live.
### R2 — pinfra: `Type=notify` on `console.service`