carlos / platform Public

spec: move-any-app rev 7.12: joint round 11, holder.admissions and PublishGeneration (claim rev 6.12), every number rerun (#175)

Answers CODEX-FINDINGS-JOINT-R11 (R11-1 to R11-5, the R10-3 leftovers,
R10-6's final oracle, the probe retry deadline) against claim rev 6.12
(b202ea4e, with rev 6.11's answers) and the library E at 34224a29.
holder.admissions replaces op.journal.writers; the predecessor is the
last record (INV-16); Coverage "" | sealed | clean-return replaces
BaselineCoversPredecessor, with clean-return speaking for the target's
probe session and the source's cut session only; PublishGeneration is
the one retirement path, bound to op and phase, legal in every operation
a writer runs in, with per-region coverage; the sweep reads an absent
marker as the origin; the final oracle runs the recovery admission for
real; a probe attempt's five restarts share its 30 s window and a probe
never marks the host failed; §5.1, §7.8 and the authoritative-region
table assign holder.generation only at a cold admission's CAS or the
clean return.

Results on model af9b89ed: 30,000 and 100,000 seeds clean; 96 rules, 83
caught alone (64 at 3,000, 10 at 30,000, 2 at 100,000, 7 by witness), 8
combination-only, 2 subsumed, 2 liveness, 1 unreachable; every table
regenerated from the retained verdicts. §22.18 has every disposition;
§19.4 the notes for platform-1e.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev dd3e35f6f2deacaf2bc20737417edfac3e11e787 parent af9b89e
1 file changed, +440 −158
  • docs/superpowers/specs/2026-10-02-move-any-app-design.md +440 −158
diff --git a/docs/superpowers/specs/2026-10-02-move-any-app-design.md b/docs/superpowers/specs/2026-10-02-move-any-app-design.md
index 77079268c..24137b7e0 100644
--- a/docs/superpowers/specs/2026-10-02-move-any-app-design.md
+++ b/docs/superpowers/specs/2026-10-02-move-any-app-design.md
@@ -1,7 +1,45 @@
# Move any app or instance to another region: Phase 1, a safe single-instance move
**Date:** 2026-10-05
-**Revision:** 7.11.
+**Revision:** 7.12.
+
+- **Rev 7.12** answers **joint round 11** (`CODEX-FINDINGS-JOINT-R11.md`,
+ cited "R11-n") and is written against **claim spec rev 6.12**
+ (b202ea4e, which answers rev 7.11's eight notes and R11-2 to R11-5)
+ and the library E at 34224a29; §22.18 has every disposition.
+ **`holder.admissions`** replaces `op.journal.writers`: the record of
+ admissions lives in the holder, so it survives every operation,
+ release and new operation, trimmed to eight covered records and never
+ an uncovered one or the current predecessor. **An admission's
+ predecessor is always the last record there** (session, box,
+ generation), never the generation an operation chose for a restore
+ (R11-4): a clean return resets `holder.generation` to the source's
+ for the restore, but the predecessor is still the target's writer
+ (INV-16). **`Coverage`** `""` | `sealed` | `clean-return` replaces
+ `BaselineCoversPredecessor`: only `""` with no certificate records
+ `writes_lost`, and the record always names its coverage; a clean
+ rollback with `src_covered` declares nothing. **`PublishGeneration`**
+ replaces `QueueGenerationRetire`: the one retirement path, bound to
+ the observed operation and phase, legal while serving and inside any
+ operation a writer runs in (R11-5), chores with `op = op.id` inside an
+ operation and `session:<n>` while serving, only of predecessors in
+ `holder.admissions`; `""` and `"@root"` are one origin, so nothing
+ retires an adopted host's replica before a cold admission has
+ published a successor (R11-2). **The sweep reads an absent
+ `generation.json` as the origin** (R11-1), as the residue oracle does,
+ so an unfinished admission's chain protects an adopted host's replica;
+ witness `wOriginSwept`. **The final oracle runs the recovery
+ admission for real** when the serving session is uncertified and
+ judges by what it declared; an admission that cannot run is counted as
+ an unverified prospective declaration, never exempted (R10-6). **A
+ probe attempt's five app restarts share its 30 s readiness window**
+ (§7.7): the fifth failure or the window ends the attempt and the
+ operation counts one of its three budgeted attempts; a probe never
+ marks the host failed. §5.1, §7.8 and the authoritative-region table
+ carry no instruction left that assigns `holder.generation` outside a
+ cold admission's CAS or the clean return (R10-3). Rule
+ `clean-return-identity` (96 in all); witnesses `wCleanReturnIdentity`
+ and `wOriginSwept` (59 in all). Results in §14.2.3 and §14.2.5.
- **Rev 7.11** answers **joint round 10** (`CODEX-FINDINGS-JOINT-R10.md`,
cited "R10-n") and is written against **claim spec rev 6.10**
@@ -791,8 +829,11 @@ is `0000/0000000000000008-0000000000000008.ltx`. Rev 7.5 wrote
one in this spec and in the model.
The claim names the current one, **`holder.generation`** (CC18): written
-by the commit's claim CAS (§7.9), by a push's probe CAS (F7), and by a
-dirty rollback's source probe (§7.8). Restore reads it from the same fresh
+only by a cold admission's `AdmitWriter` CAS (a landing's, a push's or a
+dirty rollback's probe into its prepared generation, every recovery into
+a fresh one, §7.14) and by a clean rollback's return CAS, which names the
+source's generation again for the restore (§7.8; R10-3: no commit,
+`probed` or install phase writes it). Restore reads it from the same fresh
admission read as `holder.location` (claim C3a).
**The restore contract (J2-R2-1; R3-1; R4-1).** A restore reads
@@ -1028,32 +1069,43 @@ fails there first (§14.2.6).
nothing writes while a placement runs. After a conflict the box
re-establishes its evidence, the certificate, the exec handover,
rather than re-reading alone. It writes `holder.session = its
- resulting gen`, `holder.writer_box = this box`, and a journal entry
- in `op.journal.writers` `{session, box, generation, stamp, mode,
- baseline, predecessor: {session, box, generation, stamp},
- writes_lost?}`, the predecessor copied from the claim it observed. It
- **never replaces the operation**: kind, id, phase, participants,
- obligations and the rest of the journal are kept; and the release of
- an operation to `serving` carries the writers journal over, so an
- admission whose start is unfinished at the release stays explained
- (below).
+ resulting gen`, `holder.writer_box = this box`, and a record in
+ **`holder.admissions`** `{session, box, generation, predecessor:
+ {session, box, generation, stamp}, mode, coverage, covered,
+ writes_lost?}` (claim rev 6.12; the library's `AdmissionRecord`).
+ **The predecessor is the last record there**, with its own session,
+ box and generation; it never comes from the holder's fields, which a
+ clean return has reset to the source's generation for the restore
+ while the predecessor is still the target's writer (R11-4; rev 7.11
+ journalled the target's session and box with the source's
+ generation, a writer that never was; INV-16). `holder.admissions`
+ lives in the holder, so it survives every operation transition,
+ release and new operation; it is trimmed to the last eight covered
+ records, never an uncovered one or the current predecessor. The
+ admission **never replaces the operation**: kind, id, phase,
+ participants, obligations and the rest of the journal are kept.
- **Failed starts are governed by a retry policy, never by another
admission** (R10-1). Within the admitted session the agent retries
the app start with a doubling backoff from one step (1, 2, 4, 8, 16
steps in the model; seconds in production) up to **five attempts**;
a start the environment is not ready for (config not rendered, the
- release not live) waits and counts no attempt. At the fifth failure
- the box marks the host **failed**, abandons the session's start, and
- creates no new session for the host until an operator clears it (or
- a health signal does; the model's operator clears it after half a
- horizon). An operation whose probe is the failed host rolls back
- ("target would not start") or counts one failed try. Five attempts
- because the start's own faults (a missing key, a bad bundle) do not
- heal within the window and a crash loop would otherwise churn
- generations; the backoff keeps five attempts within half a minute.
- An app's writes are never left in an interval without an admitted
- session: there is no app before the CAS, and the session stands until
- the next CAS.
+ release not live) waits and counts no attempt. For a **serving
+ wake**, at the fifth failure the box marks the host **failed**,
+ abandons the session's start, and creates no new session for the
+ host until an operator clears it (or a health signal does; the
+ model's operator clears it after half a horizon). For a **probe**,
+ the restarts share the probe attempt's 30 s readiness window (§7.7):
+ the fifth failure or the window's end, whichever comes first, ends
+ the attempt, the operation counts one of its budgeted attempts, and
+ the host is not marked failed. Five attempts because the start's own
+ faults (a missing key, a bad bundle) do not heal within the window
+ and a crash loop would otherwise churn generations. The waits
+ between attempts total 15 s (1 + 2 + 4 + 8); each attempt's own
+ start and readiness time is on top, so five attempts are not a
+ bound on a serving wake's duration, only on its count. An app's
+ writes are never left in an interval without an admitted session:
+ there is no app before the CAS, and the session stands until the
+ next CAS.
- **A box never reuses its local database (R9-1).** Before it starts,
every admitted writer purges the local database with an
error-returning purge; if the purge fails the writer does not start
@@ -1101,14 +1153,25 @@ fails there first (§14.2.6).
uploads are gone with its database. When the baseline is a **seal
that covers the stopped predecessor** (a landing's, a push's, a
return's prepared generation, built from the stopped database's
- every page), there is nothing to declare and the entry says
- `baseline: sealed` (`BaselineCoversPredecessor`, claim rev 6.9.1);
- the comparison is against the seal's own position, never a TXID from
- another region. A seal built from the **remote** because the disk
- was gone (`seal.from_db` false, §7.4) stops at the remote's
- position and covers nothing beyond it: the prepared generation's
- admission records `writes_lost` for the predecessor's acknowledged
- writes past it, as a cold admission from the remote would. The box is never inferred from `op.exec`. A write the
+ every page), there is nothing to declare: the admission's
+ **`Coverage`** is `sealed` (claim rev 6.12, replacing rev 6.9.1's
+ `BaselineCoversPredecessor`); the comparison is against the seal's
+ own position, never a TXID from another region. A clean rollback's
+ return with `src_covered` (§7.8) is covered too, `clean-return`: the
+ unchanged target and the source's complete replica establish
+ preservation, and the source's re-admission declares nothing. The
+ coverage speaks for the **target's probe session** and for the
+ **source's cut session** (`cut.session`, journalled at the stop)
+ only: a later session of the recovered source that dies uncertified
+ is declared like any other, and a return made clean only by a
+ declared-lost target is not covered at all. Only
+ coverage `""` with no certificate records `writes_lost`, and the
+ record always names its coverage, certified or not. A seal built
+ from the **remote** because the disk was gone (`seal.from_db` false,
+ §7.4) stops at the remote's position and covers nothing beyond it:
+ the prepared generation's admission has coverage `""` and records
+ `writes_lost` for the predecessor's acknowledged writes past it, as
+ a cold admission from the remote would. The box is never inferred from `op.exec`. A write the
host's remote holds, in any generation, is never declared lost while
its writer's box is with us (INV-15): the lineage adopts the
generation that holds it, a dirty return's lane, instead; a box
@@ -1138,25 +1201,47 @@ fails there first (§14.2.6).
queued the chore at the CAS, so a writer that died before its first
upload could have its only baseline archived under it). The chores
that retire superseded generations are queued by the **marker's
- publication**, one per dead generation (`QueueGenerationRetire` in
- the library): the predecessor; behind a lagging marker, every empty
- generation of the chain of unfinished admissions between the marker's
- generation and the new one, and the marker's; and the predecessor of
- any earlier cold admission of this operation whose journal entry
- shows no chore was queued (its writer died after its marker landed
- and before the chore CAS; the journal marks entries whose
- predecessor is covered). A chore queued while the claim is `serving`
- has `op = "session:<holder.session>"`; an adopted legacy host's
- generation is the location root itself, named by the sentinel
- **`"@root"`** so a chore can name it, `holder.generation` is `""`
- for such a host until its first cold admission, and the adoption
- writes `holder.writer_box` as the box running the pre-release
- process, so the first cold admission's `writes_lost` names the
- writer whose unuploaded writes it leaves behind (R10-5). A failed
+ publication**, through one **`PublishGeneration(observedOpID,
+ observedPhase, observedSession, publishedGeneration, region,
+ newID)`** CAS (claim rev 6.12, replacing `QueueGenerationRetire`):
+ bound to the observed operation and phase like the admission, legal
+ while serving and inside any operation a writer runs in (a restarted
+ landing probe, a rollback's or a revert's source; R11-5), it marks
+ every admission record up to the published generation covered and
+ queues one `park-generation` per dead generation, deduplicated: the
+ predecessor; behind a lagging marker, every generation of the chain
+ of unfinished admissions between the marker's generation and the new
+ one, and the marker's; and the predecessor of any earlier cold
+ admission in `holder.admissions` not yet covered (its writer died
+ after its marker landed and before the CAS). Its chores carry `op =
+ op.id` inside an operation and `op = "session:<holder.session>"`
+ while serving. **Retirement happens only through it, and only of
+ predecessors recorded in `holder.admissions`** (R11-2). An adopted
+ legacy host's generation is the location root itself, named by the
+ sentinel **`"@root"`** so a chore can name it; `""` and `"@root"`
+ are one origin, so nothing retires the active legacy replica before
+ a cold admission has created a successor and published it;
+ `holder.generation` is `""` for such a host until its first cold
+ admission, and the adoption writes `holder.writer_box` as the box
+ running the pre-release process, so the first cold admission's
+ `writes_lost` names the writer whose unuploaded writes it leaves
+ behind (R10-5, R11-3). **Coverage is per region**: a record is
+ covered when its predecessor's chore was queued in the region that
+ holds the predecessor's objects (or the predecessor holds none
+ anywhere); a predecessor whose objects live in another region (a
+ move's source generation, seen by the target's publication whose
+ chain walks back through it) stays uncovered for that region's next
+ `PublishGeneration`, since a chore queued from the target's region
+ would park nothing there and one queued into the source's region
+ would park a generation the rollback may still need. A dead
+ generation holding nothing yet still gets its chore in the publishing
+ region: a dead writer's late upload or certificate may land in it
+ within the chore's horizon. A failed
cold start leaves an empty, unpublished generation; the next
attempt is cold again and the marker it publishes retires it.
- - **A marker that lags `holder.generation`** is read through the
- writers journal: when it names the predecessor of the latest
+ - **A marker that lags `holder.generation`** (an absent marker is the
+ origin `""`, for the sweep as for the restore, R11-1) is read through
+ `holder.admissions`: when it names the predecessor of the latest
admission, or the predecessor of a chain of admissions each of which
died before its marker (two in a row happen: the second's purge
failed after its CAS), that is the normal unfinished state, every
@@ -1330,21 +1415,25 @@ is the region of the holder's current installation:
|---|---|
| `serving`, `pushing` | `op.exec`'s region |
| `moving` (before the flip), `reverting` | the source's region |
-| `landing` (after the flip, before the commit) | the source's region: `holder.generation` is still the pre-move generation, and the target's new generation is not yet named |
-| `landing` after the commit, until the claim releases | the target's region |
-| `restoring`, clean | the source's region |
-| `restoring`, dirty, until the source's probe names the return generation | the source's region |
-| `restoring`, dirty, after the source's probe | the source's region, for the return generation |
+| `landing` after the flip, before the target's probe is admitted | the source's region: `holder.generation` is still the pre-move generation, and the target's prepared generation is not yet named |
+| `landing` from the target's probe's cold admission on, committed or not | the target's region: `holder.generation` is the generation that admission chose, the prepared one or, for a restarted probe, a fresh one restored from it (§7.14; rev 7.11's row said "before the commit", R10-3) |
+| `restoring`, clean, from the return CAS on | the source's region: the return CAS named the source's generation again for the restore, and the source's re-admission moves to a fresh generation there |
+| `restoring`, dirty, until the source's probe is admitted | the source's region, for the pre-move generation; the return generation is built there but not yet named |
+| `restoring`, dirty, from the source's probe's cold admission on | the source's region, for the return generation |
| `creating`, `deleting`, `parking`, `purging`, free | none: nothing is live |
**The start check (INV-4, J2-R2-8).** Before every spawn (`Start`, `Seed`,
`ProbeWake`), the activator requires:
1. the box's own `<location>generation.json` (absent is origin) to name
- **the generation the claim expects**: `holder.generation` for an
- ordinary wake, or, for a probe, the generation the probing operation is
- installing (the move id, the rollback id, the push id); and its
- incarnation to be the holder's;
+ **the generation the claim expects**: `holder.generation`, as the
+ admission's CAS left it, for every start; a probe's first admission
+ publishes the operation's prepared generation (the move id, the
+ rollback id, the push id) and a restarted probe's a fresh generation
+ restored from it (§7.14; rev 7.11's clause named the prepared
+ generation for every probe, R10-3); a lagging marker is read through
+ `holder.admissions` (§5.1 step 9); and its incarnation to be the
+ holder's;
2. `.files-gen`, when the files directory exists, to name the same
generation and incarnation;
3. `<dbPath>.gen` to name the same generation and location. A warm
@@ -2078,7 +2167,18 @@ only while the claim names this box as execution holder:
otherwise) answers 200 to 399 within 30 s (`backend_exec.go:36`);
- a 20 s settle, the process still running, and a second request;
- up to three attempts, and never more than T11 admitted for this
- budget (§7.3, R3-7).
+ budget (§7.3, R3-7). **One attempt is one cold admission** (§7.14): its
+ app may be restarted under the retry policy of §5.1 step 9 within the
+ attempt's **30 s readiness window**, which runs from the first start
+ (the waits total 15 s, each start's own time is on top), and the fifth
+ failure or the window's end, whichever comes first, ends the attempt;
+ the next attempt, if the budget allows one, is a new cold admission
+ into a fresh generation restored from the dead attempt's. A probe never
+ marks the host failed; the operation's rollback (or `stuck`) is its
+ outcome. The budget's three attempts and the policy's five restarts are
+ different things: at most three admissions, each with at most five
+ starts inside 30 s. The absolute `cut_deadline` (§7.4) still bounds the
+ whole.
The probe's activator entry is **held**: `RetireExcept`
(`internal/edge/edge.go:924`, `activator.go:2624`) keeps it, and the edge
@@ -2119,10 +2219,10 @@ because, until then, a source failure might need the target's state again.
| phase | action | replay |
|---|---|---|
| `waiting` | until `released` (clean) or `returned` (dirty) and the claim's execution holder is `none` | |
-| `claimed` | CAS the claim: `op.kind = restoring`, execution holder = this box, citing the target's evidence (§19 K4), **and `holder.stamp = op.source_stamp`**, the source installation's own stamp the flip journaled (claim rev 6.5: a CAS that makes an existing installation current again writes that installation's stamp; R6-4). The source's fresh read then matches its record, or re-initializes a lost one, to `S` | |
+| `claimed` | CAS the claim: `op.kind = restoring`, execution holder = this box, citing the target's evidence (§19 K4), **and `holder.stamp = op.source_stamp`**, the source installation's own stamp the flip journaled (claim rev 6.5: a CAS that makes an existing installation current again writes that installation's stamp; R6-4); **clean, with `src_covered`: `holder.generation = op.journal.src_gen`**, the source's generation again, for the restore. The predecessor of the source's re-admission is still the target's writer, the last record of `holder.admissions` (claim rev 6.12, R11-4), and its coverage is `clean-return`: nothing is declared. The source's fresh read then matches its record, or re-initializes a lost one, to `S` | |
| `restoring` | row `restoring`, `hold_op = rollback id` | replayable |
| clean: `verified` | files and timers digests equal its `stopped` digests (a mismatch is `stuck`, INV-4); its warm database's `<dbPath>.gen` equals its pre-move generation | replayable |
-| dirty: `parking`, `building`, `published`, `local`, `configured`, `restored` | the target's install phases of §7.6, on the source, from `moves/<host>/<rollback id>/` (`building` restores the returned snapshot, requires `N'`, and writes the rollback generation's snapshot and anchor), with destination `superseded/<rollback id>/<host>/` for what it supersedes, **with two differences: `configured` and the release materialization run on the inputs the source renders now, recorded as `recovery.inputs`, and are never gated on `move.inputs`** (§7.7, J2-R2-5); and the stamps: the install runs under the source's pre-move installation `S`, which the `claimed` CAS wrote back into `holder.stamp` and which stays active; `local` runs `retire-artifacts(S)` on the pre-move database, tagged `S`, which moves no stamp (a leftover tagged with a **retired** stamp, left by a cold admission that issued its stamp and then failed its purge, is parked too, rev 7.11); the return generation's database and files are tagged `S` as they are installed; the `probed` CAS below, which names the return generation in `holder.generation`, writes the **new `holder.stamp` `R`** in the same write, and the source's fresh read under the guard activates `R` before the open, tagging the return generation's artifacts `R` and retiring `S` then (claim rev 6.5 §6.4: a dirty rollback installs a new generation and never keeps its predecessor's stamp, R5-4, R6-4; rev 7.5's model kept it, rev 7.6's activated the target's). Rev 7.3 said "exactly" and so inherited the landing's `configured` gate: a bundle published after admission, a target that wrote, and a dirty rollback would then have failed before the recovery probe (R2-5). The model's `recovery-current-inputs` witness is that case (§14.2.5) | as §7.6 |
+| dirty: `parking`, `building`, `published`, `local`, `configured`, `restored` | the target's install phases of §7.6, on the source, from `moves/<host>/<rollback id>/` (`building` restores the returned snapshot, requires `N'`, and writes the rollback generation's snapshot and anchor), with destination `superseded/<rollback id>/<host>/` for what it supersedes, **with two differences: `configured` and the release materialization run on the inputs the source renders now, recorded as `recovery.inputs`, and are never gated on `move.inputs`** (§7.7, J2-R2-5); and the stamps: the install runs under the source's pre-move installation `S`, which the `claimed` CAS wrote back into `holder.stamp` and which stays active; `local` runs `retire-artifacts(S)` on the pre-move database, tagged `S`, which moves no stamp (a leftover tagged with a **retired** stamp, left by a cold admission that issued its stamp and then failed its purge, is parked too, rev 7.11); the return generation's database and files are tagged `S` as they are installed; **the probe's cold admission** (§7.14), which names the return generation in `holder.generation`, issues the **new `holder.stamp` `R`** in the same write (`KeepStamp` false: a writer was admitted since `S` was issued), and the source's fresh read under the guard activates `R` before the open, tagging the return generation's artifacts `R` and retiring `S` then (claim rev 6.5 §6.4: a dirty rollback installs a new generation and never keeps its predecessor's stamp, R5-4, R6-4; rev 7.5's model kept it, rev 7.6's activated the target's; rev 7.11's row still said the `probed` CAS wrote them, R10-3). Rev 7.3 said "exactly" and so inherited the landing's `configured` gate: a bundle published after admission, a target that wrote, and a dirty rollback would then have failed before the recovery probe (R2-5). The model's `recovery-current-inputs` witness is that case (§14.2.5) | as §7.6 |
| `probing` | the probe, an `AdmitWriter` (§7.14): dirty, cold into the return generation from its pinned seal (`baseline: sealed`, no `writes_lost`); clean, warm or cold into the source's own generation, which the return CAS named again | **never replays an earlier phase**: once its recovery process has started, its own new writes are authoritative (INV-2, INV-7); a probe that dies before its session opened replication, or in its settle, is restarted, a new admission |
| `probed` | the phase CAS alone: **`holder.generation` and `holder.stamp` moved at the probe's cold admission** (§7.14; a dirty return's generation and its new stamp, claim rev 6.5 §2 and 6.9 §6.4a), and the `probed` CAS writes neither (R10-3; rev 7.10's row still named the return generation here). Dirty: the return lane's `park-staging` chore is queued now | |
| `recovered` | CAS `rollback.recovered_at` | |
@@ -2369,9 +2469,13 @@ rollback's return generation) is built by the operation's install phases
and becomes `holder.generation` at its probe's cold admission, never
before; the flip and the commit move no generation (rev 7.9's commit did).
A clean rollback's **return CAS names the source's generation again**
-(`op.journal.src_gen`, recorded at the flip), since the target's probe had
-moved `holder.generation` to the target's and the target wrote nothing;
-the source's probe then restores from its own region's remote of it.
+(`op.journal.src_gen`, recorded at the flip; only with `src_covered`,
+§7.8), since the target's probe had moved `holder.generation` to the
+target's and the target wrote nothing; the source's probe then restores
+from its own region's remote of it, is covered `clean-return`, and
+journals the **target's writer** as its predecessor, the last record of
+`holder.admissions`, never the holder's reset fields (claim rev 6.12,
+R11-4, INV-16).
**The admitted writer's start**, on its box, in this order; it is the
agent's own loop around one claim CAS, not a set of claim transitions,
@@ -2379,13 +2483,13 @@ and a new agent process never resumes it (a new agent is a new session):
| step | action | if it fails |
|---|---|---|
-| decide | read the claim; `op.exec` must be this box and the kind one that admits; the certificate for `holder.session` decides warm or cold; a cold admission's generation is the operation's prepared one if `holder.generation` is not it or a descendant of it, else a fresh id; `KeepStamp` when `holder.stamp > holder.session`; a lagging `generation.json` is read through the writers journal (below) | nothing happened |
-| **`AdmitWriter`** | the CAS of §5.1 step 9, **first**: session, writer_box, journal entry; cold: generation, stamp unless kept, `writes_lost` for an uncertified predecessor the baseline does not cover (`baseline: sealed` otherwise); **no chore**: the predecessor is the unfinished generation's baseline until the marker names the new one (R10-2); the carried files are retagged with the new stamp here | a conflict: re-establish the evidence and decide again |
+| decide | read the claim; `op.exec` must be this box and the kind one that admits; the certificate for `holder.session` decides warm or cold; a cold admission's generation is the operation's prepared one if `holder.generation` is not it or a descendant of it, else a fresh id; `KeepStamp` when `holder.stamp > holder.session`; `Coverage` `sealed` for a prepared generation from a `from_db` seal, `clean-return` for a clean rollback's return with `src_covered`, else `""`; a lagging `generation.json` is read through `holder.admissions` (below) | nothing happened |
+| **`AdmitWriter`** | the CAS of §5.1 step 9, **first**: session, writer_box, the `holder.admissions` record with the last record as its predecessor; cold: generation, stamp unless kept, `writes_lost` only for coverage `""` with no certificate; **no chore**: the predecessor is the unfinished generation's baseline until the marker names the new one (R10-2); the carried files are retagged with the new stamp here | a conflict: re-establish the evidence and decide again |
| purge | delete the local database, with an error-returning purge | the start waits and purges again; the session stands |
| restore | warm: `holder.generation` from this region's remote, to at least the certificate's `max_txid`; cold, prepared: the prepared generation from its pinned snapshot and anchor (the operation's build journal); cold, fresh: the baseline from this region's remote, the predecessor or, behind a lagging marker, the nearest generation of the chain that holds an object | the start waits; a warm restore short of `max_txid` is an alert, the remote is incomplete |
| start, readiness | the app starts on the restored database and answers its readiness path; nothing it acknowledges is outside the session | the retry policy (§5.1 step 9): a doubling backoff from one step, five attempts, then the host is marked failed, the start abandoned, and no session is created until an operator clears it |
| first upload (cold, fresh, a non-empty baseline) | the full file `[1, 1]` of the restored database, captured once and acknowledged to the client; the generation has a root; it is in the session's ledger (R10-7) | retried with the same bytes after the client's wait, whether the original timed out or completed unseen; the session is uncertain for good |
-| marker (cold) | `generation.json` names the new generation: the pinned snapshot identity for a prepared one, `snapshot_txid = 0` for a fresh one (its root is `[1, 1]`); never before the root exists (INV-11). **Then the retire chores**: one `park-generation` per dead generation, the predecessor and the chain's (§5.1 step 9) | retried after the timeout; the writer waits |
+| marker (cold) | `generation.json` names the new generation: the pinned snapshot identity for a prepared one, `snapshot_txid = 0` for a fresh one (its root is `[1, 1]`); never before the root exists (INV-11). **Then `PublishGeneration`** (§5.1 step 9), bound to the operation and phase it observed, legal in `serving` and in every operation a writer runs in: the records up to the new generation are covered and one `park-generation` per dead generation is queued, the predecessor's, the chain's and any uncovered record's | retried after the timeout; the writer waits |
| anchor (warm, when the restored position is above the level-0 maximum) | `[N, N]`, acknowledged to the client; in the ledger (R10-7) | retried with the same bytes; the session is uncertain for good |
| open | replication opens; the replica reads its remote position at its first sync; every later upload is the session's. An app stopped idle before this point is not closed: the replicator opens, ships what the app wrote, then closes cleanly | |
@@ -2393,7 +2497,7 @@ An admitted writer that dies between its CAS and its marker leaves
`holder.generation` naming an **unfinished** generation `generation.json`
does not (R10-2): its journalled predecessor is the live baseline, no
chore retires it and the sweep protects it. The next admission, by this
-box or another `op.exec` box, reads the lag through the writers journal
+box or another `op.exec` box, reads the lag through `holder.admissions`
(§5.1 step 9): the marker names the latest admission's predecessor, or
the predecessor of a chain of unfinished admissions, so this is the
normal state and no alert; a `holder.generation` that holds objects (the
@@ -2406,13 +2510,12 @@ not explain is unexplained missing data: the start is refused and the
box alerts. A clean rollback's return leaves the marker naming a
descendant of `holder.generation`; the source publishes the source
generation's marker again from its last version before anything else.
-An operation's release to `serving` carries the writers journal over, so
-an admission unfinished at the release (an abort released over a source
-admitted a tick earlier) stays explained. A marker that lands after its
-writer died, before the writer queued the chores, leaves the predecessor
-unretired: the next admission's marker stage retires the predecessor of
-every earlier cold admission of the operation whose entry is not marked
-covered. A pre-flip round never forces a sync on a session whose start is
+`holder.admissions` lives in the holder, so an admission unfinished at a
+release (an abort released over a source admitted a tick earlier) stays
+explained through the next operation. A marker that lands after its
+writer died, before the writer's `PublishGeneration`, leaves the
+predecessor unretired: the next admission's `PublishGeneration` retires
+the predecessor of every record not yet covered. A pre-flip round never forces a sync on a session whose start is
unfinished: there is no open replicator, and a forced upload would write
the first upload's key with other bytes.
@@ -2684,6 +2787,16 @@ combination-only, unexercised), each with its reason. The sweep exits
nonzero on any ERROR, any unexpected MISSED, and any expected miss that is
now caught (STALE).
+**Rev 7.12: the final oracle runs the recovery.** When the run is
+quiescent with the serving host at rest after a session that did not
+certify, the final oracle no longer exempts the acknowledged, unuploaded
+writes as a prospective declaration (R10-6: that recorded and alerted
+nothing, with `writes-lost` off too). It wakes the host, runs the cold
+admission for real, drives its chores to quiescence, and judges the
+database by what the admission declared; a recovery that cannot run
+within the bound is counted (`final: unverified prospective
+declaration`) and the local check is skipped for it, never exempted.
+
**Rev 7.11: the rare-at-depth outcome.** `expected-outcomes.txt` may
list a rule as `rare <N>`: it has no witness of its own and the random
sweep reaches it only at N seeds or more; below N its miss is reported as
@@ -3267,6 +3380,74 @@ readiness, and same-operation lease identities.
review's 3 GiB workload is reproduced (108.68 s with three passes at one
rate, 124.04 s with the fourth) and refused by rev 7.7's arithmetic.
+**Rev 7.12: joint round 11 and claim rev 6.12.**
+
+- **`holder.admissions` (claim rev 6.12).** `holder.Admissions
+ []admissionRecord{Session, Box, Gen, Predecessor, Mode, Coverage,
+ Covered, Lost, LostSrc}` replaces `op.Writers`; the release and the
+ move's and push's start carry nothing. `lastAdmission(holder)` is the
+ next admission's predecessor; `admitCommit` journals it (session, box,
+ generation) and INV-16 refuses a record whose predecessor is not the
+ last admitted writer. `PublishGeneration` trims covered records beyond
+ the last eight; an uncovered record and the newest are never trimmed.
+- **Coverage (R11-4).** `admitInput.Coverage` `""` | `"sealed"` (a
+ prepared generation from a `from_db` seal) | `"clean-return"` (a
+ rollback with `DirtyKnown && !Dirty && SrcCovered`, the source
+ re-admitted into its own generation, and no declared-lost target);
+ `writes_lost` only for `""` without a certificate. Rule
+ `clean-return-identity` (the mutation takes the predecessor from the
+ holder's fields and gives the clean return no coverage); witness
+ `wCleanReturnIdentity`: a probed target that wrote nothing, a clean
+ rollback, the source's re-admission journals the target's writer and
+ declares nothing; under the mutation INV-16. `dirty-return`'s named
+ failure is INV-2 local at the final recovery: treated as clean with the
+ source's replica covering the stop, the return is covered and declares
+ nothing, and the target's write is gone from the serving database.
+- **`PublishGeneration` (R11-5).** `publishGeneration(b, c, observedOpID,
+ observedPhase, session, published, region, newID, dead)` replaces
+ `queueGenerationRetire`: bound to the observed `op.id` and phase like
+ the admission, legal in serving and in every operation kind, its
+ chores carry `op = op.id` inside an operation and `session:<n>` while
+ serving; the marker stage and the lag path's republish call it;
+ `uncovered` reads `holder.admissions`.
+- **The absent marker is the origin (R11-1).** `deadGeneration` reads a
+ missing `generation.json` as `""` before testing the chain, as
+ `residueOf` always did; witness `wOriginSwept` (under `baseline-live`):
+ an adopted host's origin replica, a cold admission that crashes before
+ its first upload, the ordinary sweep for three horizons with no wake,
+ then the recovery; under the mutation the sweep parks the origin and
+ the recovery restores nothing (INV-2 local).
+- **The final oracle runs the recovery (R10-6).** `final()` wakes an
+ at-rest, uncertified serving host, drives the cold admission and its
+ chores to quiescence, then judges; `final: recovery admission run` and
+ `final: unverified prospective declaration` count the cases. It found
+ a false coverage at once: a return made clean by a declared-lost target
+ was covered `clean-return` and the target's write went undeclared
+ (the `lost-return-park` witness under no mutation).
+- **A probe attempt's window (§7.7).** `openState.startedAt`,
+ `probeStartWindow = 30`: in a probe, the fifth failed start or the
+ window's end abandons the attempt (`probeAttemptFailed` counts one
+ budgeted try: a landing rolls back at three, a revert or a rollback's
+ source is stuck at nine), the environment wait included; a probe never
+ marks the host failed. `recovery-current-inputs`'s witness reaches
+ `stuck` through this path now.
+- **Adoption names the writer (R11-3).** Unchanged since rev 7.11
+ (`WriterBox: eb.ID` at `adopt`).
+- **Model faults found and fixed this round** (all before the final
+ numbers; the 100,000-seed baseline found them): a `clean-return`
+ coverage applied to a later session of the recovered source, whose
+ uncertified death then went undeclared (seed 95491: the coverage speaks
+ for the target's probe session and the source's cut session only,
+ `op.CutSession`); `PublishGeneration` queued a dead generation's chore
+ in the publishing region alone, so a move's source generation covered
+ by the target's publication was never parked in the source's region
+ (seeds 33646 and 40148: coverage is per region, and a chore is queued
+ only where the generation holds objects; a first fix that queued chores
+ into the other regions parked the source's own generation under a
+ rollback, seeds 1036 and 1296 / 3,000, and was withdrawn; an empty dead
+ generation still gets its chore, since a dead writer's late upload or
+ certificate may land in it, seeds 15273 and 20810 / 30,000).
+
**Rev 7.11: joint round 10 and claim rev 6.10.**
- **The admitting CAS first (R10-1, claim rev 6.10).** `spawn` decides
@@ -3761,6 +3942,38 @@ adds and one it makes stricter:
app is idle. Writes past the last completed checkpoint are lost by
design and declared so; every durable write must come back.
+**Rev 7.12, on the final model (claim rev 6.12: `holder.admissions`,
+`Coverage`, `PublishGeneration`, the origin's absent marker, the final
+recovery admission, a probe attempt's window): 30,000 seeds, zero
+violations; 100,000 seeds, zero violations** (673 s and 2231 s).
+Across the 100,000 seeds: 150,033 completed operations, among them
+71,784 cold and 16,875 warm admissions (13,689
+covered `sealed`, 919 covered `clean-return`;
+20,049 clean closes, 1,568 closes refused as
+uncertain, 0 stale certificates, 1,063 wakes
+that waited for a draining writer, 56,566 local databases
+purged, 4,443 starts that waited for a failed purge,
+57,206 writes_lost records declaring 8,884 acknowledged
+writes lost, 29,236 full first uploads, 108,295 start
+steps that waited for their marker, 663 markers published
+again, 3,883 probes restarted, 541 probe
+attempts ended by their window or fifth failure, 2,324 app
+starts that failed and were retried within their session,
+0 hosts marked failed by the retry policy (a probe no longer marks one, and no serving wake failed five times in these seeds),
+111 seals whose source replica was short and
+51 returns that carried the seal; 9,326 final
+recovery admissions run by the oracle, 0 unverified),
+825 completed moves, 2,199 clean and
+101 dirty rollbacks, 356 pre-flip reverts,
+287 declared losses, 25,894 pushes, 89,204
+delete-park-free cycles and 4,945 lost disks (3,672
+with a crash); 9,418 LTX compactions, 6,608 snapshot
+rotations, 564 level-0 upload retries, 30,446
+anchors; 26,101 local stamp records lost and re-initialized;
+49,321 requests completed after `H`; 33,312 staging
+signatures refused as stale; 30,514 creates restarted on a
+412. Every oracle left the system unchanged.
+
**Rev 7.11, on the final model (claim rev 6.10: the admitting CAS before
the app start, a session per agent process, the retry policy, unfinished
generations with live baselines, the library's admission shape,
@@ -4039,37 +4252,56 @@ Each was a failing seed first, then a rule; each rule's mutation is in
#### 14.2.5 Mutation results
Every rule was dropped in turn, with the one prebuilt binary of §14.2.1,
-on the final rev 7.11 model (bd1587a1), with the strict classification,
+on the final rev 7.12 model (af9b89ed), with the strict classification,
**in two ways**: the **random sweep**, 3,000 seeds each, 30,000 for every
rule not caught at 3,000 and for the new and the rare ones, 100,000 for
the rarest, 30,000 for each combination and 100,000 for the rarest; and
the rule's **witness scenarios** (§14.2.2, `witness_test.go`) under the
-same mutation, for the 48 rules that have them. A rule is caught
+same mutation, for the 49 rules that have them. A rule is caught
if either catches it; `mutate.sh` reports the two separately, and this
-section does too. The model has **95 rules**: rev 7.10's 92 plus
-`admit-before-start` (R10-1), `baseline-live` (R10-2) and `seal-return`
-(rev 7.11 §7.8). `mutate.sh 3000` exited 0: no ERROR, no unexpected
+section does too. The model has **96 rules**: rev 7.11's 95 plus
+`clean-return-identity` (claim rev 6.12, R11-4). `mutate.sh 3000` exited 0: no ERROR, no unexpected
MISSED, no STALE; every live combination was rerun this round. Seed
numbers reproduce any sweep line with `HOSTLIFE_SEED`;
-`HOSTLIFE_WITNESS=<rule>` replays a witness with its trace. Rev 7.10's
-counts are in the rev 7.10 spec (33ce0a9c); the admitting CAS before the
-start and the retry policy change what every start does, so sweep counts
-moved throughout. **Every table below is regenerated from the retained
-verdict files** (R9-6; `~/.cache/nearest-region/rev711-sweeps/`), none is
-carried over.
+`HOSTLIFE_WITNESS=<rule>` replays a witness with its trace. Rev 7.11's
+counts are in the rev 7.11 spec (ec982436). **Every table below is
+regenerated from the retained verdict files** (R9-6;
+`~/.cache/nearest-region/rev712-sweeps/`), none is carried over.
| | rules |
|---|---|
-| caught alone by the sweep at 3,000 seeds | 65 |
-| caught alone by the sweep at 30,000 (and by their witness, where one exists) | 8 (`evidence-whole-tree`, `hostguard`, `markers-last`, `orphan-order`, `restore-overlap`, `seal-return`, `stale-hold-release`, `strict-spawn`) |
-| caught alone by the sweep at 100,000 (and by its witness, where one exists) | 3 (`baseline-live`, `declare-lost-compute`, `newest-l0`) |
-| caught alone by their witness only; the sweep misses them at 30,000 | 6 (`admit-before-start`, `close-evidence`, `close-waits`, `closed-marker`, `remote-baseline`, `restore-gap-closed`) |
+| caught alone by the sweep at 3,000 seeds | 64 |
+| caught alone by the sweep at 30,000 (and by their witness, where one exists) | 10 (`dirty-return`, `evidence-whole-tree`, `hostguard`, `lost-return-park`, `markers-last`, `orphan-order`, `restore-overlap`, `seal-return`, `stale-hold-release`, `strict-spawn`) |
+| caught alone by the sweep at 100,000 (and by its witness, where one exists) | 2 (`baseline-live`, `declare-lost-compute`) |
+| caught alone by their witness only; the sweep misses them at 30,000 | 7 (`admit-before-start`, `close-evidence`, `close-waits`, `closed-marker`, `newest-l0`, `remote-baseline`, `restore-gap-closed`) |
| caught only in a stated combination: the witness holds alone and under every proper subset, and violates with the partners | 8 |
| subsumed: the witness holds under every combination tried, or the scenario is unreachable by construction | 2 (`door-reread`, `door-by-version`, by C3a and by writer epochs; historical results only, below). `start-check`, subsumed in rev 7.10, is caught alone by the sweep again since rev 7.11: with the whole check gone the lagging-marker reading is skipped and an empty generation is restored as if it held the data |
| liveness only | 2 (`readiness-key`, `config-before-probe`) |
| unreachable under claim rev 5 | 1 (`readiness-quiet`) |
| unexercised | **0** |
+**What rev 7.12 moved.** The new rule `clean-return-identity`
+13 / 3,000, 125 / 30,000, 387 / 100,000 (a clean rollback after a probed target is a
+schedule the sweep reaches; under the mutation the false predecessor is
+INV-16 at the source's re-admission). The final oracle's real recovery
+and the probe window moved a few counts: `dirty-return`
+0 / 3,000, 11 / 30,000, `lost-return-park` 0 / 3,000, 29 / 30,000, 74 / 100,000,
+`writes-lost` 14 / 3,000, 125 / 30,000, 411 / 100,000, `baseline-live` 0 / 3,000, 0 / 30,000, 2 / 100,000,
+`seal-return` 0 / 3,000, 12 / 30,000, 27 / 100,000, `recovery-current-inputs`
+40 / 3,000, `hostguard` 0 / 3,000, 2 / 30,000, 2 / 100,000,
+`stale-hold-release` 0 / 3,000, 14 / 30,000, 47 / 100,000, `strict-spawn`
+0 / 3,000, 1 / 30,000, 11 / 100,000; `dirty-return` and `lost-return-park`
+now need 30,000 seeds (the final oracle's recovery declares what the
+hypothetical declaration used to exempt, and the serving database is
+judged by it), and `newest-l0` fell back to witness-only (0 / 100,000;
+1 / 100,000 on rev 7.11). The witness-only rules keep their shape:
+`admit-before-start` witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000, `remote-baseline`
+witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000, `close-evidence` witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000,
+`closed-marker` witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000, `close-waits` witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000,
+`restore-gap-closed` witness; sweep 0 / 3,000, 0 / 30,000; the pair `admit-bind-op`
++ `claim-cas-opid` 0 / 30,000, 0 / 100,000; the admission
+four 183 / 30,000, 644 / 100,000.
+
**What rev 7.11 moved.** The three new rules: `admit-before-start` is
witness-only (sweep 0 / 3,000, 0 / 30,000, 0 / 100,000: a background
acknowledgement in the few ticks between the start and readiness, then a
@@ -4205,16 +4437,16 @@ witness to hold there; each witness violates with the failure it names.
| rule | the scenario | witness alone | witness with partners | sweep alone |
|---|---|---|---|---|
-| `generation-conditional` (model 29) | push p1's first `generation.json` PUT is accepted and its response lost; the agent publishes again and p1 completes; push p2 completes; the stale PUT lands | **violated**: the marker names p1, the claim p2, and the serving box cannot start | | 2 / 3,000, 12 / 30,000, 52 / 100,000 |
-| `lost-return-park` (model 27) | the target writes in the settle window, the settle check fails, the target is stopped after its first return PUT and declared lost | **violated**: INV-10, the lane in the source region at the release | | 1 / 3,000, 30 / 30,000, 77 / 100,000 |
+| `generation-conditional` (model 29) | push p1's first `generation.json` PUT is accepted and its response lost; the agent publishes again and p1 completes; push p2 completes; the stale PUT lands | **violated**: the marker names p1, the claim p2, and the serving box cannot start | | 1 / 3,000, 10 / 30,000, 42 / 100,000 |
+| `lost-return-park` (model 27) | the target writes in the settle window, the settle check fails, the target is stopped after its first return PUT and declared lost | **violated**: INV-10, the lane in the source region at the release | | 0 / 3,000, 29 / 30,000, 74 / 100,000 |
| `declare-lost-compute` (model 5) | the target is frozen in its settle window and its execution lease expires; the VM resumes once the source has recovered | **violated**: INV-1, two boxes run the host | | 0 / 3,000, 0 / 30,000, 1 / 100,000 |
| `watchdog-independent` (§7.1) | as above, with the agent alone paused, so the application keeps running | held | with `declare-lost-compute`: **violated**, INV-1 | 0 / 3,000 |
-| `lost-quarantine` (CC12) | the target is stopped while landing, declared lost, and started again with its old disk | **violated**: INV-10, local state for a host served elsewhere | | 1 / 3,000, 5 / 30,000 |
+| `lost-quarantine` (CC12) | the target is stopped while landing, declared lost, and started again with its old disk | **violated**: INV-10, local state for a host served elsewhere | | 1 / 3,000, 6 / 30,000 |
| `markers-last` (R2-6) | the source has a registered timer; the target's agent crashes between extracting the files and writing the marker | **violated**: INV-2, the timer is lost | | 0 / 3,000, 5 / 30,000 |
| `rollback-journal` (R2-3) | a dirty rollback; the source's agent crashes after its probe spawned the instance, which wrote and replicated into the return generation | **violated**: INV-2 on cold restore | | 1 / 3,000, 9 / 30,000 |
| `seal-by-version` (J-N2) | a pre-cut staging round completes after the seal; the source wrote and replicated between them | **violated**: INV-2 on cold restore; the landing installs the stale snapshot | | 1 / 3,000, 6 / 30,000 |
| `staging-quiet` (J-N2) | a staging round completes after the landing's staging park acknowledged, before the release | **violated**: INV-10 at the release | | 1 / 3,000, 2 / 30,000 |
-| `dirty-return` (INV-2) | the target writes during its probe and is rolled back | **violated**: INV-2, the write is lost | | 1 / 3,000, 25 / 30,000 |
+| `dirty-return` (INV-2) | the target writes during its probe and replicates; the rollback is dirty and the return lane carries the write | **violated**: treated as clean with the source's replica covering the stop, the return is covered `clean-return`, nothing is declared and the serving database lacks the target's write (INV-2 local at the final recovery; rev 7.11 saw INV-15 at the declaration) | | 0 / 3,000, 11 / 30,000 |
| `commit-before-open` (INV-5; R3-5) | a public request reaches the target's edge while its probe runs | **violated**: INV-5 | | 2 / 3,000, 61 / 30,000 |
| `claim-cas-opid` (C2) | a stalled source goroutine with the rollback's last read resumes after a purge claimed the host | held | with `revalidate-before-effect`: **violated**, the store is torn down under a serving host | 0 / 3,000 |
| `exec-admission`, `hold-op-open`, `start-check-claim-gen`, `exec-writer` (J2-R2-8; claim rev 6.8.1) | a paused open from an earlier operation lands after the commit while the source's row is still held; a request wakes the source | held, each, and under every proper subset | all four: **violated**, INV-1 (the non-exec source is admitted cold into a fresh generation restored from its own region's old files and serves beside the target) | 0 / 3,000 |
@@ -4222,37 +4454,39 @@ witness to hold there; each witness violates with the failure it names.
| `strict-spawn` (J-D3) | the source runs a main process and a descendant placed as its parent was; the move cuts | held | with `evidence-whole-tree`: **violated**, INV-1 | 0 / 3,000, 1 / 30,000, 11 / 100,000 |
| `touched-incomplete` (J-N5) | a legacy host with a pre-release replica in another region is adopted, then deleted | held | with `legacy-discovery`: **violated**, INV-10 after `free` | 0 / 3,000 |
| `registration-check` (CC21) | the first create of a host registers and its console pauses; a purge of the app drains the expired registration, tears the store down and finishes; the creator resumes | held | with `fence-etag`: **violated**; with `purge-claim-fence`: **violated** | 0 / 3,000 |
-| `fence-by-installation` (claim rev 6.4 §6.4, R3-3) | UK→US, then US→UK; **unmutated, the instance must serve on UK again, running** | **violated**: the landing probe on UK is refused by the box's own installation record (INV-3) | | 336 / 3,000, 3,071 / 30,000 |
-| `fence-stamp` (claim rev 6.4 §6.4, R4-2) | a config-sync pass selects the row under the first installation and pauses; UK→US→UK; a new bundle is published; the pass takes the guard | held: the host guard's fresh re-validation refuses its stale bundle | with `hostguard`: **violated**, INV-6, a pass of a retired installation wrote host state | 334 / 3,000, 3,017 / 30,000 |
+| `fence-by-installation` (claim rev 6.4 §6.4, R3-3) | UK→US, then US→UK; **unmutated, the instance must serve on UK again, running** | **violated**: the landing probe on UK is refused by the box's own installation record (INV-3) | | 342 / 3,000, 3,133 / 30,000 |
+| `fence-stamp` (claim rev 6.4 §6.4, R4-2) | a config-sync pass selects the row under the first installation and pauses; UK→US→UK; a new bundle is published; the pass takes the guard | held: the host guard's fresh re-validation refuses its stale bundle | with `hostguard`: **violated**, INV-6, a pass of a retired installation wrote host state | 337 / 3,000, 3,042 / 30,000 |
| `orphan-order` (claim rev 6 §5.1 step 5, R3-2) | the recovery pass's cleanup pauses after its first observation; a create removes the orphan, claims and publishes; the paused cleanup resumes | **violated**: the record of the incarnation the claim names is deleted | | 0 / 3,000, 1 / 30,000 |
| `sweep-namespace` (claim rev 6 §6.2a, R3-4) | a replication PUT of incarnation 1 completes after 33 recreates dropped it from `retired_incarnations` | **violated**: INV-10, residue the sweep never finds | | 541 / 3,000 |
-| `live-set-region` (claim rev 6.4 §6.2a, R4-3) | a legacy host serving in UK with an earlier replica in US; discovery parks US; an old US replication PUT lands after | **violated**: INV-10, residue the US sweep exempts by key alone | | 2 / 3,000, 13 / 30,000 |
+| `live-set-region` (claim rev 6.4 §6.2a, R4-3) | a legacy host serving in UK with an earlier replica in US; discovery parks US; an old US replication PUT lands after | **violated**: INV-10, residue the US sweep exempts by key alone | | 2 / 3,000, 16 / 30,000 |
| `restore-overlap` (§5.1, R4-1) | a generation's snapshot ends at the push's TXID; the only continuation is a compacted file starting one below it; the disk is lost and the host wakes cold | **violated**: INV-3 since rev 7.10, the restore stops short of the certificate's `max_txid` and the box never starts (rev 7.4's `min == current + 1` discarded the file and lost four writes) | | 0 / 3,000, 2 / 30,000 |
| `restore-gap-closed` (§5.1, R4-1) | the same generation with the next file missing and the one after current | **violated**: a restore across the gap returns a database short of the acknowledged writes | | witness; sweep 0 / 3,000, 0 / 30,000 |
-| `restore-anchor` (§5.1 step 7, R5-1) | a push installs a snapshot alone; the host wakes, writes three times, replicates, loses its disk and wakes cold | **violated**: INV-2, every write since the push is lost: replication restarted at TXID 1 below the snapshot and the planner skipped the files (facts R5-1a, b) | | 58 / 3,000, 590 / 30,000, 1,954 / 100,000 |
-| `root-advance` (§5.1 step 8, R5-3) | a push, then twelve replicated writes: four compactions, four snapshot rotations, retention expiring every file that continued from the pinned snapshot; the disk is lost | **violated**: INV-3, the host refuses to wake on a gap the retention made, while the newest snapshot holds every write (facts R5-3d, e) | | 11 / 3,000, 115 / 30,000, 422 / 100,000 |
-| `anchor-acked` (§5.1 step 7, R6-1) | a push installs a snapshot alone; the install's anchor PUT is held across forty attempted opens, then released; the host writes, replicates, loses its disk and wakes cold | **violated**: the host opened before its anchor was acknowledged; litestream's position would be 0 and the writes below the snapshot are lost on the cold restore (INV-2) | | 13 / 3,000, 103 / 30,000, 358 / 100,000 |
-| `return-stamp` (claim rev 6.5, R6-4) | a dirty rollback; the source's local stamp record is lost after the target's return; the return CAS writes the source installation's stamp back and the source re-initializes from it, installs under it and serves under its probe CAS's new stamp | **violated**: the source activates the target's stamp, issued for another box's installation (INV-6) | | 74 / 3,000, 772 / 30,000, 2,583 / 100,000 |
-| `recovery-generation` (claim rev 6.6 §6.4a, R7-1), three scenarios and a crash | writer A's upload `[N+1]` is held in flight, A dies with its disk, B wakes; (i) B replicates its own `[N+1]`, then A's lands; (ii) A's lands after B's position is initialized and before B's upload, so litestream's loop skips B's file; (iii) A's held write updated K, B durably updates K, A's lands; (iv) a clean stop drains, then the agent crashes before the certificate | **violated** in each: with the rule B recovers into a fresh generation and A's file lands in the dead one; without it B's acknowledged write is lost on the cold restore taken the moment A's file lands (INV-2), or no recovery runs after the crash (iv) | | 9 / 3,000, 98 / 30,000, 361 / 100,000 |
+| `restore-anchor` (§5.1 step 7, R5-1) | a push installs a snapshot alone; the host wakes, writes three times, replicates, loses its disk and wakes cold | **violated**: INV-2, every write since the push is lost: replication restarted at TXID 1 below the snapshot and the planner skipped the files (facts R5-1a, b) | | 59 / 3,000, 593 / 30,000, 1,960 / 100,000 |
+| `root-advance` (§5.1 step 8, R5-3) | a push, then twelve replicated writes: four compactions, four snapshot rotations, retention expiring every file that continued from the pinned snapshot; the disk is lost | **violated**: INV-3, the host refuses to wake on a gap the retention made, while the newest snapshot holds every write (facts R5-3d, e) | | 12 / 3,000, 121 / 30,000, 434 / 100,000 |
+| `anchor-acked` (§5.1 step 7, R6-1) | a push installs a snapshot alone; the install's anchor PUT is held across forty attempted opens, then released; the host writes, replicates, loses its disk and wakes cold | **violated**: the host opened before its anchor was acknowledged; litestream's position would be 0 and the writes below the snapshot are lost on the cold restore (INV-2) | | 13 / 3,000, 104 / 30,000, 361 / 100,000 |
+| `return-stamp` (claim rev 6.5, R6-4) | a dirty rollback; the source's local stamp record is lost after the target's return; the return CAS writes the source installation's stamp back and the source re-initializes from it, installs under it and serves under its probe CAS's new stamp | **violated**: the source activates the target's stamp, issued for another box's installation (INV-6) | | 74 / 3,000, 773 / 30,000, 2,587 / 100,000 |
+| `recovery-generation` (claim rev 6.6 §6.4a, R7-1), three scenarios and a crash | writer A's upload `[N+1]` is held in flight, A dies with its disk, B wakes; (i) B replicates its own `[N+1]`, then A's lands; (ii) A's lands after B's position is initialized and before B's upload, so litestream's loop skips B's file; (iii) A's held write updated K, B durably updates K, A's lands; (iv) a clean stop drains, then the agent crashes before the certificate | **violated** in each: with the rule B recovers into a fresh generation and A's file lands in the dead one; without it B's acknowledged write is lost on the cold restore taken the moment A's file lands (INV-2), or no recovery runs after the crash (iv) | | 10 / 3,000, 105 / 30,000, 388 / 100,000 |
| `closed-marker` (claim rev 6.6 §6.4a; a certificate since rev 7.9) | a stale certificate (`max_txid` behind the remote maximum) beside the dead writer's outstanding upload | **violated**: taken as intact, B continues in place and A's late file replaces B's (INV-2) | | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
| `close-waits` (claim rev 6.6 §6.4a) | a clean stop with an upload in flight | **violated**: written at once, the marker vouches for an upload that has not returned | | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
-| `newest-l0` (§5.1 step 8, R7-3) | the local position runs ahead of the uploads across two compactions and snapshot rotations | **violated**: retention below the previous snapshot removes the newest uploaded level-0 file | | 0 / 3,000, 0 / 30,000, 1 / 100,000 |
-| `build-completion` (§5.1 step 2, §7.6, R7-4) | a push's build with its snapshot, then its anchor, held, the agent crashing in between each | **violated**: `generation.json` published before its snapshot landed (INV-11) | | 699 / 3,000 |
+| `newest-l0` (§5.1 step 8, R7-3) | the local position runs ahead of the uploads across two compactions and snapshot rotations | **violated**: retention below the previous snapshot removes the newest uploaded level-0 file | | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
+| `build-completion` (§5.1 step 2, §7.6, R7-4) | a push's build with its snapshot, then its anchor, held, the agent crashing in between each | **violated**: `generation.json` published before its snapshot landed (INV-11) | | 704 / 3,000 |
| `evidence-whole-tree` (§6.1, J-D3) | an adopted legacy host runs a descendant outside the cgroup; the move cuts | **violated**: evidence blind to the escapee certifies the stop and two boxes run the host (INV-1) | | 0 / 3,000, 7 / 30,000 |
| `timer-freeze` (J-N14) | a registered timer on the source; the move holds the row; the runner's deliveries are refused; a clean rollback | **violated**: the refused deliveries advanced the runner's bookkeeping, the timer digest differs from the stop's, the source is `stuck` | | 2 / 3,000, 21 / 30,000 |
| `recovery-current-inputs` (§7.7, §7.8; R2-5) | a bundle is published after admission; the target writes; the rollback is dirty | **violated**: `stuck` | | 40 / 3,000 |
-| `writer-session` (claim rev 6.8 §6.4a, R8-1) | two sessions certify; the third dies with its disk and an upload in flight; the dead certificates still match the remote maximum | **violated**: the newest certificate readmits the box into the generation and the late upload replaces its file (INV-2) | | 1 / 3,000, 19 / 30,000, 61 / 100,000 |
-| `admit-everywhere` (claim rev 6.8 §6.4a, R8-2), two scenarios | (i) the committed move's target dies with its disk and an upload in flight before finalization; (ii) the landing's probe dies with its disk and an upload in flight in its settle window | **violated** in each: admitted for ordinary wakes alone, the target continues the generation and the late upload replaces its file (INV-2); the restarted probe reuses the install generation and the landing's restore loses its write | | 705 / 3,000, 6,772 / 30,000, 22,881 / 100,000 |
+| `writer-session` (claim rev 6.8 §6.4a, R8-1) | two sessions certify; the third dies with its disk and an upload in flight; the dead certificates still match the remote maximum | **violated**: the newest certificate readmits the box into the generation and the late upload replaces its file (INV-2) | | 2 / 3,000, 22 / 30,000, 63 / 100,000 |
+| `admit-everywhere` (claim rev 6.8 §6.4a, R8-2), two scenarios | (i) the committed move's target dies with its disk and an upload in flight before finalization; (ii) the landing's probe dies with its disk and an upload in flight in its settle window | **violated** in each: admitted for ordinary wakes alone, the target continues the generation and the late upload replaces its file (INV-2); the restarted probe reuses the install generation and the landing's restore loses its write | | 710 / 3,000, 6,840 / 30,000, 23,078 / 100,000 |
| `exec-writer` (claim rev 6.8.1) | the admission scenario above | held alone, and under every proper subset of the four | with the three box-side fences: **violated**, INV-6 | 0 / 3,000, 0 / 30,000 |
-| `valid-ltx` (R8-3) | a create's first wake into an empty generation (no LTX file), then a move of the never-written incarnation, whose seal is at position 0 | **violated**: the install writes `[1, 0]` and `[0, 0]`, which the encoder refuses (INV-12) | | 41 / 3,000, 389 / 30,000 |
+| `valid-ltx` (R8-3) | a create's first wake into an empty generation (no LTX file), then a move of the never-written incarnation, whose seal is at position 0 | **violated**: the install writes `[1, 0]` and `[0, 0]`, which the encoder refuses (INV-12) | | 41 / 3,000, 391 / 30,000 |
| `close-evidence` (claim rev 6.8 §6.4a, R8-5) | an upload is held past the client's timeout; the retry lands; the original stays outstanding; a clean stop | **violated**: the certificate is written while the original is unresolved | | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
| `close-evidence` (R9-5), two more scenarios | (i) a compaction's level-1 PUT is held past the client's timeout, the next pass retries and lands, the original completes afterwards; (ii) a snapshot PUT completes on the server after the client gave up on it | **violated** in each: the certificate is written while a request of the session was retried after a timeout, or its response was lost | | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
| `remote-baseline` (claim rev 6.9 §6.4a, R9-1) | a session closes cleanly through N+1; the box's local database is a cached copy through N; the next wake | **violated**: the stale copy is served without the acknowledged write, and its upload for N+1 is skipped at the remote position (INV-2) | | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
-| `writes-lost` (claim rev 6.9 §6.4a, R9-2) | a writer acknowledges a write and crashes before uploading it; the next wake is cold | **violated**: lost silently, the serving database differs from the acknowledged writes (INV-2); with the rule the admission records writes_lost and alerts | | 11 / 3,000, 122 / 30,000, 395 / 100,000 |
+| `writes-lost` (claim rev 6.9 §6.4a, R9-2) | a writer acknowledges a write and crashes before uploading it; the next wake is cold | **violated**: lost silently, the serving database differs from the acknowledged writes (INV-2); with the rule the admission records writes_lost and alerts | | 14 / 3,000, 125 / 30,000, 411 / 100,000 |
| `admit-bind-op` (claim rev 6.9 §6.4a, R9-4) | a wake's admission closure computed under serving resumes after a delete began that kept session, generation and executor | held: the model's general CAS condition on `op.id` (C2) refuses it too | with `claim-cas-opid`: **violated**, INV-13, a writer admitted into a host being deleted | 0; the pair 0 / 30,000, 0 / 100,000 |
| `admit-before-start` (claim rev 6.10 §6.4a, R10-1) | a background worker acknowledges a write right after the app starts; the box crashes before replication opens; admitted before the start, the acknowledgement is the session's and the next cold admission declares it | **violated**: under rev 6.8.2's order the acknowledgement is in a database the next warm admission purges silently (INV-2 local) | | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
| `baseline-live` (claim rev 6.10 §6.4a, R10-2) | a cold admission into a fresh generation; the box crashes before the first upload; the predecessor's retirement runs out its quiet time; the recovery | **violated**: with the chore at the CAS the predecessor is parked and the recovery restores nothing (INV-2 local) | | 0 / 3,000, 0 / 30,000, 2 / 100,000 |
-| `seal-return` (rev 7.11 §7.8) | the source's last upload is in flight when the cut stops it; the landing is rolled back after its build; the return must carry the seal | **violated**: treated as clean, the source's cold admission declares a write the landing's built generation holds (INV-15) | | 0 / 3,000, 10 / 30,000, 26 / 100,000 |
+| `clean-return-identity` (claim rev 6.12, R11-4) | a move's target is probed and writes nothing; the seal recorded `src_covered`; a clean rollback; the source's re-admission | held: the record's predecessor is the target's writer and its coverage `clean-return`; nothing is declared | **violated** under the mutation: INV-16, the record names the target's session and box with the source's generation, a writer that never was | 13 / 3,000, 125 / 30,000, 387 / 100,000 |
+| `baseline-live` (R11-1), a second scenario | an adopted host's origin replica with durable writes and no `generation.json`; a cold admission crashes before its first upload; the ordinary sweep runs for three horizons; the recovery | **violated**: the sweep parks the origin and the recovery restores nothing (INV-2 local) | | 0 / 3,000, 0 / 30,000, 2 / 100,000 |
+| `seal-return` (rev 7.11 §7.8) | the source's last upload is in flight when the cut stops it; the landing is rolled back after its build; the return must carry the seal | **violated**: treated as clean, the source's cold admission declares a write the landing's built generation holds (INV-15) | | 0 / 3,000, 12 / 30,000, 27 / 100,000 |
| `close-evidence` (R10-7), two more scenarios | (i) a fresh generation's first upload is held past the client's timeout and its retry lands; (ii) a warm admission's anchor is held and its retry lands; then a clean stop | **violated** in each: the certificate is written while a request of the session was retried after a timeout | | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
**The purge fence, the ETag condition and C5a.** `purge-claim-fence`
@@ -4277,53 +4511,54 @@ combination** (R4 §3): each door rule's two-rule pair with C3a already
fails, so the three-rule row is a wider set and inherits no claim that its
proper subsets hold. It is no longer run.
-**Caught alone: 82 of 95** (65 by the sweep at 3,000; 8 by the sweep at
-30,000, marked †; 3 at 100,000,
-marked ††; 6 by their witness alone, marked ‡).
+**Caught alone: 83 of 96** (64 by the sweep at 3,000; 10 by the sweep at
+30,000, marked †; 2 at 100,000,
+marked ††; 7 by their witness alone, marked ‡).
| rule | seeds failing | | rule | seeds failing |
|---|---|---|---|---|
-| `abort-target-owner` | 939 / 3,000 | | `admission-registration` | 32 / 3,000 |
-| `admit-before-start` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 | | `admit-everywhere` | 705 / 3,000, 6,772 / 30,000, 22,881 / 100,000 |
-| `anchor-acked` | 13 / 3,000, 103 / 30,000, 358 / 100,000 | | `baseline-live` †† | 0 / 3,000, 0 / 30,000, 2 / 100,000 |
-| `build-completion` | 699 / 3,000 | | `cancelled-creates` | 383 / 3,000 |
-| `claim-never-deleted` | 4 / 3,000, 57 / 30,000 | | `claim-op-exclusive` | 81 / 3,000 |
-| `close-evidence` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 | | `close-waits` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
-| `closed-marker` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 | | `commit-before-open` | 2 / 3,000, 61 / 30,000 |
-| `cut-deadline` | 38 / 3,000 | | `declare-lost-compute` †† | 0 / 3,000, 0 / 30,000, 1 / 100,000 |
-| `dirty-return` | 1 / 3,000, 25 / 30,000 | | `evidence-from-state` | 2,610 / 3,000 |
-| `evidence-whole-tree` † | 0 / 3,000, 7 / 30,000 | | `fence-by-installation` | 336 / 3,000, 3,071 / 30,000 |
-| `fence-etag` | 26 / 3,000, 229 / 30,000 | | `fence-stamp` | 334 / 3,000, 3,017 / 30,000 |
-| `files-carried` | 33 / 3,000 | | `floor-boot-recovery` | 2,576 / 3,000 |
-| `fresh-admission` | 10 / 3,000 | | `fresh-incarnation` | 41 / 3,000 |
-| `generation-conditional` | 2 / 3,000, 12 / 30,000, 52 / 100,000 | | `hostguard` † | 0 / 3,000, 2 / 30,000, 2 / 100,000 |
-| `legacy-discovery` | 276 / 3,000, 2,738 / 30,000 | | `live-set-region` | 2 / 3,000, 13 / 30,000 |
-| `location-per-incarnation` | 28 / 3,000, 360 / 30,000, 1,179 / 100,000 | | `lost-quarantine` | 1 / 3,000, 5 / 30,000 |
-| `lost-return-park` | 1 / 3,000, 30 / 30,000, 77 / 100,000 | | `markers-last` † | 0 / 3,000, 5 / 30,000 |
-| `newest-l0` †† | 0 / 3,000, 0 / 30,000, 1 / 100,000 | | `obligations-block-ops` | 32 / 3,000 |
-| `orphan-no-deadline` | 41 / 3,000 | | `orphan-order` † | 0 / 3,000, 1 / 30,000 |
-| `park-all-versions` | 567 / 3,000 | | `park-by-version` | 2,527 / 3,000 |
-| `park-skip-lock` | 2,728 / 3,000 | | `participant-rows` | 2 / 3,000 |
-| `purge-adopts` | 7 / 3,000 | | `purge-claim-fence` | 22 / 3,000, 232 / 30,000 |
-| `purge-journal` | 1,889 / 3,000 | | `purge-reserve-first` | 2,145 / 3,000 |
-| `quiet-before-ack` | 179 / 3,000 | | `recovery-current-inputs` | 40 / 3,000 |
-| `recovery-generation` | 9 / 3,000, 98 / 30,000, 361 / 100,000 | | `recovery-pass` | 2,482 / 3,000 |
-| `registration-recovery` | 2,116 / 3,000 | | `remote-baseline` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
-| `restore-anchor` | 58 / 3,000, 590 / 30,000, 1,954 / 100,000 | | `restore-by-generation` | 133 / 3,000 |
-| `restore-gap-closed` ‡ | witness; sweep 0 / 3,000, 0 / 30,000 | | `restore-overlap` † | 0 / 3,000, 2 / 30,000 |
-| `retirement-ids` | 482 / 3,000 | | `return-stamp` | 74 / 3,000, 772 / 30,000, 2,583 / 100,000 |
-| `revalidate-before-effect` | 18 / 3,000, 188 / 30,000 | | `revert-journal` | 12 / 3,000 |
-| `rollback-journal` | 1 / 3,000, 9 / 30,000 | | `root-advance` | 11 / 3,000, 115 / 30,000, 422 / 100,000 |
-| `sdk-no-resign` | 10 / 3,000 | | `seal-by-version` | 1 / 3,000, 6 / 30,000 |
-| `seal-return` † | 0 / 3,000, 10 / 30,000, 26 / 100,000 | | `sign-at-check` | 11 / 3,000 |
-| `sign-before-safeuntil` | 17 / 3,000 | | `source-readiness` | 10 / 3,000 |
-| `staging-quiet` | 1 / 3,000, 2 / 30,000 | | `stale-hold-release` † | 0 / 3,000, 15 / 30,000, 46 / 100,000 |
-| `start-check` | 13 / 3,000, 181 / 30,000 | | `start-check-claim-gen` | 12 / 3,000, 140 / 30,000 |
-| `straggler-sweep` | 774 / 3,000 | | `strict-spawn` † | 0 / 3,000, 1 / 30,000, 11 / 100,000 |
-| `sweep-namespace` | 541 / 3,000 | | `sweep-staging` | 34 / 3,000 |
-| `target-park` | 25 / 3,000 | | `timer-canonical` | 3 / 3,000 |
-| `timer-freeze` | 2 / 3,000, 21 / 30,000 | | `valid-ltx` | 41 / 3,000, 389 / 30,000 |
-| `writer-session` | 1 / 3,000, 19 / 30,000, 61 / 100,000 | | `writes-lost` | 11 / 3,000, 122 / 30,000, 395 / 100,000 |
+| `abort-target-owner` | 940 / 3,000 | | `admission-registration` | 32 / 3,000 |
+| `admit-before-start` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 | | `admit-everywhere` | 710 / 3,000, 6,840 / 30,000, 23,078 / 100,000 |
+| `anchor-acked` | 13 / 3,000, 104 / 30,000, 361 / 100,000 | | `baseline-live` †† | 0 / 3,000, 0 / 30,000, 2 / 100,000 |
+| `build-completion` | 704 / 3,000 | | `cancelled-creates` | 383 / 3,000 |
+| `claim-never-deleted` | 4 / 3,000, 57 / 30,000 | | `claim-op-exclusive` | 82 / 3,000 |
+| `clean-return-identity` | 13 / 3,000, 125 / 30,000, 387 / 100,000 | | `close-evidence` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
+| `close-waits` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 | | `closed-marker` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
+| `commit-before-open` | 2 / 3,000, 61 / 30,000 | | `cut-deadline` | 38 / 3,000 |
+| `declare-lost-compute` †† | 0 / 3,000, 0 / 30,000, 1 / 100,000 | | `dirty-return` † | 0 / 3,000, 11 / 30,000 |
+| `evidence-from-state` | 2,610 / 3,000 | | `evidence-whole-tree` † | 0 / 3,000, 7 / 30,000 |
+| `fence-by-installation` | 342 / 3,000, 3,133 / 30,000 | | `fence-etag` | 26 / 3,000, 229 / 30,000 |
+| `fence-stamp` | 337 / 3,000, 3,042 / 30,000 | | `files-carried` | 33 / 3,000 |
+| `floor-boot-recovery` | 2,576 / 3,000 | | `fresh-admission` | 10 / 3,000 |
+| `fresh-incarnation` | 42 / 3,000 | | `generation-conditional` | 1 / 3,000, 10 / 30,000, 42 / 100,000 |
+| `hostguard` † | 0 / 3,000, 2 / 30,000, 2 / 100,000 | | `legacy-discovery` | 273 / 3,000, 2,739 / 30,000 |
+| `live-set-region` | 2 / 3,000, 16 / 30,000 | | `location-per-incarnation` | 28 / 3,000, 359 / 30,000, 1,182 / 100,000 |
+| `lost-quarantine` | 1 / 3,000, 6 / 30,000 | | `lost-return-park` † | 0 / 3,000, 29 / 30,000, 74 / 100,000 |
+| `markers-last` † | 0 / 3,000, 5 / 30,000 | | `newest-l0` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 |
+| `obligations-block-ops` | 31 / 3,000 | | `orphan-no-deadline` | 41 / 3,000 |
+| `orphan-order` † | 0 / 3,000, 1 / 30,000 | | `park-all-versions` | 568 / 3,000 |
+| `park-by-version` | 2,527 / 3,000 | | `park-skip-lock` | 2,728 / 3,000 |
+| `participant-rows` | 2 / 3,000 | | `purge-adopts` | 7 / 3,000 |
+| `purge-claim-fence` | 22 / 3,000, 232 / 30,000 | | `purge-journal` | 1,889 / 3,000 |
+| `purge-reserve-first` | 2,143 / 3,000 | | `quiet-before-ack` | 178 / 3,000 |
+| `recovery-current-inputs` | 40 / 3,000 | | `recovery-generation` | 10 / 3,000, 105 / 30,000, 388 / 100,000 |
+| `recovery-pass` | 2,482 / 3,000 | | `registration-recovery` | 2,118 / 3,000 |
+| `remote-baseline` ‡ | witness; sweep 0 / 3,000, 0 / 30,000, 0 / 100,000 | | `restore-anchor` | 59 / 3,000, 593 / 30,000, 1,960 / 100,000 |
+| `restore-by-generation` | 136 / 3,000 | | `restore-gap-closed` ‡ | witness; sweep 0 / 3,000, 0 / 30,000 |
+| `restore-overlap` † | 0 / 3,000, 2 / 30,000 | | `retirement-ids` | 463 / 3,000 |
+| `return-stamp` | 74 / 3,000, 773 / 30,000, 2,587 / 100,000 | | `revalidate-before-effect` | 17 / 3,000, 188 / 30,000 |
+| `revert-journal` | 12 / 3,000 | | `rollback-journal` | 1 / 3,000, 9 / 30,000 |
+| `root-advance` | 12 / 3,000, 121 / 30,000, 434 / 100,000 | | `sdk-no-resign` | 9 / 3,000 |
+| `seal-by-version` | 1 / 3,000, 6 / 30,000 | | `seal-return` † | 0 / 3,000, 12 / 30,000, 27 / 100,000 |
+| `sign-at-check` | 10 / 3,000 | | `sign-before-safeuntil` | 17 / 3,000 |
+| `source-readiness` | 10 / 3,000 | | `staging-quiet` | 1 / 3,000, 2 / 30,000 |
+| `stale-hold-release` † | 0 / 3,000, 14 / 30,000, 47 / 100,000 | | `start-check` | 16 / 3,000, 218 / 30,000 |
+| `start-check-claim-gen` | 15 / 3,000, 181 / 30,000 | | `straggler-sweep` | 774 / 3,000 |
+| `strict-spawn` † | 0 / 3,000, 1 / 30,000, 11 / 100,000 | | `sweep-namespace` | 541 / 3,000 |
+| `sweep-staging` | 34 / 3,000 | | `target-park` | 18 / 3,000 |
+| `timer-canonical` | 3 / 3,000 | | `timer-freeze` | 2 / 3,000, 21 / 30,000 |
+| `valid-ltx` | 41 / 3,000, 391 / 30,000 | | `writer-session` | 2 / 3,000, 22 / 30,000, 63 / 100,000 |
+| `writes-lost` | 14 / 3,000, 125 / 30,000, 411 / 100,000 | | | |
**Caught only in a combination: 9 rules**, every live combination rerun this
round; `admit-bind-op` joins with `claim-cas-opid` (R9-4); the `start-check`
@@ -4341,16 +4576,16 @@ subset in the gate.
| `purge-claim-fence` + `fence-etag` (**the re-read alone**, rev 7's CC21 as proposed) | 340 / 30,000 | `purge-claim-fence` 22 / 3,000, 232 / 30,000, `fence-etag` 26 / 3,000, 229 / 30,000 | (the two `registration-check` rows below) | a store destroyed under a creating or serving host |
| `registration-check` + `purge-claim-fence` | 269 / 30,000 | `registration-check` 0 / 3,000, `purge-claim-fence` 22 / 3,000, 232 / 30,000 | violated | the same |
| `registration-check` + `fence-etag` | 270 / 30,000 | `registration-check` 0 / 3,000, `fence-etag` 26 / 3,000, 229 / 30,000 | violated | the same |
-| `exec-admission` + `hold-op-open` + `start-check-claim-gen` + `exec-writer` | 143 / 30,000, 503 / 100,000 | `exec-admission` 0 / 3,000, `hold-op-open` 0 / 3,000, `start-check-claim-gen` 12 / 3,000, 140 / 30,000, `exec-writer` 0 / 3,000, 0 / 30,000 | violated, INV-1 | the non-exec source admitted cold beside the target, Astra's J2-R2-8 trace under writer sessions |
+| `exec-admission` + `hold-op-open` + `start-check-claim-gen` + `exec-writer` | 183 / 30,000, 644 / 100,000 | `exec-admission` 0 / 3,000, `hold-op-open` 0 / 3,000, `start-check-claim-gen` 15 / 3,000, 181 / 30,000, `exec-writer` 0 / 3,000, 0 / 30,000 | violated, INV-1 | the non-exec source admitted cold beside the target, Astra's J2-R2-8 trace under writer sessions |
| `exec-admission` + `hold-op-open` + `start-check` + `exec-writer` (**historical**, rev 7.9: 7 / 30,000, violated INV-6) | not rerun: the `start-check` witness is retired, subsumed by regional restores | | retired | the stale source cannot restore the target's generation from its own region |
| `admit-bind-op` + `claim-cas-opid` | 0 / 30,000, 0 / 100,000 | `admit-bind-op` 0 / 3,000, 0 / 30,000, `claim-cas-opid` 0 / 3,000 | violated, INV-13 | a stale serving-time closure admits a writer into a host being deleted |
| `door-reread` + `location-per-incarnation` (**historical**, rev 7.7: 432 / 30,000, 196 door violations, witness violated) | not rerun: the witness is retired and the rule is subsumed | `location-per-incarnation` 28 / 3,000, 360 / 30,000, 1,179 / 100,000 this round (rev 7.10's row said 336 / 30,000 against its own result of 357, R10-9) | retired | under writer epochs the pair adds nothing the partner's own count does not show; no current witness evidence is claimed |
| `door-by-version` + `location-per-incarnation` (**historical**, rev 7.7: 385 / 30,000, 60 door violations, witness violated with C3a alone) | not rerun: the witness is retired and the rule is subsumed | `location-per-incarnation` 28 / 3,000, 360 / 30,000, 1,179 / 100,000 this round | retired | the same |
-| `claim-cas-opid` + `revalidate-before-effect` | 898 / 30,000 | `claim-cas-opid` 0 / 3,000, `revalidate-before-effect` 18 / 3,000, 188 / 30,000 | violated | a stale step destroys a store |
-| `strict-spawn` + `evidence-whole-tree` | 86 / 30,000 | `strict-spawn` 0 / 3,000, 1 / 30,000, 11 / 100,000, `evidence-whole-tree` 0 / 3,000, 7 / 30,000 | violated | two writers |
-| `touched-incomplete` + `legacy-discovery` | 7,292 / 30,000 | `touched-incomplete` 0 / 3,000, `legacy-discovery` 276 / 3,000, 2,738 / 30,000 | violated | a freed host's residue |
+| `claim-cas-opid` + `revalidate-before-effect` | 901 / 30,000 | `claim-cas-opid` 0 / 3,000, `revalidate-before-effect` 17 / 3,000, 188 / 30,000 | violated | a stale step destroys a store |
+| `strict-spawn` + `evidence-whole-tree` | 88 / 30,000 | `strict-spawn` 0 / 3,000, 1 / 30,000, 11 / 100,000, `evidence-whole-tree` 0 / 3,000, 7 / 30,000 | violated | two writers |
+| `touched-incomplete` + `legacy-discovery` | 7,298 / 30,000 | `touched-incomplete` 0 / 3,000, `legacy-discovery` 273 / 3,000, 2,739 / 30,000 | violated | a freed host's residue |
| `declare-lost-compute` + `watchdog-independent` | 0 / 30,000, 2 / 100,000 | `declare-lost-compute` 0 / 3,000, 0 / 30,000, 1 / 100,000, `watchdog-independent` 0 / 3,000 | violated | two writers after a paused or frozen target resumes |
-| `fence-stamp` + `hostguard` (no longer combination-only) | 3,966 / 30,000 | `fence-stamp` 334 / 3,000, 3,017 / 30,000, `hostguard` 0 / 3,000, 2 / 30,000, 2 / 100,000 | violated | a stale pass writes host state for a retired installation (INV-6); the witness is what shows the stamp load-bearing against the guard's own check |
+| `fence-stamp` + `hostguard` (no longer combination-only) | 3,994 / 30,000 | `fence-stamp` 337 / 3,000, 3,042 / 30,000, `hostguard` 0 / 3,000, 2 / 30,000, 2 / 100,000 | violated | a stale pass writes host state for a retired installation (INV-6); the witness is what shows the stamp load-bearing against the guard's own check |
Every live combination was rerun on the rev 7.9 model; the gate runs
every proper subset of the admission four with the witness, which holds
@@ -4770,6 +5005,33 @@ although the seal carries every write; the admitted writer's start
agent loop; and the model's C2 already binds every CAS to `op.id`, so
the `admit-bind-op` witness needs both rules off.
+**Claim rev 6.11 (63255a3c) and 6.12 (b202ea4e), after joint round 11:
+no change requested, three notes.** Rev 6.11 answered rev 7.11's eight
+notes (the retry limit confirmed; the chain generalized to a run of
+admissions; `holder.admissions` in the holder; `PublishGeneration`
+replacing `QueueGenerationRetire`; the clean return only with
+`src_covered`; `BaselineCoversPredecessor` only for a `from_db` seal; a
+new agent stops a running app; the lost box's timers, the source's cut
+session and adoption's `writer_box`). Rev 6.12 answers R11-2 to R11-5:
+retirement only through `PublishGeneration` and only of predecessors in
+`holder.admissions`, `""` and `"@root"` one origin; adoption sets
+`writer_box`; the predecessor is always the last record and admission
+carries `Coverage` `""` | `sealed` | `clean-return`;
+`PublishGeneration(observedOpID, observedPhase, observedSession,
+publishedGeneration, region, newID)` bound to the operation and phase,
+legal in serving and in move kinds. Rev 7.12 encodes all of it (§5.1
+step 9, §7.8, §7.14, §14.2.2). Notes for platform-1e
+(`moves-claim-questions.md`, rev 7.12 heading): **(1)** a return made
+clean only by a declared-lost target is **not** `clean-return`: the
+target may have written and its session is uncovered, so `writes_lost`
+is recorded for it (and the source's cut session when `src_covered` is
+false); **(2)** a probe attempt's app restarts share the attempt's 30 s
+readiness window, the fifth failure or the window ends the attempt, and
+a probe never marks the host failed (the retry policy's failed-host
+marking is a serving wake's); **(3)** when `PublishGeneration` queues
+several chores for one `newID`, the model names the second and later
+ones `<newID>-<generation>`; E's naming is the one to mirror.
+
**Claim rev 6.9.1 and 6.10 (3f916b05), after joint round 10: no change
requested, eight notes.** Rev 6.9.1 answered rev 7.10's seven readings
(confirmed: the ancestor restore from a complete listing, the prepared
@@ -5192,6 +5454,26 @@ answers the rest and reruns every number.
| R6-5 (P3) replayed anchor bytes differ (the encoder's `time.Now()`) | the encoding inputs, timestamp included, are journaled in the install manifest before the PUTs and a replay reuses a current object (§5.1 step 2, §7.6 `building`); `TestFact_R6_5_AnchorReplayBytes` shows identical bytes for identical inputs and different bytes one millisecond apart |
| fidelity: compaction deleted the newest level-0 file, creating anchor-required cold restores the library would not | compaction keeps the newest input (§14.2.2); time-based level-0 retention stays deferred (§14.2.6) |
+### 22.18 Joint round 11 (claim 3f916b05, moves rev 7.11 ec982436, model bd1587a1, library E 090fb7a2)
+
+Round 11 judged the admitting order sound and R10-1, R10-5, R10-7, R10-8
+and R10-9 resolved; it found one P1 and four P2s and kept R10-2, R10-3
+and R10-6 partly open. Claim rev 6.11 answered rev 7.11's notes and rev
+6.12 (b202ea4e) answers R11-2 to R11-5; the library E at 34224a29 gains
+`Holder.Admissions`, `Coverage`, `PublishGeneration` and adoption's
+`writer_box`.
+
+| finding | rev 7.12 |
+|---|---|
+| R11-1 (P1) the model's sweep skipped the chain protection when `generation.json` was absent, so an adopted origin replica could be parked under an unfinished admission | the sweep reads an absent marker as the origin, as the residue oracle does (§5.1 step 9, §6.4); witness `wOriginSwept` (origin, an unfinished admission, three horizons of ordinary sweeps, the recovery) |
+| R10-3 leftovers (B) §5.1 said the commit writes `holder.generation`; the dirty-return row said `probed` writes generation and stamp; the authoritative-region table and the start check were stale | one rewrite: `holder.generation` is written only by a cold admission's CAS and the clean return (§5.1); the dirty install row names the probe's admission; the region table follows the target's or the source's admission; the start check expects the generation the admission chose (§5.1) |
+| R11-4 (P2) a clean return journalled {target session, target box, source generation}, and declared a false loss | the predecessor is the last record of `holder.admissions` (INV-16); `Coverage` `clean-return` for a clean rollback with `src_covered` records nothing; rule `clean-return-identity`, witness `wCleanReturnIdentity` (the identity tuple and the absence of a declaration) |
+| R10-6 (C) the final oracle exempted writes a future admission would declare | the oracle runs the recovery admission for real and judges by what it declared; a recovery that cannot run is an unverified prospective declaration, counted, never exempted (§14.2.1); it found the declared-lost return's false coverage at once |
+| R11-5 (P2) publication-time retirement during operations could not use E's serving-only helper | `PublishGeneration(observedOpID, observedPhase, observedSession, publishedGeneration, region, newID)` bound to the operation and phase, legal in serving and in every operation a writer runs in, chores with `op = op.id` inside an operation (§5.1 step 9, §7.14) |
+| probe retry deadline | one attempt is one cold admission; its five restarts share the 30 s readiness window (the waits total 15 s), the fifth failure or the window ends the attempt and the operation counts one of its three budgeted attempts; a probe never marks the host failed (§5.1 step 9, §7.7) |
+| R11-2, R11-3 (E) | mirrored: retirement only through `PublishGeneration` of predecessors in `holder.admissions`, `""` and `"@root"` one origin; adoption's `writer_box` (already in the model since rev 7.11) |
+| the eight notes judged | all accepted in claim rev 6.11; the aggregate probe deadline defined above |
+
### 22.17 Joint round 10 (claim f6180ae4, moves rev 7.10 33ce0a9c, model 572066ec, library E fdff530f)
Round 10 judged the simplification sound (generation reuse needs a