spec: host lifecycle claim rev 6.11, the moves spec's rev 7.11 notes
holder.admissions records unfinished/uncovered admissions across op transitions; PublishGeneration covers the chain and queues retirement of every predecessor (replaces QueueGenerationRetire); unfinished chains; clean rollback only with src_covered; sealed baseline only from_db; a new agent stops a running app; adoption sets writer_box.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+62
−4
docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md+62 −4
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 2bda2e6de..148f7adf3 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,10 +1,11 @@ |
| # The host lifecycle claim |
| -Design, 2026-10-05, **rev 6.10**. Joint rounds 6 and 7 judged the claim ready for primitive planning. Rev |
| +Design, 2026-10-05, **rev 6.11**. 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 answered the moves session's notes on §6.4a. Rev 6.8 rewrote §6.4a |
| around writer sessions, for joint round 8. Rev 6.10 answers joint round 10 |
| -(R10-1, R10-2, R10-4, R10-5). Rev 6.9 answered joint round 9 |
| +(R10-1, R10-2, R10-4, R10-5). Rev 6.11 answers the moves spec's rev 7.11 |
| +notes. Rev 6.9 answered joint round 9 |
| (R9-1 to R9-4) and takes **Paul's ruling R6 (2026-10-04): a box never |
| reuses its local database. Every writer start restores from the |
| certified remote.** A small primitive cited by: |
| @@ -99,7 +100,9 @@ replaced whole with conditional writes (`If-Match` on the ETag read). |
| "generation": "<op id of the installed generation, or \"\">", |
| "stamp": 41, |
| "session": 57, |
| - "writer_box": "adi-knitting" |
| + "writer_box": "adi-knitting", |
| + "admissions": [{"session": 57, "generation": "g…", "predecessor": "g…", |
| + "mode": "cold", "covered": false}] |
| }, |
| "op": { |
| "kind": "serving", |
| @@ -173,6 +176,13 @@ Field rules: |
| are retired there. |
| - **`holder.session`** is the current writer session's admission `gen` |
| (§6.4a). Every `AdmitWriter` CAS moves it forward. |
| +- **`holder.admissions`** is the record of writer admissions whose chain |
| + is not yet finished, or whose predecessors are not yet queued for |
| + retirement (rev 7.11 notes 3 and 4). It lives in the holder, so it |
| + survives every operation transition, release and new operation. Each |
| + entry is `{session, generation, predecessor, mode, covered, |
| + writes_lost?}`. Entries are trimmed once covered, keeping at most the |
| + last 8. |
| - **`holder.writer_box`** is the box admitted as that session's writer |
| (§6.4a). It lives in the holder, not only in an operation's journal, so |
| it survives an operation being replaced (R9-2). |
| @@ -918,7 +928,8 @@ After a conflicting CAS, the box re-establishes its **evidence** |
| fresh read alone isn't enough. |
| **Chores raised while serving, and the root generation (R10-5).** A chore |
| -queued while the claim is `serving` has `op = "session:<holder.session>"`, |
| +queued while the claim is `serving` (through `PublishGeneration`, rev 7.11 |
| +note 4) has `op = "session:<holder.session>"`, |
| and is owned as usual. An example is retiring a superseded generation |
| once its successor's root is published. An adopted legacy host's |
| generation is the location root itself (level directories directly |
| @@ -1039,6 +1050,53 @@ It records this in its journal entry, and the admitting box raises an |
| alert. `holder.writer_box` makes the box known even when the operation |
| that admitted the crashed writer has since been replaced (R9-2). |
| +#### Readings settled with the moves spec (rev 7.11) |
| + |
| +1. **Retry limit:** five start attempts within one session, with doubling |
| + backoff (1, 2, 4, 8, 16). A start the environment isn't ready for waits |
| + without counting an attempt. At the fifth failure the box marks the |
| + host failed and creates no session until an operator or a health |
| + signal clears it. Confirmed. |
| +2. **A chain of unfinished admissions.** The unfinished state covers a |
| + **run** of admissions, each of which died before its generation's |
| + marker was published. Every generation in the chain, from the marker's |
| + generation through `holder.generation`, is live, and raises no alert. |
| + The baseline is the newest generation in the chain that holds an |
| + object, else the marker's generation. `holder.admissions` is how the |
| + chain is known. |
| +3. **The admissions record survives release** and the next operation, |
| + because it lives in `holder.admissions`, not in an operation's |
| + journal. Writes-lost declarations are kept there too. `op.journal` |
| + keeps no separate writers record. |
| +4. **Uncovered predecessors.** Publishing a generation's marker is |
| + followed by one `PublishGeneration` CAS, `(observedSession, |
| + publishedGeneration, region)`. It marks every admission entry up to |
| + and including `publishedGeneration` as covered, and queues a |
| + `park-generation` chore (op `session:<n>`) for every predecessor |
| + generation in that chain other than `publishedGeneration`, without |
| + duplicates. A writer that dies after its marker landed but before this |
| + CAS leaves entries uncovered. The next admission's `PublishGeneration` |
| + covers them. This replaces `QueueGenerationRetire`. |
| +5. **A clean rollback** returns the source to its own generation **only |
| + when the seal records `src_covered`**: the source's own replica |
| + reached the stopped database's position, with no write pending and the |
| + session's start complete. Otherwise the return carries the seal as a |
| + prepared generation. |
| +6. **`BaselineCoversPredecessor`** may be passed only for a seal built |
| + from the stopped database (`from_db`). A seal built from the remote, |
| + because the disk was gone, stops at the remote's position, and the |
| + writes beyond it are declared in `writes_lost`. |
| +7. **A new agent process stops any app it finds running** for a host, |
| + because that app's session ended with the old agent. It then admits a |
| + new session before restarting the app. It never reattaches to a unit |
| + started under a dead session. |
| +8. **A declared-lost box's timers** are declared on the console's record, |
| + and alerted. A rollback whose target is lost, with `src_covered` |
| + false, records a second `writes_lost` for the source's cut session. |
| + **Adoption** sets `holder.writer_box` to the box running the |
| + pre-release process. Before the first writer of a new incarnation, |
| + `writer_box` is `""`. |
| + |
| #### Readings settled with the moves spec (rev 7.10) |
| These are the rulings on the moves spec's rev 7.10 readings: |