carlos / platform Public

spec: host lifecycle claim rev 6.7, the moves session's notes on writer epochs

closed.json consumed by version at open (failure means cold recovery); the
first wake after create or adoption is cold; the warm DB is the baseline only
when its lineage names the old generation, it passes its integrity check,
and this box was that generation's active writer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev f9df7641d413394ac08b2ef585e777a99faa5974 parent d2e83b3
1 file changed, +34 −3
  • docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md +34 −3

CI passed — run details

diff --git a/docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md b/docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md
index e6d81f41b..722a354e1 100644
--- a/docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md
+++ b/docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md
@@ -1,7 +1,9 @@
# The host lifecycle claim
-Design, 2026-10-04, **rev 6.6**. Joint rounds 6 and 7 judged the claim ready for primitive planning. Rev
-6.5 added the R6-4 rule. Rev 6.6 adds writer epochs (R7-1, amadan #225). A small primitive cited by:
+Design, 2026-10-04, **rev 6.7**. Joint rounds 6 and 7 judged the claim ready for primitive planning. Rev
+6.5 added the R6-4 rule. Rev 6.6 added writer epochs (R7-1, amadan #225).
+Rev 6.7 answers the moves session's three notes on §6.4a: consuming the
+marker, the first wake, and the warm baseline. A small primitive cited by:
- **#199**, deleting an instance and parking its data:
`2026-10-02-replica-ownership-design.md`, which this spec supersedes
@@ -853,6 +855,23 @@ So **two writers whose uploads could overlap never share a generation**.
- its `max_txid` equals the generation's remote maximum TXID;
- its `stamp` is the box's own `active_stamp`.
+ **The marker is consumed when a writer opens it.** The admitted writer
+ deletes `closed.json`, by the exact version it read, before it issues
+ its first upload. If that delete fails, the writer does not continue
+ the generation; it takes the cold-recovery path instead. A writer that
+ continues after a clean close and then crashes with uploads in flight
+ therefore leaves no marker, and the next wake recovers cold. The delete
+ marker this leaves lets the writer's own later clean close write the
+ key again with `If-None-Match`.
+
+ **The first wake after a create or an adoption is a cold recovery.** No
+ writer closed the origin generation. Nobody writes a marker it didn't
+ earn, and an empty generation is not exempted, because a first writer
+ that crashed with `[1,1]` in flight leaves the same state. A new
+ instance's first generation snapshots an empty or near-empty
+ database, so the cost is small. An adoption pays one full snapshot,
+ once.
+
Otherwise the previous writer may still have uploads in flight. That
covers a crash, an out-of-memory kill, lease expiry or takeover, a
shared-pool failover, a lost box, and a missing or unreadable marker.
@@ -863,7 +882,18 @@ So **two writers whose uploads could overlap never share a generation**.
`holder.generation`. The CAS writes a **new `holder.generation`**, a
fresh op id that is never reused, and a **new `holder.stamp`** (the
resulting `gen`). It requires `op.exec` to be this box. The box then:
- 1. restores from the old generation;
+ 1. establishes its **baseline**:
+ - **The warm local database**, if all of these hold:
+ - its lineage marker (`<dbPath>.gen`) names the old generation;
+ - it passes its integrity check;
+ - the box's local stamp record shows **this box was the old
+ generation's active writer**.
+
+ A crash without disk loss leaves that database holding
+ acknowledged writes that were never uploaded, so it is a superset
+ of the remote.
+ - **Otherwise, a restore from the old generation's remote.** Another
+ box may have advanced the remote past this box's copy.
2. activates the new stamp locally (§6.4);
3. replicates **only** into the new generation's prefix.
@@ -1128,6 +1158,7 @@ the model catches it.
| J4-R4-4 | §5.3 step 4 |
| J4-Q2 | §5.1 step 5 |
| J5-R5-4 | §2 `holder.stamp`, §6.4 initialization, refusal with no record, the two retirements |
+| moves 7.8 notes | §6.4a: marker consumed at open, first wake is cold, warm baseline only for the old generation's own writer |
| J7-R7-1 | §6.4a writer epochs: clean close, lost replication state, cold recovery as an installing CAS, generation-bound writers |
| J6-R6-4 | §2 `holder.stamp` invariant: any CAS that changes `op.exec` writes `holder.stamp` |
| moves 7.6 notes | §6.4 stamp captured at selection; only activation and retire-installation move stamps; §6.2a non-incarnation children |