provident-storeroom 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.guide.md CHANGED
@@ -21,6 +21,18 @@ WAS DRIVEN AGAINST A PUBLISHED TARBALL:** every behavioural claim below is eithe
21
21
  measurement taken on this repository's checkout and named as one. **No `npm install` was run by the pass that
22
22
  wrote this file against the registry, so a registry-installed `0.5.0` is described here and not witnessed.**
23
23
 
24
+ **⟶ AND THE TWO FIGURES THIS GUIDE CANNOT AFFORD TO HAND-WRITE ARE GENERATED AND ASSERTED FROM 2026-10-28 — `DEF-AC` (b), AND THE ASSERTION IS THE DELIVERABLE.** `RCA-8(g)` ANNOTATE-BESIDE: **the paragraph above stands
25
+ BYTE-FOR-BYTE and is read THROUGH this clause.** **THE DEFECT: the version line and the cut-state sentence below
26
+ were written BY HAND, which is how this guide came to deny the release it travels in** — a figure copied by hand
27
+ goes stale the moment the manifest or the tag set moves, and for eight dated paragraphs nothing reddened. **SO
28
+ `scripts/publish.sh` GENERATES BOTH from `bindings/js/package.json`'s `version` and `git tag --list`, and its
29
+ preflight REFUSES when these two lines do not read what it computed** (`scripts/publish.sh --figures` runs that
30
+ one check, read-only). **THE TWO LINES ARE THIS GUIDE'S OPERATIVE FIGURES; every dated paragraph below is the
31
+ reading of its own date and is read through them.**
32
+
33
+ PUBLISH-GUIDE-VERSION-LINE: THE VERSION THIS GUIDE DESCRIBES IS `1.3.0`.
34
+ PUBLISH-GUIDE-CUT-STATE: THE TAGS THIS TREE CARRIES ARE `v1.0.0` · `v1.0.1` · `v1.1.0` · `v1.2.0`; `v1.3.0` DOES NOT EXIST, SO THE RELEASE THIS GUIDE DESCRIBES IS NOT CUT.
35
+
24
36
  **⟶ CORRECTED 2026-10-26 — THE VERSION THIS GUIDE DESCRIBES IS `1.0.0`, NOT `0.5.0`, AND THE SENTENCE ABOVE STANDS
25
37
  BYTE-FOR-BYTE AS THE READING OF THE DAY THIS FILE WAS WRITTEN AND IS READ THROUGH THIS CLAUSE** (`RCA-8(g)`
26
38
  ANNOTATE-BESIDE; `DEF-2026-10-02`: no whole-file rewrite). **`bindings/js/package.json`'s `version` field read at its
@@ -45,6 +57,18 @@ date and reads `1.0.1` from here on.** **AND THE ONE THING NO PASS WITNESSED IS
45
57
  run against the registry, so a registry-installed `1.0.1` is described here from the manifest and from
46
58
  measurements on a locally packed, installed artefact, and is still not witnessed as a registry download.**
47
59
 
