carlos / platform Public

spec: host lifecycle claim rev 6.4, the moves session's notes on rev 6.3

The stamp is captured at work selection and compared with active_stamp
under the guard; retire-artifacts never moves stamps (only activation and
retire-installation do), so retired_stamps never holds the active stamp;
any non-incarnation child prefix belongs to the host prefix's own location.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 697f0f9f2776c27ba6d41e050771bbcd49f520a4 parent 8faa89a
1 file changed, +38 −13
  • docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md +38 −13

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 852b43783..88525d4b8 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,6 +1,6 @@
# The host lifecycle claim
-Design, 2026-10-03, **rev 6.3**. A small primitive cited by:
+Design, 2026-10-04, **rev 6.4**. A small primitive cited by:
- **#199**, deleting an instance and parking its data:
`2026-10-02-replica-ownership-design.md`, which this spec supersedes
@@ -17,7 +17,11 @@ I-7, adopts its replacement for D4, and answers N1, N3 to N10, N12 and the
carried-forward R3-12. The moves-only findings (N2's move side, N11, N13,
N14, N15) are the moves spec's. §12 maps every finding to its section.
-**Rev 6.3** answers R5-4 from joint round 5 (`CODEX-FINDINGS-JOINT-R5.md`):
+**Rev 6.4** answers the moves session's three notes on rev 6.3 (when
+the stamp is captured, `retired_stamps` versus the active stamp, and
+non-incarnation child prefixes).
+
+**Rev 6.3** answered R5-4 from joint round 5 (`CODEX-FINDINGS-JOINT-R5.md`):
the installation stamp's lifecycle.
**Rev 6.2** answered the claim side of joint round 4
@@ -612,13 +616,16 @@ host it can see in its bucket that has no operation running.
use `retired_incarnations`, which is capped at 32 entries and exists only
to stop an incarnation being reused. It lists `instances/<host>/` and
`moves/<host>/` with delimiter `/`, every page, and refuses on any listing
-error. Each child prefix is either:
+error. **A child prefix that is not an incarnation id (64 hex
+characters) belongs to the host prefix's own location.** That covers
+litestream's level directories and the moves spec's `g-<op id>/`
+generation prefixes alike. So each child prefix is either:
- an **incarnation location**: 64 hex characters. It is residue unless it
is the current `holder.location`;
-- a **legacy level directory** (`0000/` to `0009/`, litestream's level
- layout), sitting directly under `instances/<host>/`. That is the legacy
- location. It is residue unless `holder.location` is exactly
+- **anything else** directly under `instances/<host>/`, such as a level
+ directory (`0000/` to `0009/`) or a `g-<op id>/` generation prefix. All
+ of these are the legacy location. It is residue unless `holder.location` is exactly
`instances/<host>`.
So the sweep lists:
@@ -730,9 +737,18 @@ installation, not to the whole incarnation.
exists, serving included. Every transition that installs a new
generation issues a new stamp. That includes a dirty rollback, which
never keeps its predecessor's stamp.
-- **The writer.** Every host-state writer carries
- `{incarnation, stamp}` for the installation it acts for. It takes them
- from its fresh read under the guard (§6.4).
+- **The writer.** Every host-state writer **captures**
+ `{incarnation, stamp}` from the box's local record **when it selects
+ its work**, which may be long before it writes. Under the guard it
+ compares that captured stamp with `active_stamp`.
+
+ The fresh claim read under the guard is still required (C4: the
+ incarnation, the operation, and the held config and release identity).
+ But the stamp the writer is judged by is the one it captured at
+ selection, never one re-read under the guard. That is what refuses a
+ stale pass, and not just a stale local record. The `fence-stamp`
+ witness shows it: a pass that selected under the first installation,
+ then crossed UK→US→UK before taking the guard, is refused.
- **The local record.** Under the guard, each box keeps a record per
host: `{incarnation, active_stamp | none, retired_stamps}`.
- **Admission.** A writer is admitted only if its incarnation equals the
@@ -756,10 +772,18 @@ installation, not to the whole incarnation.
- **Two different retirements (R5-4).** Local artifacts are tagged in
the inventory (§6.3) with the stamp of the installation that produced
them.
- - **`retire-artifacts(stamp S)`** parks only the artifacts tagged `S`
- and adds `S` to `retired_stamps`. It never touches `active_stamp`.
- A landing that has activated its own stamp uses this to park its
- predecessor's leftovers.
+ - **`retire-artifacts(stamp S)`** parks only the artifacts tagged `S`.
+ **It never changes `active_stamp` or `retired_stamps`.** A landing
+ that has activated its own stamp uses it to park its predecessor's
+ leftovers. A dirty rollback uses it to park the pre-move database,
+ even while `S` is still active.
+ - **Only two things move stamps:**
+ - **activation**, which moves the old `active_stamp` (if any) into
+ `retired_stamps` and sets the new one;
+ - **`retire-installation`**.
+
+ So `retired_stamps` never contains `active_stamp`, and "equal to
+ `active_stamp`" and "not in `retired_stamps`" can never disagree.
- **`retire-installation`** (§6.3, local park at delete or a move away)
moves `active_stamp` into `retired_stamps`, sets it to `none`, and
parks every artifact.
@@ -1023,6 +1047,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.6 notes | §6.4 stamp captured at selection; only activation and retire-installation move stamps; §6.2a non-incarnation children |
## 13. S3 behaviour this relies on, verified