carlos / platform Public

spec: region HA spec 1 rev 4.2, answering Astra round 5 (A5-1)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev b27dd41ab2c0a92abf412f69e368ac637c41f893 parent 1cfa15b
3 files changed, +104 −9
  • docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md +22 −9
  • docs/superpowers/specs/CODEX-FINDINGS-REGION-HA-5.md +21 −0
  • docs/superpowers/specs/CODEX-REVIEW-BRIEF-REGION-HA-6.md +61 −0

CI failed — run details

diff --git a/docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md b/docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md
index 20f70e5f0..4ddb77d47 100644
--- a/docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md
+++ b/docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md
@@ -1,7 +1,8 @@
# Region HA, spec 1: placing an instance on a box
-Design, 2026-10-04, **rev 4.1**. DRAFT. Nothing here is built.
+Design, 2026-10-04, **rev 4.2**. DRAFT. Nothing here is built.
+Rev 4.2 answers Astra round 5 (`CODEX-FINDINGS-REGION-HA-5.md`, A5-1).
Rev 4.1 answers Astra round 4 (`CODEX-FINDINGS-REGION-HA-4.md`,
**A4-n**). Rev 4 answers Astra round 3 (`CODEX-FINDINGS-REGION-HA-3.md`, **A3-n**,
plus the A2-5, A2-7 and A1-1 residuals). Rev 3 answered Astra round 2 (`CODEX-FINDINGS-REGION-HA-2.md`, cited
@@ -494,17 +495,21 @@ these in order, journaling each:
1. **Stop every writer (A4-1).** Close admission, drain spawn attempts,
drain in-flight timer deliveries (moves §9.4), then stop the host's
process tree and wait for it to be empty: the per-host cgroup's
- `populated 0`, no member processes, and no holder of the database,
- WAL or SHM files (claim §6.1's process half). From here nothing can
- change the database, files or wake state.
+ `populated 0` and no member processes. The database, WAL and SHM
+ files may still be held, but **only** by the box's own replicator for
+ this host, identified by the agent's pid and the replicator's own
+ descriptors (A5-1). Any other holder fails the step. From here nothing
+ but the replicator can touch the database, and nothing at all can
+ change files or wake state.
2. **Flush the database:** final checkpoint and `SyncAndWait`, then
record the **final TXID** `N`, the `MaxTXID` of the newest level-0
file (moves rev 7.6 §5.1 step 1).
3. **Publish every pending file and wake-state mutation**, whatever the
app's `files_durability`, and record the manifest's final `seq`.
-4. **Finish stop evidence:** close the replicators and the file
- publisher, and check claim §6.1's remaining conditions. Only now is
- the release complete.
+4. **Finish stop evidence:** close the replicator (`DB.Close`) and the
+ file publisher, then run claim §6.1's **unrestricted** check: no
+ holder at all of the database, WAL or SHM files in `/proc/*/fd`, and
+ every other condition. Only now is the release complete.
Because step 1 empties the process tree first, the positions recorded in
steps 2 and 3 really are final.
@@ -757,7 +762,7 @@ those specs finalise a one-box-per-region assumption.
| # | Spec | Change |
|---|---|---|
| K1 | claim §5.1 step 4 | `exec` is the box `choose()` picks among the region's eligible boxes, not "the record region's box". |
-| K2 | claim §4, §8 | New op kind `relocating` (§5.8): same region, from `serving`, with its phase table, admission and rows per phase, the `installed` no-reinstall boundary, the phase-specific replacement table (termination and probe failure), the two-replacement bound and `stuck`, and the release sequence (stop every writer first, then journal the final TXID and manifest `seq`, then finish stop evidence; for the source and for a failed target). Recovery owner: the region placer. Excludes moves and placements, as `placing` does. |
+| K2 | claim §4, §8 | New op kind `relocating` (§5.8): same region, from `serving`, with its phase table, admission and rows per phase, the `installed` no-reinstall boundary, the phase-specific replacement table (termination and probe failure), the two-replacement bound and `stuck`, and the release sequence (stop every application writer first, allowing only the box's own replicator handles; then journal the final TXID and manifest `seq`; then close the replicator and run the unrestricted holder check; for the source and for a failed target). Recovery owner: the region placer. Excludes moves and placements, as `placing` does. |
| K3 | claim §7.2, CC5 | A **termination fence** (§5.9), bound to a verified box record, is a lost-box fence, written automatically by the region placer. `terminated` only; `stopped` stays operator-only. No `--readmit` for a terminated box; it still goes on `lost`. The operator path keeps §7.2's terminal-state rule: a CloudTrail request record never substitutes for it. |
| K4 | claim §8 | Region placers (boxes) need claim CAS rights for `relocating` and for removing a terminated box's obligations. |
| K5 | claim §9 | Adoption names "the record region's serving box". With several boxes that is ambiguous, so adoption must finish while the region has one box (§8 step 3). |
@@ -785,7 +790,9 @@ those specs finalise a one-box-per-region assumption.
- **Relocation:** every row of the replacement table, the
two-replacement bound, `probe-failed` without stop evidence, the
source's rows through every phase, and relocate → write → replicate →
- terminate → cold restore with the level-0 anchor.
+ terminate → cold restore with the level-0 anchor; a release with a
+ live embedded replicator (step 1 passes with only its descriptors,
+ step 4 passes only after `DB.Close`, any other holder fails step 1).
- **Integration:** two agents against one fake region, one control
bucket: create lands on the chosen box only; the other box mints no
row; the edge backhauls to the executor; relocate by drain through
@@ -871,3 +878,9 @@ those specs finalise a one-box-per-region assumption.
| A4-1 P1: the release sequence flushes before stopping writers | accepted: stop and empty the process tree and timer deliveries first, then flush and journal, then finish stop evidence (§5.8), K2 |
| A4-2 P2: the conditional Deny blocks multipart preparation | accepted: `s3:ObjectCreationOperation: true` on every header Deny; multipart completion carries the header; tested (§6) |
| A4-3 P3: 29245f69 is not moves rev 7.6 | accepted: rev 7.6 named as an uncommitted draft, rev 7.5 at cdc98845 as the last committed; the plan pins the commit (header) |
+
+## 17. Astra round 5 dispositions
+
+| Finding | Disposition |
+|---|---|
+| A5-1 P1: step 1 waits for the replicator's handle, closed only in step 4 | accepted: step 1 allows only the box's own replicator descriptors; step 4 closes it and runs the unrestricted check; tested with a live replicator (§5.8), K2 |
diff --git a/docs/superpowers/specs/CODEX-FINDINGS-REGION-HA-5.md b/docs/superpowers/specs/CODEX-FINDINGS-REGION-HA-5.md
new file mode 100644
index 000000000..5613e260c
--- /dev/null
+++ b/docs/superpowers/specs/CODEX-FINDINGS-REGION-HA-5.md
@@ -0,0 +1,21 @@
+Reviewed rev 4.1 at `1cfa15bf`, against claim rev 6.3 and the supplied moves rev 7.6 draft.
+
+| Finding | Disposition |
+|---|---|
+| A4-1 — release ordering | **Partly resolved.** Application processes stop before flushing, but the new first step also requires the still-open replicator’s file descriptors to be gone. See A5-1. |
+| A4-2 — multipart preparation | **Resolved.** The object-creation qualifier exempts multipart preparation while enforcing conditional completion, matching [AWS’s documented policy](https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes-enforce.html). |
+| A4-3 — dependency revision | **Resolved.** The header correctly identifies rev 7.6 as uncommitted and requires the plan to pin its commit. |
+| A3-2 — target durability barrier | **Partly resolved.** Final positions and minimum pinning requirements remain explicit, but A5-1 blocks the release sequence. |
+| A2-7 residual — failed-probe recovery | **Partly resolved.** Recovery preserves the required positions once release completes; A5-1 prevents normal completion. |
+
+**A5-1 — P1 — §5.8: the first release step waits for handles that close only in step 4.** [Location](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/region-ha/docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md:494)
+
+**Problem:** Step 1 requires no remaining holder of the database, WAL or SHM files, citing claim §6.1. That claim’s check scans `/proc/*/fd`; it includes the platform’s embedded replicator. Litestream v0.5.14 explicitly opens a [long-running database descriptor](/home/paulca/go/pkg/mod/github.com/benbjohnson/litestream@v0.5.14/db.go:1000), which remains open until [DB.Close](/home/paulca/go/pkg/mod/github.com/benbjohnson/litestream@v0.5.14/db.go:799). This sequence keeps the replicator open for step 2’s `SyncAndWait` and closes it only in step 4.
+
+**Failing sequence:** A healthy, replicating source begins a drain. Admission closes, timer deliveries drain, and the application cgroup empties. The descriptor scan still finds Litestream’s database handle in the platform process. Step 1 cannot finish, so the final flush and replicator close are never reached. A failed-probe target encounters the same obstruction and becomes `stuck`.
+
+**Suggested fix:** In step 1, establish that application processes and other application writers have stopped, allowing only explicitly identified platform replication/flush handles to remain. Flush and journal the final positions, close those handles, then perform the unrestricted no-holder check as part of step 4’s final stop evidence. Carry this distinction into K2 and test release with an initialized embedded replicator.
+
+All code `file:line` citations were checked against `1cfa15bf`. No files were changed or tests run.
+
+**Verdict: not ready.**
\ No newline at end of file
diff --git a/docs/superpowers/specs/CODEX-REVIEW-BRIEF-REGION-HA-6.md b/docs/superpowers/specs/CODEX-REVIEW-BRIEF-REGION-HA-6.md
new file mode 100644
index 000000000..ee9ce3b51
--- /dev/null
+++ b/docs/superpowers/specs/CODEX-REVIEW-BRIEF-REGION-HA-6.md
@@ -0,0 +1,61 @@
+# Review brief: region HA spec 1 (box placement), round 6
+
+You are an independent second reader. Review
+`docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md` at
+the commit named in the prompt, in the repository at the working
+directory (Go; carlos platform).
+
+## Fixed: do not re-argue
+
+§0's rulings H1 to H6 are Paul's and are fixed, as are the standing
+rulings listed under them. Report only mechanisms that fail to honour
+them, are unsafe, or are missing.
+
+## What the spec builds on
+
+- Host lifecycle claim rev 6.3: file
+ `/home/paulca/amadan.net/carlos/platform/.claude/worktrees/replica-ownership/docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md`
+- Move-any-app rev 7.6 (uncommitted draft in the moves worktree below; rev 7.5 is cdc98845): file
+ `/home/paulca/amadan.net/carlos/platform-moves-design/docs/superpowers/specs/2026-10-02-move-any-app-design.md`
+- Nearest-region, on main: `docs/superpowers/specs/2026-10-01-nearest-region-default-design.md`
+ and `internal/console/regioncandidates.go`.
+
+Those specs are still in review themselves. Where spec 1 relies on them,
+check it relies on what they actually say; §9 lists the changes it asks
+of them.
+
+## Focus
+
+1. **One writer.** Can any sequence (create, relocation, termination,
+ a stale edges file, a stale warm copy, a placer that pauses, the
+ console's box dying, a partition from the control bucket) leave two
+ boxes running or writing one host, or a box serving a stale copy?
+2. **The termination fence (§5.9).** Is `terminated` from
+ DescribeInstances sufficient evidence? What about eventual
+ consistency of EC2 state, a box id that is a label not an instance
+ id, a box in another account or region, a forged edges file.
+3. **Files durability (§5.6).** Restore ordering, tombstones,
+ generation scoping, interaction with the moves archive, what a
+ `snapshot` app loses.
+4. **Reconcile and the edges (§5.3, §5.4).** The slow sweep, the stamp
+ rule, legacy files without stamps.
+5. **The K list (§9).** Is anything missing that the claim or moves
+ specs would need to change for multi-box regions?
+6. **Code citations.** Verify every `file:line` cited against the tree.
+
+A mechanism named, bounded and assigned to spec 2, 3 or 4 (§12) is
+complete at this level; don't pull later specs' depth into this one.
+
+## Output
+
+Findings ranked P1 (unsafe or blocks build), P2 (wrong or missing), P3
+(clarity). Each: section, the problem, a concrete failing sequence, and
+a suggested fix. End with a verdict: ready for plan, or not ready.
+
+## Round 6
+
+This is rev 4.2, answering round 5 (`CODEX-FINDINGS-REGION-HA-5.md`). Give
+a disposition for A5-1 and the A4-1, A3-2 and A2-7 residuals, then
+report only new findings that rev 4.2's change to §5.8's release
+sequence introduces, or anything still unsafe. Don't re-raise anything a
+previous round marked resolved unless rev 4.2 broke it.