60
+ **⟶ AND THE FIGURE THE PARAGRAPH ABOVE CARRIES IS ITSELF ONE RELEASE BEHIND THE TARBALL IT DESCRIBES, 2026-10-28 — THE VERSION THIS GUIDE DESCRIBES IS `1.1.0`, `1.1.0` HAS BEEN CUT, AND EVERY `1.0.1` THIS GUIDE PRINTS READS `1.1.0` FROM HERE ON.** `RCA-8(g)` ANNOTATE-BESIDE: **the three dated paragraphs above stand BYTE-FOR-BYTE and are read THROUGH this clause — so do their readings of `0.5.0`, of `1.0.0` and of `1.0.1`; each was true of the tree it was read on and each is one release behind the shipped tree from this date.** **THE PARAGRAPH THAT OWES THIS IS QUOTED AT ITS OWN BYTES, because a guide that denies its own tarball is the defect this clause closes — `D-48` · `DEF-AC`: *"THE VERSION THIS GUIDE DESCRIBES IS `1.0.1`, AND EVERY `1.0.0` THIS GUIDE PRINTS READS `1.0.1` FROM HERE ON … the tags the tree carries are `v1.0.0` and `v1.0.1`, with `main` sixteen commits past `v1.0.1` and no version bump in any of them (`git describe` at this date reads `v1.0.1-16-gdf3ef88`; `D-41` item `1`'s semver ruling names the next release `1.1.0`, and that release has not been cut)."*** **THE TARBALL DENIES EVERY FIGURE OF THAT SENTENCE, AND IT IS THE FILE THE GUIDE TELLS YOU TO READ: `bindings/js/package.json`'s `version` is `"1.1.0"` at its own bytes, all five `optionalDependencies` pins are `1.1.0` with it, the tags the tree carries are `v1.0.0` · `v1.0.1` and `v1.1.0`, `git describe` reads `v1.1.0-1-gcbc3f8a`, and `D-41` item `1`'s minor has been RELEASED rather than awaited.** **SO THE SITES ARE RE-READ, NOT RE-SPELLED:** §0's two paragraphs above, §2.2's five exact pins, §8.1's *"an installed `0.5.0`"* — itself already corrected to `1.0.0` and then to `1.0.1` — and §11's manifest table all read `1.1.0`; **every `0.5.0`, `1.0.0` and `1.0.1` this guide prints is the figure of its writing date and reads `1.1.0` from here on**, and the six figures — the main `version` and the five pins — move together and never singly (§0 item 1; `PUB-DD-10`). **THE ONE THING THAT IS STILL UNMOVED IS THE ONE THING NO PASS WITNESSED, AND IT IS NOT A FIGURE:** no `npm install` was run against the registry, so a registry-installed `1.1.0` is described here from the manifest and from measurements on a locally packed, installed artefact, and is still not witnessed as a registry download. **NO OTHER CLAIM OF THIS GUIDE MOVES: the `files` allowlist's six rows (§11's dated re-read clause (i)), the packed set's nineteen-bare/twenty-assembled (§11's clause (ii)), the twenty-status set (§11's clause (iv)), the fourteen own members and every API clause stand exactly as they stood.** (`strata/decisions.md` · `D-48` · `DEF-AC`; `D-41` item `1`; `D-42` item `1`; `D-38`; `docs/specs/storeroom-publish/contract.md §2.3` item `3` — the byte-for-byte guide stage this correction travels by.)
61
+
62
+ **⟶ AND THE RELEASE IN PREPARATION IS NOT THIS GUIDE'S VERSION, 2026-10-28 — THE MANIFEST IS `1.1.0`, AND THIS GUIDE CLAIMS NO `1.2.0`.** `RCA-8(g)` ANNOTATE-BESIDE: **the four dated paragraphs above stand BYTE-FOR-BYTE and are read THROUGH this clause; this clause re-reads one figure and adds one pointer, and moves no other claim of this file.** **THE FIGURE, AT ITS OWN BYTES, READ THIS DATE: `bindings/js/package.json`'s `version` is `"1.1.0"` and all five `optionalDependencies` pins are `1.1.0` with it** — the six figures move together and never singly (§0 item 1; `PUB-DD-10`) — **so `1.1.0` is the version this guide DESCRIBES, and it is the version an installed tree answers to.** **A RELEASE IS IN PREPARATION AND IT HAS NOT BEEN CUT: what it adds is listed in `RELEASE-NOTES.md` at the repository root, under a `1.2.0` heading MARKED UNRELEASED, and nothing in that section is a version this guide claims or a behaviour this guide measured as shipped.** **AND THAT FILE SHIPS NOWHERE:** it stands at the repository root and no tarball carries it (§11's `files` allowlist, six rows), so a consumer reading `node_modules/provident-storeroom` has this guide and the six figures of `1.1.0`, and the `1.2.0` list is a CHECKOUT reader's document. **The rule, in one line: this guide describes what was cut (`1.1.0`); `RELEASE-NOTES.md` describes what is being prepared (`1.2.0`, UNRELEASED); neither claims the other's figure.** (`D-41` item `1`; §11's manifest table reads the same six figures; `docs/specs/storeroom-publish/contract.md §2.3` item `3`.)
63
+
64
+ **⟶ AND THE FIGURES MOVE TO THE PREPARED RELEASE, 2026-10-28 — THE SIX FIGURES THIS GUIDE POINTS AT READ `1.2.0`, AND `1.2.0` IS PREPARED, NOT CUT.** `RCA-8(g)` ANNOTATE-BESIDE: **the five dated paragraphs above stand BYTE-FOR-BYTE and are read THROUGH this clause — so do their readings of `0.5.0`, `1.0.0`, `1.0.1` and `1.1.0`; each was true of the tree it was read on.** **THE MANIFEST AT ITS OWN BYTES THIS DATE: `bindings/js/package.json`'s `version` is `"1.2.0"` and all five `optionalDependencies` pins are `1.2.0` with it** — the six figures move together and never singly (§0 item 1; `PUB-DD-10`) — **and the five platform manifests' own `version` fields read `1.2.0` with them, which is eleven sites and one rebuild.** **SO THE SITES ARE RE-READ, NOT RE-SPELLED:** this section's version line, §2.2's five exact pins, §8.1's *"an installed `0.5.0`"* and §11's manifest table all read `1.2.0`; **every `0.5.0`, `1.0.0`, `1.0.1` and `1.1.0` this guide prints is the figure of its writing date and reads `1.2.0` from here on.** **AND WHAT THIS CLAUSE DOES NOT CLAIM, SAID FIRST BECAUSE IT IS THE EASIER THING TO GET WRONG: `1.2.0` IS PREPARED AT THOSE SIX FIGURES AND THE TAG IS NOT CUT — `git tag --list` carries `v1.0.0` · `v1.0.1` · `v1.1.0` and no `v1.2.0`, so nothing here says the release is cut, and the tag is not cut until the architect cuts it.**
65
+
66
+ **⟶ AND THE TAG THAT CLAUSE SAID WAS ABSENT IS CUT, 2026-10-28 — `v1.2.0` EXISTS, AND IT IS THE RELEASE THIS GUIDE TRAVELS IN.** `RCA-8(g)` ANNOTATE-BESIDE: **the six dated paragraphs above stand BYTE-FOR-BYTE and are read THROUGH this clause — so does the sentence *"`1.2.0` IS PREPARED AT THOSE SIX FIGURES AND THE TAG IS NOT CUT … the tag is not cut until the architect cuts it"*; it was true of the tree it was written on.** **THE TAG AT ITS OWN NAME THIS DATE: `git tag --list` answers `v1.0.0` · `v1.0.1` · `v1.1.0` · `v1.2.0`; the tag `v1.2.0` names a tree whose `bindings/js/package.json` reads `"version": "1.2.0"` at its own bytes and whose five `optionalDependencies` pins read `1.2.0` with it; and `git describe` reads `v1.2.0-1-ge7c211f`.** **SO `1.2.0` IS CUT AND THIS GUIDE DESCRIBES IT — the text you are reading travels inside the `1.2.0` tarball, and a guide that told you its own release did not exist would be the denial this clause closes.** **`RELEASE-NOTES.md` at the repository root still heads its `1.2.0` section `UNRELEASED` and still says no `v1.2.0` tag exists; that file ships nowhere (§11's `files` allowlist, six rows) and its heading is behind the tag — this guide states what was cut, and what was cut is `1.2.0`.** **NO OTHER CLAIM OF THIS GUIDE MOVES: the `files` allowlist's six rows (§11), the packed set's nineteen-bare/twenty-assembled (§11), the twenty-status set (§11) and the fourteen own members all stand exactly as they stood.** (§0's figure rule; `docs/specs/storeroom-publish/contract.md §2.3` item `3` — the byte-for-byte guide stage this correction travels by.) **THE ONE THING THAT IS STILL UNMOVED IS THE ONE THING NO PASS WITNESSED, AND IT IS NOT A FIGURE:** no `npm install` was run against the registry, so a registry-installed `1.2.0` is described here from the manifest and from measurements on a locally packed, installed artefact, and is still not witnessed as a registry download. **NO OTHER CLAIM OF THIS GUIDE MOVES: the `files` allowlist's six rows (§11's dated re-read clause (i)), the packed set's nineteen-bare/twenty-assembled (§11's clause (ii)), the twenty-status set (§11's clause (iv)), the fourteen own members and every API clause stand exactly as they stood.** (`D-41` item `1`; `D-48` · `DEF-AC`; `docs/specs/storeroom-publish/contract.md §2.3` item `3` — the byte-for-byte guide stage this correction travels by; `scripts/publish.sh`'s eleven cells, and the tag coupling `release.md §2.5` puts AFTER them.)
67
+
68
+ **⟶ AND THE TREE THIS TEXT DESCRIBES IS NINE COMMITS PAST THE TARBALL IT TRAVELS IN, 2026-10-28 — THE MANIFEST IS `1.2.0`, `1.2.0` IS CUT AND PUBLISHED, AND `main` CARRIES BEHAVIOUR THAT IS NOT IN THAT TARBALL.** `RCA-8(g)` ANNOTATE-BESIDE: **the seven dated paragraphs above stand BYTE-FOR-BYTE and are read THROUGH this clause; this clause adds the one distinction none of them draws and corrects two sentences of the paragraph immediately above, and it moves no figure and no other claim of theirs.** **THE SIX FIGURES AND THE TAG, AT THEIR OWN BYTES THIS DATE:** `bindings/js/package.json`'s `version` is `"1.2.0"`, all five `optionalDependencies` pins are `1.2.0` with it, the five platform manifests' `version` fields read `1.2.0` with them — eleven sites, one rebuild — and `git tag --list` carries `v1.2.0`, **so the version line above is generated from exactly those two facts and it states that the release this guide travels in is CUT.** **AND THE TREE IS NINE COMMITS PAST THAT TAG:** `git describe` reads `v1.2.0-9-g989c216`, no version bump is in any of the nine commits, and **two of them change behaviour: `§8.0a`'s claim that the `log` belongs to the COMMIT — and that `seq` is the position in that list and not the store's journal ordinal — and `§12.6b`'s carry rule, that a reversal raised inside a pass is judged at that pass's terminal state, describe THIS TREE'S BEHAVIOUR AND NOT THE BEHAVIOUR OF THE `1.2.0` TARBALL** — `1.2.0` ships the per-attempt list and the sentence the carry rule withdraws. **So read this guide for what it is: it is the tree's text, and where it describes the two changes that are not in `1.2.0`, the change list at `node_modules/provident-storeroom/RELEASE-NOTES.md` is what tells you which release carries them — and until the next release is cut, nothing a consumer installs has them.** **AND THE TWO SENTENCES OF THE PARAGRAPH ABOVE THIS ONE THAT THIS CLAUSE CORRECTS:** *"that file ships nowhere (§11's `files` allowlist, six rows)"* is **false from 2026-10-28** — the change list is the allowlist's SEVENTH row and the release's assembly stages it byte-for-byte at the packaging root, so it ships (§11's `2026-10-28` clause (i)) — and *"its heading is behind the tag"* is **withdrawn at that file's own head**, where the `1.2.0` section is now marked **CUT AND PUBLISHED**. **THE VERSION LINE ABOVE IS NOT MOVED BY THIS CLAUSE AND MUST NOT BE: the manifest is `1.2.0` and `v1.2.0` exists, so the figure the preflight generates is the figure written there.** (`D-53`; `D-54`; `DEF-AI`; `DEF-AM`; `DEF-AJ`; the change list's `§MAIN`.)
69
+
70
+ **⟶ AND THE FIGURES MOVE TO THE PREPARED RELEASE, 2026-10-28 — THE ELEVEN SITES READ `1.3.0`, AND `1.3.0` IS PREPARED, NOT CUT.** `RCA-8(g)` ANNOTATE-BESIDE: **the eight dated paragraphs above stand BYTE-FOR-BYTE and are read THROUGH this clause — so do their readings of `0.5.0`, `1.0.0`, `1.0.1`, `1.1.0` and `1.2.0`; each was true of the tree it was read on.** **THE MANIFEST AT ITS OWN BYTES THIS DATE: `bindings/js/package.json`'s `version` is `"1.3.0"` and all five `optionalDependencies` pins are `1.3.0` with it** — the six figures move together and never singly (§0 item 1; `PUB-DD-10`) — **and the five platform manifests' own `version` fields read `1.3.0` with them, which is eleven sites and one rebuild; the rebuilt artefact is stamped from that manifest, so `version()` answers `1.3.0`.** **SO THE SITES ARE RE-READ, NOT RE-SPELLED:** this section's version line, §2.2's five exact pins, §8.1's *"an installed `0.5.0`"* and §11's manifest table all read `1.3.0`; **every `0.5.0`, `1.0.0`, `1.0.1`, `1.1.0` and `1.2.0` this guide prints is the figure of its writing date and reads `1.3.0` from here on.** **AND WHAT THIS CLAUSE DOES NOT CLAIM, SAID FIRST BECAUSE IT IS THE EASIER THING TO GET WRONG: `1.3.0` IS PREPARED AT THOSE ELEVEN FIGURES AND THE TAG IS NOT CUT — `git tag --list` carries `v1.0.0` · `v1.0.1` · `v1.1.0` · `v1.2.0` and no `v1.3.0`, and the registry carries no `1.3.0`; so nothing here says the release is cut, and the tag is not cut until the architect cuts it.** **AND THE TREE THIS GUIDE DESCRIBES IS TEN COMMITS PAST `v1.2.0`** — `git describe` reads `v1.2.0-10-g14787b5` and `git rev-list --count v1.2.0..HEAD` reads `10`, one commit past the nine the paragraph above reads — **so the two behaviour changes and the four smaller items `§1.3.0` of the change list declares are the CONTENT of `1.3.0`, and `1.3.0` is the version that carries them once it is cut; the `1.2.0` tarball carries neither, and `1.3.0` is the version this guide describes from here on.** **THE ONE THING THAT IS STILL UNMOVED IS THE ONE THING NO PASS WITNESSED, AND IT IS NOT A FIGURE:** no `npm install` was run against the registry, so a registry-installed `1.3.0` is described here from the manifest and from measurements on a locally packed, installed artefact, and is still not witnessed as a registry download. **NO OTHER CLAIM OF THIS GUIDE MOVES: the `files` allowlist's seven rows (§11's `2026-10-28` clause (i)), the packed set's `20` bare / `21` assembled (§11's clause (ii)), the twenty-status set (§11's clause (iv)), the fourteen own members and every API clause stand exactly as they stood.** (`D-41` item `1`; the change list's `§1.3.0`; `docs/specs/storeroom-publish/contract.md §2.3` item `3` — the byte-for-byte guide stage this correction travels by; `scripts/publish.sh`'s eleven cells and its two generated figures.)
71
+
48
72
  **AND ONE THING A READER OF THE INSTALLED PACKAGE SHOULD KNOW BEFORE THE CITATIONS: WHEN THIS DOCUMENT IS AT
49
73
  `node_modules/provident-storeroom/README.guide.md`, IT IS THIS GUIDE.** **Its ONE authored home is
50
74
  `docs/guides/package-use.md` in the repository, and the release's assembly stages it byte-for-byte at the packaging
@@ -433,9 +457,14 @@ guide's constraint story that is not yet observable.
433
457
  1. **A reversal INSIDE an open commit is NOT judged.** If you reverse from inside a constraint body, a repair, a listener, or the kernel's own failing-attempt floor call, the state the reversal leaves is not the state that stands (the open window moves it again, and the caller sees nothing yet) — **and judging it would invoke your constraint bodies MID-ATTEMPT and break `D-40`'s promise that a failed attempt leaves the store as it found it.** **The judgement is the AT-REST reversal's: your own `rollback` at the surface, where the state it leaves is the state you then read.**
434
458
  2. **A DISABLED pair is NOT judged.** A pair you `constraintOff`'d still appears in `constraints()`, but the judgement asks only pairs that are enabled — **because a disabled pair cannot fire, so nothing it would refuse can have run.** Re-enable it and it is asked again at the next reversal.
435
459
  3. **A pair registered STRAIGHT THROUGH THE KERNEL'S `K-1` is NOT judged at a reversal.** The judgement reads the package's own registry, which the package's declared registration routes write — `cfg.constraints` at construction and `addConstraint` after it — while a pair placed by a kernel-direct call is evaluated at writes but is **not** in the state the judgement reads (and `constraints()` does not list it either). **Register through the package's routes and the promise covers you.**
436
- 4. **WHEN IT REFUSES AND NO ATTEMPT STANDS, `log` IS ONE `constraint-check` ENTRY — NOT `[]`.** The `log` member is normally *"the attempt's own message log"*, and `[]` is its value where a failure's cause has no attempt; **a reversal's judgement is one of those causes, and here the refusal AUTHORS ITS OWN RECORD instead of reporting an absence:** `log.length === 1`, `log[0].kind === 'constraint-check'`, `log[0].id` the refusing pair's own id, `log[0].state` `null`, `log[0].opId` the reversal's own op id or `null`. **So do not read an empty array as *"nothing failed"* at this arm, and do not read this one entry as an attempt's history — it is the refusal's.**
460
+ 4. **WHEN IT REFUSES AND NO ATTEMPT STANDS, `log` IS ONE `constraint-check` ENTRY — NOT `[]`.** The `log` member is normally *"the attempt's own message log"*, and `[]` is its value where a failure's cause has no attempt; **a reversal's judgement is one of those causes, and here the refusal AUTHORS ITS OWN RECORD instead of reporting an absence:** `log.length === 1`, `log[0].kind === 'constraint-check'`, `log[0].id` the refusing pair's own id, `log[0].state` `null`, `log[0].opId` the reversal's own op id or `null`. **So do not read an empty array as *"nothing failed"* at this arm, and do not read this one entry as an attempt's history — it is the refusal's.** **⟶ AND FROM 2026-10-28 *"the attempt's own message log"* IS READ THROUGH `D-53` AS THE COMMIT'S OWN LIST** (§8.0a above): at this arm no attempt and no commit stands, which is what makes `[]` the wrong value here and one authored entry the right one.
437
461
  **AND ONE THING ABOUT A FAILING REPAIR, WHICH IS THE SAME SHAPE AND IS DECLARED RATHER THAN DISCOVERED: THE FLOOR CALL RESTORES THE ADDRESS THE ATTEMPT WROTE; AN ADDRESS A REPAIR LANDED AT BESIDE IT IS NOT RESTORED.** `D-40`'s sentence — *"a failed attempt leaves the store exactly as it found it"* — is measured true of the attempt's own address and false of a beside address: the store's rollback scope is the addressed subtree at or after the named op's own position, so a repair that writes elsewhere leaves THAT value standing after the failed attempt. **If you need the beside address's pre-attempt value, keep it yourself: the store's own floor call does not put it back** (`docs/specs/storeroom-js/contract.md §2.6`'s clause of 2026-10-26, which is where the four narrowings, the `log` arm and this spatial scope are declared; `E2E-C-9` cell 6 in `tests/e2e/blind-constraints-v2.mjs` is the measured reach).
438
462
 
463
+ **⟶ AND WHAT THE STORE HOLDS AFTER A REFUSED REVERSAL, DECLARED HERE BECAUSE `1.2.0`'s ONE BEHAVIOUR CHANGE IS THIS AND NO SHIPPED DOCUMENT SAID IT UNTIL NOW.** `RCA-8(g)` ANNOTATE-BESIDE: **every clause of §5.4 above stands BYTE-FOR-BYTE and is read THROUGH this one; this clause adds the declaration the release owed and moves no promise it prints.**
464
+
465
+ - **THE FACT: WHEN A REVERSAL IS REFUSED, THE COMPENSATING ACT PUTS THE STORE BACK AT THE MARK THE COMMIT CACHED WHEN IT OPENED — the journal's LAST VALID POSITION as it stood when that commit began (an op id, or the FLOOR where the journal held no entry then) — and never at whatever the journal's head happens to be when the refusal is built.** **Every address the reversal MOVED is read again afterwards and counted as restored only where it stands exactly as it stood before the reversal — the same value at the same tier, or absent where it was absent — and the refusal's one log entry says so address by address**, naming each address that could not be put back with what stands there instead and what it was owed (§8.1 row `20`; `js/contract.md §2.6`'s clause of 2026-10-27). **A reversal taken AT REST makes the two marks describe the same state** — it appends no journal entry — **so this is where the store stands either way at the surface.**
466
+ - **WHAT `1.2.0` CHANGED, IN ONE SENTENCE, SO YOU KNOW WHICH BEHAVIOUR YOUR VERSION HAS: BEFORE `1.2.0` THE RESTORE NAMED THE JOURNAL'S HEAD; FROM `1.2.0` IT NAMES THE OPENING MARK.** **Why the head was wrong is the measurement the ruling was taken on (`DEF-AE`):** *"a reversal appends no journal entry, so the head describes the state that stood before the action"* is true of a reversal **you** take at rest and **false of one taken inside a write's own commit** — there the ENCLOSING WRITE'S OWN OP stands at the head when a listener body's reversal runs, so the old compensation restored the write's LANDING and **a write that reported a refusal had left its own value standing** (measured: `9` stayed `9` where the refused write should have restored `7`). **In `1.2.0` a write that reports a refusal leaves the store where the ATTEMPT found it, not where the refusal's own op landed.** **A LAWFUL reversal is unchanged** (same `{opId, undoneOps, restoredTo}`, no throw), **and a lawful write still answers its record with its value standing.** **MEASURED ON THIS CHECKOUT, 2026-10-28:** a refused write restores the pre-attempt value at its own tier, and the reversal's own refusal restores the pre-reversal standing tier for tier (`tests/e2e/def-ae-restore-mark.test.mjs` cells `1`–`2`; `tests/e2e/refused-reversal-restore.test.mjs`'s shadow, higher-tier/parent and absent arms). **So the store after a refused reversal holds exactly the state the act FOUND — not a later landing that the refusal's own sentence has already told you was undone.**
467
+
439
468
  ---
440
469
 
441
470
  ## §6 · Watching for changes: the listener surface
@@ -688,6 +717,55 @@ filter nothing on one.** **There is no read-side enforcement arm, none is declar
688
717
  writes and on nothing else** — and **reads consult no constraint's verdict, filter nothing on one, and refuse
689
718
  nothing because of one.**
690
719
 
720
+ ### §7.6 ★ `context.value` is what the write verb returned — read anything else yourself
721
+
722
+ **★ THE ONE SENTENCE TO CARRY AWAY: `context.value` is the value the write verb returned; a constraint that
723
+ cares about another location reads it.** (`D-50`, the architect, verbatim: *"If a constraint needs to look for
724
+ the data at a given location, it can read()"*.)
725
+
726
+ **AND THE CASE THAT MAKES IT MATTER IS A REPAIR THAT LANDS SOMEWHERE ELSE.** A constraint that refuses `2` at
727
+ its own address `['a']` returns a repair that writes `11` at a *different* address `['b']`. **The repair's op is
728
+ the attempt's last op, so the re-run hands your body the value that op landed — `11` — while the address your
729
+ pair judges still stands at `2`.** **That is not a machinery defect: it is the value the write verb returned, and
730
+ the package cannot be wrong about a value it was told to hand over — it can only be wrong about what it stored.**
731
+ **If your constraint cares about the state at any other location — the address it judges, the address its repair
732
+ landed at, or anywhere else — IT READS THAT LOCATION.** The body is your code, it closes over the store handle
733
+ you already hold, and `store.read(address)` is a published verb. **Measured 2026-10-28**
734
+ (`tests/e2e/discard-witness.mjs`, the `W8` cell): the re-run handed the pair `11` while its own address read
735
+ `2`; **the same body with `store.read(['b'])` refused on what it read** — the write failed and the store was
736
+ restored — **and the same body without the read passed, answering its record with its own value still standing at
737
+ its address.** **The read is the whole difference.**
738
+
739
+ **★ AND THE CONSEQUENCE A READER GETS WRONG, IN `D-50`'S OWN WORDS: *"a constraint that reads inside its body is
740
+ caller code entering the surface, so by `D-45` that read opens its own commit"* — **⟶ MEASURED 2026-10-28, AND THAT CLAUSE IS WRONG: A READ BRACKETS NO COMMIT AT ALL.** `read`, `readLiteral` and `constraints` are the surface's **NON-BRACKETING** calls — the count during a constraint body's read is the attempt's own and is left undisturbed, `attempt-opened` does not fire for it, and the same `attempt` is in force. **So the accurate consequence is the shorter one: a read inside a body runs INSIDE the attempt's window, opens nothing, and disturbs nothing.** (The `D-45` quote above is kept as the reading of its own date; this sentence governs.) — AND A READ RUNS NO CHECK, SO
741
+ NOTHING IS JUDGED BY IT.** **No constraint is asked on the value it returns, no pass runs, and the value you
742
+ read back is never a verdict.** **AND THE COUNT'S OWN RULE IS WHERE THE ACT'S SHAPE IS VISIBLE — MEASURED
743
+ 2026-10-28 AT THE `W8` CELL, ON BOTH SIDES OF THE READ: `read`, `readLiteral` and `constraints` are the surface's
744
+ NON-BRACKETING calls — no commit is bracketed for them — so the count during your read is the attempt's own
745
+ (`open` `1`, `live` `1`) and it is left undisturbed (`open` `1`, the same attempt).** **THE DECLARED SENTENCE IS
746
+ THE AUTHORSHIP — the read is not the write's act — and the count shows what that authorship costs: nothing is
747
+ opened and nothing is judged for it.** **So the load-bearing half for you is the authorship and the absence of a
748
+ check: your read is your own act at the surface, it carries no judgement, and it neither re-asks a constraint nor
749
+ re-runs the pass. A read is data, never a verdict — if you want a state judged, read it and judge it in your
750
+ body.**
751
+
752
+ **⟶ AND THE PASS ASKS EXACTLY THE PAIRS STANDING AT THE ADDRESS IT WRITES, 2026-10-28 — `D-50`'S CONSEQUENCE, WHICH NO CLAUSE ABOVE SPELLS OUT.** `RCA-8(g)` ANNOTATE-BESIDE: **every clause of §7.6 above stands BYTE-FOR-BYTE and is read THROUGH this one; this clause adds one declaration and moves nothing it prints.** **THE RULE: A WRITE'S CONSTRAINT PASS JUDGES THE PAIRS STANDING AT THE ADDRESS IT WRITES — the kernel's own `pairsAtAddress` reads the pair record at that one address — SO A PAIR AT A DIFFERENT ADDRESS IS NOT ASKED.** **If a constraint cares about another location it READS it** (`D-50`, the architect, verbatim: *"If a constraint needs to look for the data at a given location, it can read()"*). **MEASURED 2026-10-28, on this checkout, through the published entry, in a two-address drive:** a pair `b1` registered at `['b']`; **a write at `['a']` asked `b1` `0` times**; **the same write at `['b']` asked it once**, and the value the body was handed was the one that write returned. **So an action one address away is INVISIBLE to your pair** — it was never asked at the address the action moved — **and the body's own `store.read` is the only thing that makes it visible.** **That is the whole reason this section tells you to read what you care about: the pass will not ask a pair that does not stand where you wrote.** (`held-listener/contract.md §2.8` item `1`, `HL-8`: *"the pass selects the rows whose address IS the triggering address"*, preserving the EXACT-ADDRESS rule rather than widening it; `D-50`; §7.1–§7.5's declarations; the pass's own scan at `bindings/js/src/entry/kernel-foundations.mjs:782`.)
753
+
754
+ ### §7.7 ★ The check is BOUNDED — THREE restarts per terminal act, and past the budget it fails closed
755
+
756
+ **★ THE LIMIT, DECLARED HERE BECAUSE NO CLAUSE OF THIS GUIDE SAID IT: A CONSTRAINT CHECK RESTARTS AT MOST THREE TIMES PER TERMINAL ACT.** The bound is **`RESTART_LIMIT` = `3`**, one exported constant at **`bindings/js/src/entry/constraints.mjs:1366`**. **THE BUDGET IS SPENT AND NOT RESET by an action raised inside a restart** — a body that reverses again inside a restart's own ask spends the SAME budget and not a fresh one — **AND PAST IT THE CHECK FAILS CLOSED IN THE ONE FORM:** the write throws the same plain `{status, message, log}` it throws for a refused pass (§8), with `status` **`'ConstraintPassRefused'`** and **ONE log entry** whose message says the budget was spent rather than that a pair refused a state it never judged. **The store is restored** — the request's own watch records what is owed — so the terminal act leaves no unjudged effect standing (`D-42` item `3`; `D-41` item `4`).
757
+
758
+ **⟶ AND THE ARM PAST THE BUDGET NAMES THE PAIR THAT WAS BEING ASKED, AND SAYS WHAT IT IS, 2026-10-28 — `DEF-AL`, MEASURED AND CLOSED HERE.** `RCA-8(g)` ANNOTATE-BESIDE: **the two clauses above stand BYTE-FOR-BYTE and are read THROUGH this one; this clause re-reads what the refusal NAMES and what its `message` SAYS, and moves no status, no form and no bound.** **WHAT WAS MEASURED:** the arm named the FIRST WATCHED ADDRESS rather than the one the budget was spent at, **so registration order decided the accusation — the pair it named had answered `true` on every ask it received**, and the crossed `message` was **byte-identical to a genuine refusal's**, so a consumer reading only the message could not tell a pair refusing from a budget running out. **WHAT IT DOES NOW:**
759
+ - **the one `log` entry names the pair that was BEING ASKED when the budget ran out, and the address it was being asked at** — not the first watched address — **and its sentence says that pair refused nothing and that the check could not settle**;
760
+ - **the crossed `message` keeps the store's generated sentence for `ConstraintPassRefused` and then says, in its own words, that this is a RESTART BUDGET EXHAUSTION and NOT a constraint pair refusing a state** — no pair refused the state the check was asking it for, a pair body acted inside the check at every restart, and the budget is spent. **A GENUINE refusal never carries that clause**, so the two are distinguishable by the message alone.
761
+ **`status` stays `ConstraintPassRefused`, the form stays `{status, message, log}`, ONE log entry stands, and the store is still restored by the refusal's own compensating act.** (`D-42`; `D-41` item `4`; §7.7's bound above.) **MEASURED 2026-10-28, on this checkout, with a passing pair registered FIRST: the entry named the passing pair and the passing pair's address before this clause, and names the pair the check was asking and its own address after it; the crossed message said `'t5' was refused by a constraint pass, the state this act would leave is not one the registered constraints admit` before and carries the budget's own clause after — beside a control in which a genuine refusal still reads as its refusing pair's own sentence.**
762
+
763
+ **MEASURED 2026-10-28, ON THIS CHECKOUT, THROUGH THE PUBLISHED ENTRY — AND THE MEASUREMENT IS THE POINT: THE RESIDUAL IS THE BUDGET, NOT THE STATE AND NOT THE JOURNAL.** A pair whose body raises ONE FRESH REVERSAL on every ask the restart makes, **with every ask passing**, was driven twice: **with `60` fresh reversals available it rests at exactly `3` restart asks** (the listener's own action plus one per ask — `4` actions in all), **and with `40` available it answers identically, `3`.** **The body had `57` and `37` reversals it never got to spend, and nothing structural stopped it: every ask it made passed.** The terminal write then refused `ConstraintPassRefused` with its log entry saying the budget was spent.
764
+
765
+ **AND WHY THE BOUND EXISTS, SAID PLAINLY: NO STRUCTURAL STATE DISTINGUISHES A BODY THAT KEEPS REVERSING FROM ONE THAT MEANS TO.** The machinery cannot tell a loop from a caller with more work to do, so the restarts are COUNTED and the check fails closed instead of spinning.
766
+
767
+ **WHAT DOES NOT SPEND THE BUDGET**, so a lawful in-commit action costs at most one round and no more: **a request whose watch shows no moved address is consumed and asks nothing** — it can neither loop nor exhaust the budget — and **the count belongs to the PASS's own scope**, so a nested pass (a listener body's own write) has a scope and a budget of its own, exactly as it has its own commit (`js/contract.md §2.6`'s clause of 2026-10-27, item `4`).
768
+
691
769
  ---
692
770
 
693
771
  ## §8 · Refusals
@@ -719,6 +797,64 @@ attempt at all, and every failure whose attempt exists carries that attempt's ow
719
797
  `unlisten`, `register` and `removeListener`: every one was an `Object` whose `Object.keys` was
720
798
  `["status","message","log"]`, whose `log` was `[]`, and which was not an `Error` instance.**
721
799
 
800
+ ### §8.0a What the `log` IS: one list per COMMIT — and what that buys you
801
+
802
+ **⟶ ADDED 2026-10-28. THIS SUBSECTION IS THE ONE THING TO KNOW ABOUT `log`, AND IT CHANGES WHAT YOU WILL SEE
803
+ IN IT.** `RCA-8(g)` ANNOTATE-BESIDE: **the paragraph above stands BYTE-FOR-BYTE and is read THROUGH this
804
+ subsection.** **The architect, verbatim: *"If it's part of the same commit, then it uses the same message log.
805
+ If it opens a new commit, it uses the new commit's message log. Constraints/Repairs should always use the same
806
+ commit. Listeners should open a new commit, because the triggering commit already passed constraints"***
807
+ (`strata/decisions.md` · `D-53`).
808
+
809
+ **SO THE LIST BELONGS TO THE COMMIT AND NOT TO THE ATTEMPT.** One write is one commit, and everything that
810
+ commit does — the constraint passes that judged its value, a repair's own write, the re-run after that repair,
811
+ and the terminal arm's `outcome` entry — **appends to ONE array**. Consequences you can rely on, each measured
812
+ on this checkout:
813
+
814
+ - **`seq` runs `1..n` CONTINUOUSLY across those steps**, because it is *the ordinal of the list it stands in*
815
+ and there is one list. A repair's `commit` entry can stand in the middle of the list, between the refused
816
+ pass's entries and the re-run's: **it is a real entry of the same commit, not a second log.**
817
+
818
+ **⟶ AND WHAT `seq` IS TRUE OF, SAID PLAINLY, 2026-10-28 — `DEF-AI`, MEASURED.** **`seq` is the position of the
819
+ entry in the commit's own message log; it is not the store's journal ordinal, and the two differ by design.**
820
+ `RCA-8(g)` ANNOTATE-BESIDE: **the bullets above stand BYTE-FOR-BYTE and are read THROUGH this paragraph.** **THE
821
+ MEASUREMENT THAT OWES IT: a refusal's entry carried `seq` `1` while the store's own journal counter read `41`, and a
822
+ consumer read the two as one ordinal.** They are two ordinals with two homes — **`JournalOp.seq`, the store's
823
+ append ordinal that orders the store's record, and this `seq`, the kernel's append ordinal on the COMMIT's one
824
+ list** — and neither equals the other by construction. **AND THE ORDER ACROSS A COMMIT'S ATTEMPTS IS MEASURED, NOT
825
+ CLAIMED: one repair write appends the five entries `constraint-check` `1` · `repair-run` `2` · `commit` `3` ·
826
+ `constraint-check` `4` · `commit` `5` — strictly increasing in array order, continuous from `1`, across the pass,
827
+ the repair's own joined write and the re-run** (`tests/e2e/repair-in-commit.test.mjs`'s `D-46` (1) cell, printed).
828
+ **No entry is ever minted from the store's journal counter**: that would be a second ordinal with no consumer.
829
+ (`D-53`; `D-48` · `DEF-AI`; `index.d.ts`'s `LogEntry` carries the same sentence.)
830
+ - **A nested write a CONSTRAINT body makes is part of the same commit**, so **its entries are in YOUR list** —
831
+ which is why a constraint body that performs a refused write now shows you that refusal's own
832
+ `constraint-check` and `outcome` entries, verbatim, before the enclosing `outcome` entry. **That is `DEF-AK`'s
833
+ `constraint` host.** (Its `listener` host is unchanged, and the difference is the next bullet.)
834
+ - **A LISTENER's write OPENS A COMMIT OF ITS OWN**, so **its entries are NOT in the list of the commit that
835
+ triggered it**: *the triggering commit already passed constraints, so what the listener does is a new
836
+ question.* If you need to know what the listener's own write decided, catch the refusal the listener body
837
+ lets out — it carries **its own** `log`, and so does a refusal you throw out of a listener.
838
+ - **A failed `file`-tier SAVE now crosses WITH THE COMMIT'S ENTRIES — its `log` is no longer `[]`.** The save is
839
+ the write's LAST constraint: when it fails, the one `outcome` entry that ends your list carries **`KC-9`**,
840
+ and the entries before it are everything the commit did. **So a consumer can tell the two failing arms apart
841
+ from the log alone: `ConstraintPassRefused` ends at `KC-3`/`KC-5`/`KC-6`/`KC-8`, `FileCommitFailed` ends at
842
+ `KC-9`.** (See `§8.1`'s token line below — the kernel's set is `KC-1`…`KC-9` from this date, and the store's
843
+ closed status set has not moved.)
844
+ - **A refusal that names no attempt still carries `[]`** — a `listen` refusal, a construction refusal, a
845
+ detached member's — and a `TypeError` from a constraint method carries `[]` too. **The list is the COMMIT's
846
+ and there is no commit there.**
847
+
848
+ **READ THIS BEFORE YOU LOG-COUNT.** `log.length` is **not** *"how many constraints were evaluated"* and not
849
+ *"how many attempts this write made"*: it is **every entry of the commit**, in append order, from every attempt
850
+ the commit held. Count entries by `kind` and `id` (and by `opId` where you need the iteration) rather than
851
+ assuming a shape, because **a repair or a body's own write legitimately adds entries to the list you caught.**
852
+
853
+ **AND THE ONE PLACE THE INVARIANT IS NOT REACHED, SAID PLAINLY RATHER THAN LEFT TO A MEASUREMENT: a pair body
854
+ invoked at a REVERSAL's judgement has no commit record standing beside it to name**, so a write such a body
855
+ makes still opens a commit of its own and its entries land in that commit's list and not in the reversal's
856
+ refusal (`js/contract.md §2.6`'s `D-53` clause, item `6`).
857
+
722
858
  **EVERY REFUSAL NAMES ITSELF** — by a `status` from the store's own closed set, and by a **human `message` that
723
859
  carries the address, the domain, and what was found instead.** The message is generated from the code and the
724
860
  failing trigger's arguments and never hand-authored at a call site
@@ -741,6 +877,17 @@ answers it again**, and the status stops naming a layer that did not fail. The a
741
877
  own date and is read THROUGH this clause** (the guide's figures move with the set's own membership, which is
742
878
  this section's own rule).
743
879
 
880
+ **★ AND THE KERNEL'S OWN TOKEN SET — the one that rides `log[].state` — GREW BY ONE ON 2026-10-28, WHILE THIS
881
+ SECTION'S SET DID NOT MOVE AT ALL.** **The architect, verbatim: *"Open the token set"*** (`strata/decisions.md` ·
882
+ `D-53`). **The kernel's states are `KC-1`…`KC-9` from this date; the appended member is the SAVE ARM's own,
883
+ `KC-9`, and `KC-8` keeps its declared meaning (the composition's floor) unmoved.** **WHY IT WAS OWED: a save
884
+ failure and a constraint refusal both ended at `KC-8` on the arm where the failed save's compensation met a
885
+ floor code, so `KC-8` crossed as two statuses and neither arm was derivable from the log's terminal state.** **So
886
+ now: a constraint's refusal ends at `KC-3`/`KC-5`/`KC-6`/`KC-8`, a failed save ends at `KC-9`, and the two are
887
+ told apart by the list you caught.** **NO MEMBER OF THE STORE'S CLOSED STATUS SET MOVES AND NO RANK OF IT
888
+ MOVES**: `KC-9` rides `log[].state` exactly as every other token does, and `status` still never carries a `KC`
889
+ spelling at all — the paragraph above's own law (`A120` (2)), unmoved.
890
+
744
891
  **⟶ RE-DERIVED 2026-10-26 TO THE ARCHITECT'S RULING AND NOT TO THE BYTES** (`DEF-S` and `DEF-N`; the architect,
745
892
  verbatim: *"Expand the returned error set for both S/N"*). **`StoreStatus` carries NINETEEN members, plus the open
746
893
  escape arm `(string & {})`** — ranks `1`…`17` stand exactly as the paragraph below prints them, and the two
@@ -778,6 +925,13 @@ whose union stopped at `17` would mistype both.** **So: do
778
925
  not `switch` on these without a `default`, and NEVER treat an unknown `status` as success.** The set is the
779
926
  store's to close; **the package mints no member, widens no set and renames none.**
780
927
 
928
+ **⟶ AND AN INNER REFUSAL A CONSTRAINT BODY THREW NOW CROSSES BESIDE THE CROSSED ONE, 2026-10-28 — `DEF-AK`, MEASURED AND DECLARED.** `RCA-8(g)` ANNOTATE-BESIDE: **the paragraph above stands BYTE-FOR-BYTE and is read THROUGH this one; no rank moves and no member is minted.** **WHAT WAS MEASURED: a LISTENER body propagates an inner refusal VERBATIM — same `status`, same `message`, same two-entry `log` — while a CONSTRAINT body making the IDENTICAL write had it REPLACED by a generated `ConstraintBodyThrew` whose single log entry was the OUTER attempt's, with the inner refusal's own literal occurring ZERO TIMES anywhere. WHICH HOST YOU WERE INSIDE DECIDED WHAT YOU WERE TOLD.**
929
+ - **`ConstraintBodyThrew` is still the `status` that crosses** — the body did throw, and rank `18` says so — **but the inner refusal is now REACHABLE from what you catch, under `Symbol.for('provident-storeroom.inner-refusal')`:** a non-enumerable own member carrying the value the body threw, so **its own `status`, its own `message` and its own `log` are all there to read.** `Object.keys(caught)` still reads `["status","message","log"]` — three members in the form's own order — and the form is unmoved.
930
+ - **AND THE CROSSED SENTENCE STOPS CLAIMING MORE THAN IT DELIVERS.** Its own bytes — *"a constraint body's throwable crosses as this refusal"* — now stand followed by **the package's own clause saying the value the body threw does NOT cross as this refusal, naming the inner `status` and quoting the inner `message`, and saying where the inner refusal crosses instead.** A body that threw something that is **not** a refusal (**a `TypeError`, a string**) has **nothing carried beside the crossed form**; there is no inner refusal to name, and the generated sentence names the CODE rather than promising a value.
931
+ - **A FORGED THREE-MEMBER OBJECT IS STILL NOT QUOTED.** The inner refusal is recognised by **a mark this package sets on the forms IT builds** — never by the shape a caller can spell — so a body throwing `{status, message, log}` of its own gets the generated sentence and nothing of its text is repeated back as though the package had found a refusal there (`DEF-A`'s protection, extended one layer in).
932
+ - **THE LISTENER ARM IS UNCHANGED, AND THAT IS THE CONTROL:** nothing marks a listener's throw, so it still crosses **as itself**, by identity — `caught === thrown`, its own `status`, `message` and `log`. **A `rollback` whose judgement a pair's body threw** crosses `ConstraintBodyThrew` at rank `18` and carries any inner refusal the same way (`§5.4`).
933
+ - **⟶ AND THE CONSTRAINT HOST'S LIST IS NOW THE COMMIT'S, WHICH IS THE DEEPER HALF OF THE SAME RULING (2026-10-28, `D-53`).** The inner refusal's own two entries are **IN the crossed report** — the `constraint-check` entry naming the inner pair and the `outcome` entry carrying `KC-3` — on the same array the enclosing attempt appends to, at a continuous `seq`; **`carriedInner.log` and `caught.log` are ONE array, not two.** **READ §8.0a ABOVE BEFORE COUNTING ENTRIES**: the listener's list is still its own, because the listener's write opens its own commit, and that difference between the two hosts is now the difference the ruling draws rather than an asymmetry nobody declared.
934
+
781
935
  **AND `ValueRefusedAtBoundary` IS THE ONE YOU WILL MEET ON THE VALUE ROUTE:** the package's own walk decides a
782
936
  value's class **before any store verb is called** and answers this member with the failing target's spelling
783
937
  (§10). **`ValueNotAdmitted` stays at rank `14` and is the STORE's own answer on the native route — a pass that
@@ -1120,6 +1274,8 @@ a change of licence.**
1120
1274
 
1121
1275
  **⟶ AND FOUR FIGURES OF THIS SECTION ARE RE-READ AT THE SHIPPED TREE, 2026-10-26, EACH AT ITS OWN SITE, SO THE ALLOWLIST IS NOT LEFT AT A COUNT THE MANIFEST NO LONGER CARRIES.** `RCA-8(g)` ANNOTATE-BESIDE: **every table row, every ★ paragraph and every figure above stands BYTE-FOR-BYTE and is read THROUGH this clause; THIS clause re-reads four figures and moves no rule of theirs — the reachability rule, the licence reading's ground and the `engines` floor all stand whole.** **(i) THE `files` ROW READS SIX ROWS, NOT FIVE** — `bindings/js/package.json`'s `files` array, read at its own bytes: `index.mjs` · `README.md` · `README.guide.md` · `index.d.ts` · `src/entry/` · `src/constraint-kernel.mjs` — **`6 = 4 + 2` ✓, the four root files plus the entry directory and the kernel** — and **the sixth row is the consumer guide's landed copy, `README.guide.md`, staged byte-for-byte from `docs/guides/package-use.md` by the release's assembly and imported by nothing** (`scripts/publish.sh`'s guide stage; `distribution.md §4.2` item 3's documented-text class). **THE TWO *"FIVE"* READINGS ABOVE — the table's own *"five rows"* and the ★ paragraph's *"THE FIVE ROWS ABOVE"* — are the reading of their own date and are read THROUGH this clause; and so is the licence paragraph's *"the five allowlist rows"*, whose subject is UNMOVED: NONE of the SIX rows is a `LICENSE` row, and none will be unless `D-8`'s evidence condition is met.** **THE RULE THE COUNT CARRIES IS UNMOVED EITHER WAY: whatever the entry requires by path must ship, and the count is a fact of this tree and not a contract.** **(ii) THE PACKED SET READS NINETEEN MEMBERS BARE AND TWENTY ASSEMBLED** — measured at the shipped packers: **the bare tarball carries `19` files** (`1` `package.json` + `4` root files + `13` entry modules + `1` kernel, `1 + 4 + 13 + 1 = 19` ✓, the guide standing among the four root files), **and the assembled artefact carries `20`, the nineteen plus `LICENSE`, which lands only in the assembled tree** — so a consumer comparing a bare `npm pack` tree with the release's artefact should expect exactly one member's difference and it is the licence. **(iii) AND THE GUIDE ITSELF NOW SHIPS:** **this document's canonical text reaches `node_modules/provident-storeroom/README.guide.md` in an installed package, beside `README.md`** — so a reader of the installed tree holds the document this file is, at that one path, and the landing adds no code, no export and no import. **(iv) THE STATUS SET IS TWENTY** — the figure `§8.1`'s heading and table print, and the one `§8.1`'s own dated clause and `§12.3`'s entry still spell `nineteen`: **each is read through the correction of this date at its own site, and the crate's own `CODES` is `[&str; 20]` at its bytes**, so the declaration of record and the crate agree at twenty.**
1122
1276
 
1277
+ **⟶ AND THE CHANGE LIST NOW SHIPS AND THE ALLOWLIST NAMES SEVEN ROWS, 2026-10-28 — `DEF-AC` (a), MEASURED.** `RCA-8(g)` ANNOTATE-BESIDE: **every row and every dated clause above stands BYTE-FOR-BYTE and is read THROUGH this clause; THIS clause re-reads three figures of this section and adds one document, and it moves no rule of theirs.** **(i) THE `files` ROW READS SEVEN ROWS, NOT SIX** — `bindings/js/package.json`'s `files` array, read at its own bytes: `index.mjs` · `README.md` · `README.guide.md` · `RELEASE-NOTES.md` · `index.d.ts` · `src/entry/` · `src/constraint-kernel.mjs` — **`7 = 5 + 2` ✓, the five root files plus the entry directory and the kernel** — and **the seventh row is the CHANGE LIST's landed copy, `RELEASE-NOTES.md`, staged byte-for-byte from the repository root by the release's assembly and imported by nothing**, the same mechanism and the same declared non-code class as `README.guide.md`. **NONE OF THE SEVEN IS A `LICENSE` ROW**, and none will be unless `D-8`'s evidence condition is met. **(ii) THE PACKED SET READS TWENTY MEMBERS BARE AND TWENTY-ONE ASSEMBLED** — **the bare tarball carries `20` files** (`1` `package.json` + `5` root files + `13` entry modules + `1` kernel, `1 + 5 + 13 + 1 = 20` ✓, the guide and the change list standing among the five root files), **and the assembled artefact carries `21`, the twenty plus `LICENSE`** — so a consumer comparing a bare `npm pack` tree with the release's artefact still expects exactly one member's difference and it is still the licence. **(iii) AND THE CHANGE LIST IS ON DISK IN AN INSTALLED PACKAGE**: `node_modules/provident-storeroom/RELEASE-NOTES.md` is **the declaration of `1.2.0`'s one behaviour change** — *"a refused reversal now restores to the commit's opening mark, not the journal's head"* — and **that is the row's own subject: a consumer receives the behaviour change WITH a shipped declaration of it, not a root document it can only reach by reading the repository** (`scripts/publish.sh`'s notes stage; the preflight REFUSES a drifted landing and refuses an allowlist that does not name it). **THE RULE THE COUNT CARRIES IS UNMOVED EITHER WAY: whatever the entry requires by path must ship, and the count is a fact of this tree and not a contract.**
1278
+
1123
1279
  **AND THE `engines` FLOOR IS ONE DECLARATION WITH ONE READER — YOURS.** `>=18.0.0` is what the artefact loads on
1124
1280
  and it is honest rather than provisional: the addon's highest-referenced Node-API class is the `napi_*` pair at
1125
1281
  **Node-API version 6** (`Node 12.17.0` / `10.20.0`), read at `bindings/js/build.rs:35`–`:36`, and the ESM entry uses
@@ -1286,7 +1442,48 @@ tree sharing no mutable member with the store or with another crossing**, which
1286
1442
 
1287
1443
  **THE SECOND EXIT — REGENERATE THE STORE.** Construct a new instance and replay your writes; **a judged state by construction.**
1288
1444
 
1289
- **Neither window is new and neither is a defect**: both are places **a pass does not begin**, not places a judgement was skipped mid-flight. **And every pass that DOES run drains its own restart request** — so the fail-state is bounded by the two acts that run none.
1445
+ **Neither window is new and neither is a defect**: both are places **a pass does not begin**, not places a judgement was skipped mid-flight.
1446
+
1447
+ **⟶ AND THE SENTENCE THAT STOOD HERE IS WITHDRAWN AS FALSE, 2026-10-28 — `D-54`, MEASURED, AND IT IS WITHDRAWN RATHER THAN NARROWED. THE BYTES WERE: *"And every pass that DOES run drains its own restart request — so the fail-state is bounded by the two acts that run none."* THE CONSUMER MEASURED THREE HOSTS WHERE NEITHER HALF HOLDS — a repair body, a delete's pass, and a reentrant reversal-then-write — AND IN EACH ONE A PASS RAN, THE REVERSAL WAS LEFT UNJUDGED, AND ITS EFFECT STOOD (zero judge invocations; the refused `5` still there). What follows replaces them and is true of the code after that fix.**
1448
+
1449
+ **THE RULE NOW, IN ONE SENTENCE: NO PASS CONSUMES A RESTART REQUEST IT DID NOT RAISE, AND A REQUEST RAISED INSIDE A PASS IS CARRIED TO THAT PASS'S OWN TERMINAL STATE AND JUDGED THERE — ONCE, AS `D-38` DECLARES, AND NEVER PER STEP.** The budget, its three asks, the failing-closed arm and `D-42` are exactly as they were; what changed is where the request is carried.
1450
+
1451
+ - **A PASS THAT RUNS TO ITS PASSING ARM** drains the request its bodies raised after the pass and before its commit closes — unchanged, and the arm this section always described.
1452
+ - **A PASS THAT ENDS BY THROWING** reaches the SAME judgement: a repair body that reversed and then broke the attempt's re-run, or a pair that refused after its delivery's act, is judged at the TERMINAL state the pass left, inside the same window, before you meet the pass's answer. **A pass's own refusal is superseded by the verdict of the check it invalidated — the state that pass left**; a constraint body's own throwable and a store's own refusal still cross as themselves, so no caller's value is re-shaped.
1453
+ - **A NESTED PASS NO LONGER DROPS AN ENCLOSING WINDOW'S REQUEST.** The restart's consumer compares window identities; where they differ it ASKS NOTHING AND TAKES NOTHING. The request stands for the act that raised it (`D-42` item `3`), and the enclosing pass's own check is the one that judges it. **A request no pass ever matches still dies with its window**, and the two passless windows below have their own answers.
1454
+ - **AND THE PACKAGE'S OWN COMPENSATING ROLLBACK IS NOT AN ACTION OF YOURS.** The kernel's terminal act composes the attempt's rollback through the `rollback` member; while it does, it carries a flag and neither raises a request nor is judged as a step — `D-42`: *"a restart is only ever raised by a consumer's own `rollback` member call."*
1455
+
1456
+ **SO THE FAIL-STATE OF PASS-HOSTED REVERSALS IS EMPTY, AND WHAT GUARANTEES IT IS ONE CONSUMER: the drain in the pass's own commit scope, reached on BOTH arms, matching the window that raised the request, and judging at the pass's terminal state.** The exits below are now owed to the two passless windows alone.
1457
+
1458
+ **YOUR `delete` QUESTION, ANSWERED HERE, AND IT IS A THIRD CASE AND NOT THE DECLARED ONE.** A `delete` runs **no constraint pass of its own** (`D-1-bis`); the window declared above is its LISTENER DELIVERY, which runs no pass and is UNCHANGED — the `discarded` witness still reports the discard and the reversal's effect still stands. **Where a `delete` is performed INSIDE a pass — the case the consumer measured — the delete's window IS that pass's window**, and a reversal raised by the listener its delivery fires is a DIFFERENT ACT AT A DIFFERENT INSTANT from the declared window: **a THIRD case, and it is now judged** — the request lands in the pass's window and that pass's terminal check asks the pairs at the state the reversal left. **A registration's own evaluation remains the second passless window, silent and identity-only** (`D-49`), and both exits below still leave it honestly.
1459
+
1460
+ **⟶ ADDED 2026-10-28 — `D-49`: THE DISCARD IS NOW OBSERVABLE ON THE `delete`'S OWN ANSWER, AND THE OTHER
1461
+ WINDOW STILL CARRIES NOTHING. READ THIS BEFORE YOU RELY ON EITHER FAIL-STATE.**
1462
+
1463
+ **THE USE CASE THAT MADE IT A DEFECT, IN YOUR TERMS.** Your `window.tabs` is one object; **a listener you
1464
+ installed at `window.tabs` DOES fire when you delete `window.tabs.landingPage`** — the triggered set's rule is the
1465
+ address prefix, and the invocation's one argument is the deleted address. That is exactly where you would check
1466
+ your own invariant — *"exactly one tab is active"* — **and that check IS the kind of act the delete-delivery
1467
+ window throws away**: if it fails and you raise a `rollback`, **the request dies with the window** (`DEF-AH`).
1468
+
1469
+ - **WHAT YOU CAN NOW SEE.** **A `delete`'s record carries `discarded` beside its four members** — a list, `0` or
1470
+ `1` long, of `{ opId, addresses }`: **`opId` is the id the reversal you raised named**, and **`addresses` are
1471
+ the addresses the discarded check would have been asked at**. **`record.discarded.length === 0` means this
1472
+ act's delivery discarded nothing.** **This is a WITNESS, not a repair** — the delete still answers everything
1473
+ it answered, **throws nothing**, mints no new status, and the reversal's effect **still stands**; the
1474
+ fail-state, the exits below and the behaviour of both windows are unchanged.
1475
+ - **READ IT BY ITS NAME, AND EXPECT IT NOT TO BE ENUMERABLE.** `record.discarded` works; **`Object.keys(record)`
1476
+ still prints the four members you already know**, and **a spread or `Object.assign` copy of a receipt does not
1477
+ carry the witness** — read `discarded` off the record itself.
1478
+ - **WHAT IT CANNOT SHOW, SAID PLAINLY.** **A registration's answer (`addConstraint`) is an opaque identity and
1479
+ carries NO witness** — an action raised inside that evaluation is still unobservable, and no member was
1480
+ invented for it. **And the machinery holds ONE pending request per instance**: a second in-flight action
1481
+ overwrites the first, so the witness reports the **last** request a delivery raised, and earlier ones were
1482
+ never recorded. **Neither limit is a defect; both are the declared shape.**
1483
+
1484
+ **THE EXITS ARE STILL YOURS AND ARE UNCHANGED: reload the file, or regenerate the store.** What changed is that
1485
+ **the `delete` now tells you the discard happened** — *"a fail-state is honest only if the consumer learns it
1486
+ happened"* (`D-49`).
1290
1487
 
1291
1488
  ### §12.7 A skip is not a green, and your own throws are not refusals
1292
1489
 
@@ -1335,3 +1532,5 @@ quietly.**
1335
1532
  document, not a test report:** the declared documents are the instrument for questions of semantics, and a
1336
1533
  driven run is the instrument for questions of behaviour. **This guide tries to say which is which, and it is not
1337
1534
  the instrument that decides between them.**
1535
+
1536
+ **⟶ CORRECTED 2026-10-28 — THE BULLET ABOVE'S *"the two of 2026-10-26"* NO LONGER COUNTS THIS FILE, AND THE FIGURE IS MOVED RATHER THAN THE RULE.** `RCA-8(g)` ANNOTATE-BESIDE: **the bullet above stands BYTE-FOR-BYTE and is read THROUGH this clause.** **This file now names FOUR measurements of its own — the two of 2026-10-26 the bullet carries, §7.6's two-address `b1` drive and §7.7's 60/40-reversal restart-budget drive, both taken 2026-10-28 on this checkout through the published entry — and each is named where it stands rather than gathered here.** **WHAT DOES NOT MOVE IS THE BULLET'S RULE AND THE DOCUMENT'S OWN STANDING: this guide is a consumer document and not a test report; a figure it states is either declared and cited or measured and marked; and the declared documents and the driven batteries remain the instruments for questions of semantics and of behaviour respectively.** **A reader who wants the measurements re-run finds their drives named at their sites, and no figure of this file is offered as a green.**
package/README.md CHANGED
@@ -54,7 +54,7 @@ reached INTERNALLY by the package's own resolution step and is not an entry poin
54
54
  | `read(address, tier?)` | a leaf's literal, a branch's assembled value, or the empty address's whole register |
55
55
  | `readLiteral(address, tier?)` | the same, narrowed to a leaf (`ReadTargetIsBranch` on a branch) |
56
56
  | `write(address, tier, value, commit?)` | `{op, watched, triggered}` — **four positions, `commit` the fourth and optional** |
57
- | `delete(address, tier?)` | `{address, tiers, triggered}` |
57
+ | `delete(address, tier?)` | `{address, op, tiers, triggered}`, plus a non-enumerable `discarded` witness |
58
58
  | `rollback(opId)` | `{opId, undoneOps, restoredTo}` |
59
59
  | `listen(handle, addresses)` | **the handle it watches under** (`Handle`) — **you spell it**, and position `2` is a SET |
60
60
  | `unlisten(handle)` | `undefined` — the withdrawal: the store-side entry and this package's registry entry |
@@ -115,6 +115,17 @@ records, with the `outcome` entry's `state` carrying the `KC` token where the co
115
115
  (`index.d.ts`, `LogEntry`; `surface.md §2.5` items 3–4). **The `message` is generated from the code and the
116
116
  failing trigger's arguments**, never hand-authored at a call site.
117
117
 
118
+ **★ AND TWO THINGS ABOUT THAT LIST THAT A CONSUMER COUNTING IT NEEDS — DECLARED HERE BECAUSE THE SURFACE DOES NOT
119
+ TELL YOU EITHER BY ITSELF.** **ONE: THE LIST BELONGS TO THE COMMIT, NOT TO THE ATTEMPT.** One write is one commit,
120
+ and everything the commit does — the passes that judged its value, a repair's own write, the re-run after that
121
+ repair, the terminal arm's `outcome` entry — appends to **one** array, **so a crossed report carries the entries of
122
+ EVERY attempt in the commit, including a write a constraint body makes** (a listener's write opens a commit of its
123
+ own, so its entries are that new commit's). **`log.length` is therefore every entry of the commit and not "how many
124
+ constraints were evaluated".** **TWO: AN ENTRY'S `seq` IS THE POSITION OF THE ENTRY IN THAT LIST — NOT THE STORE'S
125
+ JOURNAL ORDINAL.** `JournalOp.seq` orders the store's own record; this `seq` orders the commit's message log, and
126
+ the two differ by design (a refusal's entry can carry `seq` `1` while the store's journal counter reads `41`). **The
127
+ kernel's `state` token set is `KC-1`…`KC-9`, `KC-9` being the save arm's own; the store's status set has not moved.**
128
+
118
129
  ## The status set is TWENTY, and open by design
119
130
 
120
131
  **`StoreStatus` carries TWENTY members, ranked `1`…`20`, plus the open escape arm `(string & {})`** — the union
@@ -178,8 +189,9 @@ is REJECTED in both directions** — a listener and a constraint do not share on
178
189
  constraint arm is declared, and none is owed.
179
190
 
180
191
  **What a refusal costs you:** a write whose registered constraint refuses it **throws
181
- `{status: 'ConstraintPassRefused', message, log}`** — rank `20` — with the failure's `log` carrying the
182
- attempt's own entries and the kernel's `KC` token on the `outcome` entry's `state`. **The value is not written
192
+ `{status: 'ConstraintPassRefused', message, log}`** — rank `20` — with the failure's `log` carrying the entries of
193
+ the write's whole commit (the attempt's own among them, and every attempt the commit held) and the kernel's `KC`
194
+ token on the `outcome` entry's `state`. **The value is not written
183
195
  and a failed attempt leaves the store exactly as it found it**, whether the constraint refused outright or its
184
196
  repair failed on the re-run (`D-40`).
185
197
 
@@ -268,8 +280,12 @@ empirically by `delivery` together with the e2e/install instruments. **No declar
268
280
  exclusivity binds the allowlist** — a hand-maintained count in its place would re-create the constraint those
269
281
  rulings lifted. **ONE DOCUMENTATION ROW IS ADDITIVE AND DECLARED AS SUCH:** `README.guide.md` names no module and
270
282
  imports nothing, so it travels in the reachability rule's own declared non-code class (`README*` at the package
271
- root) and no limb of that rule moves for it. **The prohibitions are unmoved:** no `.node`, no `build/Release`
272
- path and no `postinstall` route in this package's own tarball, and no `LICENSE` row.
283
+ root) and no limb of that rule moves for it. **AND A SECOND: `RELEASE-NOTES.md` is the change list, staged
284
+ byte-for-byte at the packaging root by the release's assembly, names no module and imports nothing, and is likewise
285
+ admitted and declared** — so the manifest's `files` allowlist reads **seven rows** and the packed set reads **`20`
286
+ members bare / `21` assembled** (`1` manifest + `5` root files + `13` entry modules + `1` kernel `= 20`, plus the
287
+ licence at assembly). **The prohibitions are unmoved:** no `.node`, no `build/Release` path and no `postinstall`
288
+ route in this package's own tarball, and no `LICENSE` row.
273
289
 
274
290
  ## Tests — a REPOSITORY instruction, not a consumer one
275
291
 
@@ -279,12 +295,12 @@ nothing by them. **A consumer's own tests are the consumer's.**
279
295
 
280
296
  ```sh
281
297
  cargo test --manifest-path tests/Cargo.toml -p storeroom-tests --no-fail-fast # THE BATTERY'S LEG — 235 cells, 0 fail
282
- cargo test --offline -p storeroom-native # THE STORE'S LEG — 415 cells, 0 fail
283
- cargo test # BOTH — 650 cells, 0 fail
298
+ cargo test --offline -p storeroom-native # THE STORE'S LEG — 434 cells, 0 fail
299
+ cargo test # BOTH — 669 cells, 0 fail
284
300
  ```
285
301
 
286
302
  **AND THE THIRD COMMAND IS NOT A FOURTH LEG:** a bare `cargo test` runs `default-members = [".", "tests"]`, so
287
- it is EXACTLY the store's `415` plus the battery's `235` — `415 + 235 = 650` ✓ — in one run (`D-34`: one
303
+ it is EXACTLY the store's `434` plus the battery's `235` — `434 + 235 = 669` ✓ — in one run (`D-34`: one
288
304
  workspace at the repository root, `members = [".", "bindings/js", "tests"]`). **`-p` IS NOT DECORATION ON THE
289
305
  BUILD SIDE EITHER:** the store's leg keeps `--offline`, and a workspace-root `cargo build --offline` would pull
290
306
  this crate's `napi` crates and `--offline` would refuse them.