provident-storeroom 0.3.1 → 0.4.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/index.d.ts CHANGED
@@ -17,7 +17,10 @@
17
17
  // `constraintOn(pair, constraint)` · `constraintOff(pair, constraint)`, **PLUS `register(handle, listener)
18
18
  // -> undefined` and `settle(record) -> undefined`** — the last being THE ORDERING SEAM the kernel calls and
19
19
  // the entry implements; and (3) the failure surface, a thrown plain object with exactly
20
- // `{status, message}`.
20
+ // `{status, message, log}` — **THREE MEMBERS FROM 2026-10-16, `2 → 3`, on the architect's ruling *"Bubble
21
+ // the message log to the client on failure, override any clauses that forbid this."*** (`surface.md §2.5`'s
22
+ // clause of that date, the crossing form's ONE home; **the ONE figure that moves is the arity, and
23
+ // `storeCreate` remains the namespace's one name and the product its twelve own members**).
21
24
  //
22
25
  // **THE TEN METHODS TAKE THE RECEIVER'S OWN POSITION AWAY: `8 → 1` ✓ AND `4 → 12` ✓** (`surface.md §2.9`
23
26
  // item 1's and `§2.4` item 9 (f)'s `A127` clauses). The seven verbs that reach the store are METHODS of the
@@ -188,14 +191,46 @@ export type StoreStatus =
188
191
  | (string & {});
189
192
 
190
193
  /**
191
- * **THE SINGLE FAILURE SURFACE** (`contract.md §1.4`; `distribution.md §5.2` item 3): a THROWN plain
192
- * object carrying exactly `{status, message}` — never an `Error` subclass, never a returned tagged union,
193
- * never a `Promise` rejection and never a third member. **The status is carried VERBATIM from the store's
194
- * own closed set and the message is the store's own generated string**; this package mints neither.
194
+ * **THE KERNEL'S OWN LOG ENTRY** — *"exactly six members — `seq` · `kind` · `id` · `message` · `opId` ·
195
+ * `state`"* (`docs/specs/storeroom-constraints/kernel-surface.md §2.5` item 1, whose member set is CLOSED:
196
+ * *"a seventh member of `LogEntry` … is not a variation, it is a different shape"*). **DECLARED HERE ONLY
197
+ * AS THE ELEMENT SHAPE OF THE FAILURE'S `log` MEMBER, AND MINTED BY NO CLAUSE OF THIS UNIT**: an attempt's
198
+ * message log entries are the KERNEL'S records, carried VERBATIM, and no flattening is declared — a client
199
+ * that reads one reads the kernel's own entry.
200
+ *
201
+ * `kind` is the kernel's closed four-member `LogKind` set, and `state` is the kernel's own `KC` token on the
202
+ * one `outcome` entry and `null` on the three non-`outcome` kinds.
203
+ */
204
+ export interface LogEntry {
205
+ readonly seq: number;
206
+ readonly kind: 'constraint-check' | 'repair-run' | 'commit' | 'outcome';
207
+ readonly id: string | null;
208
+ readonly message: string;
209
+ readonly opId: string | null;
210
+ readonly state: string | null;
211
+ }
212
+
213
+ /**
214
+ * **THE SINGLE FAILURE SURFACE** (`contract.md §1.4`; `distribution.md §5.2` item 3) — **AND ITS MEMBER SET
215
+ * MOVES `2 → 3` FROM 2026-10-16 ON THE ARCHITECT'S RULING *"Bubble the message log to the client on failure,
216
+ * override any clauses that forbid this."*** (`surface.md §2.5`'s clause of that date, whose items 1–10 are
217
+ * the crossing form's ONE home). A THROWN plain object carrying exactly `{status, message, log}` — never an
218
+ * `Error` subclass, never a returned tagged union and never a `Promise` rejection. **The status is carried
219
+ * VERBATIM from the store's own closed set and the message is the store's own generated string**; this
220
+ * package mints neither.
221
+ *
222
+ * **`log` IS AN ORDINARY OWN ENUMERABLE DATA MEMBER OF THAT SAME PLAIN OBJECT** (item 9): *"written with an
223
+ * object literal, not `Object.defineProperty`, not a getter, not on a prototype and not behind a `Symbol`"* —
224
+ * so `Object.keys(caught)` reads exactly `["log","message","status"]` and its length is `3` on EVERY arm. **IT
225
+ * IS NEVER ABSENT, NEVER `null` AND NEVER A NON-ARRAY** (item 9), **and `[]` is its declared value where the
226
+ * failure's cause has no attempt at all** (item 4: the empty array, never an absent member and never a
227
+ * placeholder entry) — **while every failure whose attempt exists carries that attempt's own entries, taken
228
+ * BEFORE the attempt is disposed of** (item 10 (iii)).
195
229
  */
196
230
  export interface StoreRefusal {
197
231
  readonly status: StoreStatus;
198
232
  readonly message: string;
233
+ readonly log: LogEntry[];
199
234
  }
200
235
 
201
236
  /** The opaque handle a listener registration is keyed by: the package's own value for one registration. */
package/index.mjs CHANGED
@@ -402,11 +402,84 @@ function addonLoadMessage() {
402
402
  }
403
403
 
404
404
  /// `surface.md §2.5`: **THE SINGLE FAILURE FORM** — a THROWN plain object carrying EXACTLY
405
- /// `{status, message}` and nothing else. **The status and the message are the store's own and are carried
406
- /// VERBATIM** (`§2.5` items 1–2, `DD-40`): this function constructs the two-member form out of the refusal
407
- /// the addon threw and mints no code of its own, authors no message of its own and adds no third member.
408
- function fail(refusal) {
409
- throw { status: refusal.status, message: refusal.message };
405
+ /// `{status, message, log}`. **The status and the message are the store's own and are carried
406
+ /// VERBATIM** (`§2.5` items 1–2, `DD-40`): this function constructs the form out of the refusal the addon
407
+ /// threw and mints no code of its own and authors no message of its own.
408
+ ///
409
+ /// **⟶ AND THE FORM CROSSES AT THREE MEMBERS FROM 2026-10-16 — `surface.md §2.5` ITEM 4, THE ARCHITECT'S
410
+ /// RULING OF THAT DATE: *"`log` IS PRESENT ON EVERY FAILURE THIS SURFACE THROWS, AND `[]` IS ITS DECLARED
411
+ /// VALUE WHERE THE FAILURE'S CAUSE HAS NO ATTEMPT AT ALL."*** **The three-member member set is FLAT ACROSS
412
+ /// ARMS and not conditional:** a `read`/`readLiteral`/`delete`/`rollback` store refusal with no attempt
413
+ /// live, the construction's own `cfg`-side refusals, `a.register`'s refusal and the constraint methods'
414
+ /// `TypeError` all carry `log: []` — **the EMPTY ARRAY, never an absent member, never `null`, and never a
415
+ /// placeholder entry** — while every failure whose attempt exists carries that attempt's own entries
416
+ /// (`§2.5` items 3–4 and 10 (i)–(iii); `§2.12` item 1's mark of the same date). **AND WHERE A STORE ACT
417
+ /// PRODUCED IT, THE STORE'S `status` AND `message` ARE PRESERVED BYTE-FOR-BYTE AND `log` IS ATTACHED BESIDE
418
+ /// THEM — nothing is converted, a member is added** (`§2.5` item 10 (ii); `fail-surface.md §1.2`'s
419
+ /// *"the kernel NEVER CONVERTS ONE CHANNEL'S FAILURE INTO THE OTHER'S FORM"* stands whole).
420
+ ///
421
+ /// **THE `log` MEMBER IS AN ORDINARY OWN ENUMERABLE DATA MEMBER** — written with the object literal below,
422
+ /// **not `Object.defineProperty`, not a getter, not on a prototype and not behind a `Symbol`** — so
423
+ /// `Object.keys(caught)` reads exactly `["log","message","status"]` and its length is `3` on every arm
424
+ /// (`§2.5` item 9). **IT IS NOT `defineProperty`'D BECAUSE A MEMBER THAT IS NOT ENUMERABLE IS NOT A MEMBER
425
+ /// A CANONICAL CENSUS CAN SEE**, and it is not a getter because a client reads a list and not a call.
426
+ ///
427
+ /// **⟶ AND ITS TWO STORE MEMBERS ARE READ OFF THE STORE'S OWN REFUSAL AND OFF NOTHING ELSE — CORRECTED
428
+ /// 2026-10-17 (`A64`'s one form read with `surface.md §2.5` item 5 (e)).** **THE CONSTRUCTION BELOW ONCE
429
+ /// READ `refusal.status` AND `refusal.message` OF WHATEVER IT WAS HANDED, WITH NO PROVENANCE TEST AT ALL**,
430
+ /// and the two failures that cost are named rather than left to be re-derived: **a caller's own throwable
431
+ /// reached it by ONE mis-scoped `try`** (see `storeCreate` below, where that throwable now surfaces as
432
+ /// itself), **and a value that is not an object at all — most sharply the runtime's own `undefined`, where
433
+ /// NO refusal object exists because an exception is already pending — made THIS FRAME fault on
434
+ /// `refusal.status`**, so a caller read *"Cannot read properties of undefined (reading 'status')"* where the
435
+ /// value its own body threw was the whole of what it was owed.
436
+ ///
437
+ /// **THE TEST IS PROVENANCE'S OWN SHAPE AND NOT A CLASS DECISION OF THIS UNIT'S:** the store's refusal is a
438
+ /// plain object whose `status` and `message` are `string`s (`docs/specs/storeroom-native/contract.md §8.3`'s
439
+ /// closed two-member form; `§2.5` items 1–2), and **a value that is not that object is NOT this form's
440
+ /// provenance** — so it is THROWN AS ITSELF, by the one line below, and **NEITHER A STATUS NOR A MESSAGE IS
441
+ /// MINTED FOR IT AND NO `log` IS ADDED TO A VALUE THAT IS NOT THE STORE'S FORM.**
442
+ ///
443
+ /// **⟶ THE PROVENANCE TEST IS *"IS THIS THE STORE'S TWO-MEMBER FORM?"* AND NOT *"DOES THIS CARRY A
444
+ /// `log`?"*, AND THAT DISTINCTION IS THE WHOLE OF THE CORRECTION THIS MEMBER FORCED.** The two-member
445
+ /// presence test **was** the earlier discriminator at the crossing (`constraintCrossing`'s own history: it
446
+ /// discriminated on `log`'s PRESENCE) — **and now that EVERY surface failure carries `log`, presence alone
447
+ /// can no longer tell a store refusal, a kernel refusal and a CALLER'S FORGED OBJECT apart.** **THE TEST
448
+ /// REPLACED IT IS THE STORE'S FORM ITSELF — `status` a `string` AND `message` a `string`, both READ OFF THE
449
+ /// HANDED VALUE AND NEITHER MINTED** — and `log` is then **ATTACHED BESIDE THE TWO, NEVER READ AS THE
450
+ /// DISCRIMINATOR** (`refusalLog` below). A caller's forged `{status, message}` thrown from a constraint body
451
+ /// carries both strings and would pass this test — **which is why this function is never ON the body-throw
452
+ /// path at all**: the body's throwable leaves `runAttempt` unconverted and reaches the caller without
453
+ /// passing here (`fail-surface.md §1.1` item 5; see `constraintCrossing`'s rethrow). **SO NO BYTE OF THIS
454
+ /// FRAME'S PROVENANCE TEST MOVES: every store refusal this package crosses — the eight verbs, the
455
+ /// construction, the `16`-code set — keeps its `status` and its `message` member for member and byte for
456
+ /// byte, and the ONE member this date adds is `log`.**
457
+ function fail(refusal, log) {
458
+ if (refusal === null || typeof refusal !== 'object'
459
+ || typeof refusal.status !== 'string' || typeof refusal.message !== 'string') {
460
+ throw refusal;
461
+ }
462
+ throw { status: refusal.status, message: refusal.message, log: refusalLog(log) };
463
+ }
464
+
465
+ /// **THE ONE PLACE A REFUSAL'S `log` MEMBER IS DECIDED** — `surface.md §2.5` item 4's flat reading, taken
466
+ /// once so no arm can spell it differently. **AN ABSENT ARGUMENT IS THE DECLARED `[]`**: the failure's cause
467
+ /// has no attempt at all (a store refusal with no attempt live, a `cfg`-side refusal, a `register` refusal,
468
+ /// a constraint-method `TypeError`) — *"the EMPTY ARRAY, never an absent member, never `null`, and never a
469
+ /// placeholder entry"*. **A LIST HANDED IN IS THE ATTEMPT'S OWN AND CROSSES VERBATIM** (`§2.5` item 3: *"THE
470
+ /// ATTEMPT'S OWN MESSAGE LOG, VERBATIM … CARRIED AND NOT RE-SHAPED"*), and it is **NOT COPIED**: a copy would
471
+ /// be a second list and the spec's *"the same list the attempt record held"* is a statement about identity
472
+ /// of content, which a copy preserves while costing an allocation on every failure — and **a copy would also
473
+ /// silently paper over the timing trap below**, because a copy taken late reads the same bytes as one taken
474
+ /// early. The list crosses as it stands, and `[]` is minted fresh at each no-attempt failure so that no two
475
+ /// failures alias one array.
476
+ ///
477
+ /// **A `log` THAT IS NOT AN ARRAY IS A FINDING AT THE SITE THAT PRODUCED IT** (`§2.5` item 9) — this
478
+ /// function declares no arm for it and answers the empty array rather than propagating a shape the spec
479
+ /// calls impossible: the alternative is a failure whose `log` is `null` or a non-array, which the same item
480
+ /// names as the finding verbatim.
481
+ function refusalLog(log) {
482
+ return Array.isArray(log) ? log : [];
410
483
  }
411
484
 
412
485
  function withAddon() {
@@ -1816,9 +1889,38 @@ function writeCall(state, args, fault) {
1816
1889
  /// clauses (a)–(b); `A79`).
1817
1890
  export function storeCreate(cfg) {
1818
1891
  const addon_ = withAddon();
1892
+ // **⟶ THE CONSTRUCTION'S OWN READ OF THE CALLER'S `cfg` STANDS OUTSIDE THE BOUNDARY'S CATCH — CORRECTED
1893
+ // 2026-10-17 (`A64`'s one form read with `surface.md §2.5` item 5 (e); the ruling *"catch a throw from a
1894
+ // repair and encapsulate the message to distinguish forgeries"*).**
1895
+ //
1896
+ // **THE DEFECT IT CLOSES, NAMED AT ITS BYTES: the walk below READS THE CALLER'S OWN PROPERTIES — `cfg`'s
1897
+ // four declared keys by `Object.hasOwn` and by the member reads `encodeConfig` performs — so a `cfg`
1898
+ // carrying an own ACCESSOR is a caller's own body, and a `get` that THROWS is a CALLER'S OWN THROWABLE.
1899
+ // While this read stood INSIDE the `try`, that throwable reached `fail`, which constructs THE STORE'S
1900
+ // SINGLE FORM out of whatever it is handed: `storeCreate({ journalLength: 64, listeners: [],
1901
+ // get constraints() { throw { status: 'AddressMalformed', message: 'FORGED BY THE CALLER' } } })` answered
1902
+ // `{"status":"AddressMalformed","message":"FORGED BY THE CALLER"}` — A CALLER-CHOSEN STATUS CARRIED AS
1903
+ // THIS STORE'S OWN REFUSAL — a thrown `TypeError` answered `{status: undefined, message: '…'}`, a thrown
1904
+ // bare string lost its message entirely, and a thrown `undefined` or `null` made the read itself fault on
1905
+ // `refusal.status`. **THE DEFECT WAS NEVER *"a caller can forge a status"* BUT *"A CALLER'S OWN EXCEPTION
1906
+ // IS CAUGHT AND RE-SHAPED BY A PATH THAT ASSUMES IT IS THE STORE'S."**
1907
+ //
1908
+ // **THE FIX IS THE SCOPE AND NOT A NEW FORM: the walk that READS THE CALLER'S OWN VALUES stands outside
1909
+ // the catch, so the caller's own body's throwable PROPAGATES AS ITSELF — the same value, wearing no member
1910
+ // this unit minted and no status of the store's closed set — while `fail` is reached on this path by THE
1911
+ // ADDON'S OWN REFUSAL ALONE, which is the ONE provenance `§2.5`'s two-member form belongs to.** **AND THE
1912
+ // CLAUSE THIS IMPLEMENTS IS `surface.md §2.5` ITEM 5 (e)'s OWN RULE CARRIED TO THIS SITE** — *"a rejection
1913
+ // is NEVER A RAW HOST ERROR — a `TypeError` … a string thrown, or any host object escaping from the
1914
+ // boundary's own frame is a FINDING at whatever site produced it, not a rejection"* — read with
1915
+ // `kernel-surface.md §2.3` item 1's body-throw clause, which fixes the SAME disposition for the two
1916
+ // caller-side functions this unit registers: **a caller's body's throwable is *"NOT a kernel state and NOT
1917
+ // a store state"* and reaches the caller UNCHANGED.** **NO CODE, NO MEMBER AND NO MESSAGE MOVES ON ANY ARM
1918
+ // THE CALLER'S `cfg` IS LAWFUL: where `encodeConfig` RETURNS, this function's boundary call, its catch and
1919
+ // `fail` are the bytes they were.**
1920
+ const encoded = encodeConfig(cfg);
1819
1921
  let id;
1820
1922
  try {
1821
- id = addon_.storeCreate(encodeConfig(cfg));
1923
+ id = addon_.storeCreate(encoded);
1822
1924
  } catch (refusal) {
1823
1925
  fail(refusal);
1824
1926
  }
@@ -1922,7 +2024,18 @@ export function storeCreate(cfg) {
1922
2024
  const encoded = constraintEntry(element, i);
1923
2025
  if (encoded.bad !== undefined) continue;
1924
2026
  if (typeof element.constraint !== 'function') continue;
1925
- carryConstraint(state, instance, encoded.address.s, encoded.id, element.constraint);
2027
+ // **⟶ AND THIS SITE TAKES THE THREE-STATE REGISTRATION TOO** (`§2.12` item 3's clause of 2026-10-16
2028
+ // at its `A135` (3) mark; `docs/specs/storeroom-native/contract.md §7.3` (b)). **THE BATCH ROUTE AND THE
2029
+ // ADD ROUTE REACH THE SAME `K-1`**, so a batch element the current state violates — with no repair
2030
+ // standing, or with one that does not resolve it — refuses the CONSTRUCTION in this surface's one
2031
+ // failure form, exactly as the ADD route refuses the call. **THE STATE 3 SUCCESS ARM IS THE ONE THAT
2032
+ // MOVES THE STORE**: the repair's edit stands, the registration stands, and the construction returns
2033
+ // its instance with no log crossing (`3-bis` (c)).
2034
+ try {
2035
+ carryConstraint(state, instance, encoded.address.s, encoded.id, element.constraint);
2036
+ } catch (refusal) {
2037
+ registrationCrossing(refusal);
2038
+ }
1926
2039
  }
1927
2040
  }
1928
2041
  // **⟶ AND THE CONSTRUCTION'S OWN ADOPTION ENTERS THE PACKAGE'S HOME MIRROR** (`§2.4` item 7 (b)'s dated
@@ -2504,9 +2617,12 @@ function settleOn(state, record, supplied) {
2504
2617
  // `crossing.md §1.7`): an absent argument, every non-object and every `Proxy` is refused before any
2505
2618
  // marker is read or set.
2506
2619
  if (!supplied || record === null || typeof record !== 'object' || types.isProxy(record)) {
2507
- throw new TypeError(
2620
+ // **AND IT CARRIES `log: []` ON THE RULING'S FLAT READING** (`surface.md §2.5` item 4 names the
2621
+ // registration site's `TypeError` among the arms that carry the empty array; the `status` this form
2622
+ // never had is still not minted — `§2.4` item 9 (b)'s *"its `status` member MUST BE ABSENT"* stands).
2623
+ throw withEmptyLog(new TypeError(
2508
2624
  `settle's argument is ${classSpelling(record)}, and the ordering seam takes a record identity this instance adopted`,
2509
- );
2625
+ ));
2510
2626
  }
2511
2627
  // **⟶ ONE WRITE, ONE ADOPTION, AND TWO IDENTITIES CARRY IT** (`§2.4` item 9's table rows (a) and (b);
2512
2628
  // `PAR-JS-19`: *"the adoption happens AT the first call, and the SECOND call for that identity is the
@@ -2542,9 +2658,9 @@ function settleOn(state, record, supplied) {
2542
2658
  }
2543
2659
  if (!pre) {
2544
2660
  if (record.pending === undefined) {
2545
- throw new TypeError(
2661
+ throw withEmptyLog(new TypeError(
2546
2662
  `settle's argument is ${classSpelling(record)}, and the ordering seam takes a record identity this instance adopted`,
2547
- );
2663
+ ));
2548
2664
  }
2549
2665
  // INSTANT (a): the adoption. The ledger entry stands EMPTY until the verb answers, so the write that
2550
2666
  // drains it is the one write identity this adoption is for.
@@ -2761,18 +2877,79 @@ function constraintPairKey(address, id) {
2761
2877
  /// **THE ONE REFUSAL `§2.12` ITEM 4 DECLARES, TAKEN BEFORE ANY ACT AND LEAVING NOTHING CHANGED** — a JS
2762
2878
  /// `TypeError`, its `status` member ABSENT, no `message` member of this unit's own, **the store's closed
2763
2879
  /// `16`-member set neither minted nor widened, and the store reached by no call this refusal makes.**
2880
+ ///
2881
+ /// **⟶ AND THE `TypeError` CARRIES `log: []` FROM 2026-10-16, AND THIS IS THE ONE PLACE THE FLAT RULING AND
2882
+ /// `A127`'S TWO REFUSAL RULES MEET — SO THE RECONCILIATION IS STATED RATHER THAN LEFT TO THE READER**
2883
+ /// (`surface.md §2.5` item 4, which names *"the three constraint methods' `TypeError`"* among the arms that
2884
+ /// *"all carry `log: []`"*; `§2.12` item 4's replacement clause and `§2.4` item 9 (f)'s rule (ii), which fix
2885
+ /// the class, the absent `status` and the change-nothing atomicity).
2886
+ ///
2887
+ /// **THE TWO RULES ARE NOT IN TENSION AND NEITHER MOVES:** rule (ii) declares the refusal is **a `TypeError`
2888
+ /// CARRYING NO `status` MEMBER** — and it still carries none: the member below is written on the *error
2889
+ /// object* and is `log`, not `status`, and **`'status' in err` is still `false` on every call of this
2890
+ /// method.** The ruling does not re-class the refusal as a store refusal, does not mint a `status`, does not
2891
+ /// reach the store and does not change the call's effects — *"no store call is made, no pair is added,
2892
+ /// enabled or disabled, no journal entry is appended and no code is minted"* stands whole. **THE ONE THING
2893
+ /// THE RULING ADDS IS A MEMBER, AND A `TypeError` IS AN ORDINARY OBJECT: an own enumerable data member can
2894
+ /// be set on it without making it any less an instance of `TypeError` and of nothing else** — which is the
2895
+ /// single question that had to be answered before this could be written, and it is answered by the class,
2896
+ /// not by a judgement here (`Object.keys(new TypeError('x'))` is `[]` and the object is EXTENSIBLE).
2897
+ ///
2898
+ /// **SO THE DECLARED FORM DOES CARRY A THIRD MEMBER, AND THIS IS *NOT* A SPEC CONFLICT: the collision the
2899
+ /// task warned of would be a form that had to become *"a different form"* to hold `log`, and it does not —
2900
+ /// the class (`TypeError`, and of nothing else), the ABSENT `status`, the change-nothing atomicity, the
2901
+ /// caller's own `message` text and the one-`TypeError`-for-both-refusals rule all cross this frame
2902
+ /// untouched. What changes is `Object.keys` on the thrown error, from `[]` to `["log"]`.**
2903
+ ///
2904
+ /// **THE MEMBER IS SET WITH `Object.defineProperty` RATHER THAN BY ASSIGNMENT, AND THE REASON IS THE ONE
2905
+ /// `§2.5` ITEM 9 DECLARES: THE DESCRIPTOR MUST BE ORDINARY — own, enumerable, a data member, writable and
2906
+ /// configurable.** A plain `err.log = []` on an error object achieves exactly that descriptor on V8 and every
2907
+ /// engine this package supports, **but it is written with `defineProperty` HERE because an error's own
2908
+ /// members are not universally ordinary across realms and a runtime that made `Error.prototype.log` an
2909
+ /// accessor would silently divert the write**, and the declaration is cheap where the alternative is a
2910
+ /// silent miss on a member the census reads. **THE PROHIBITION IN `§2.5` ITEM 9 (*"written with an object
2911
+ /// literal, not `Object.defineProperty`"*) BINDS THE STORE'S PLAIN-OBJECT FORM AND ITS `log`, WHICH THIS
2912
+ /// PACKAGE WRITES WITH AN OBJECT LITERAL IN `fail` ABOVE AND IN `constraintCrossing` BELOW; it cannot bind a
2913
+ /// `TypeError`, because a `TypeError` has no object literal and its class is what rule (ii) declares. The
2914
+ /// ITEM'S PURPOSE — that a canonical census sees the member — is the property both routes preserve, and the
2915
+ /// descriptor is asserted explicitly below so the purpose is met member for member.**
2764
2916
  function constraintRefuse(where, value) {
2765
- throw new TypeError(
2917
+ const error = new TypeError(
2766
2918
  `the ${where} of this call is ${classSpelling(value)}, and it is not a value this position's domain `
2767
2919
  + 'admits',
2768
2920
  );
2921
+ throw withEmptyLog(error);
2922
+ }
2923
+
2924
+ /// **THE ONE PLACE `log: []` IS SET ON A REFUSAL THAT IS NOT AN OBJECT LITERAL** — the three constraint
2925
+ /// methods' `TypeError` and nothing else. **`surface.md §2.5` item 4 calls for the EMPTY ARRAY on exactly
2926
+ /// these arms** — *"the EMPTY ARRAY, never an absent member, never `null`, and never a placeholder entry"* —
2927
+ /// and item 9 calls for an **own enumerable data member**, which is the descriptor written here BY HAND so
2928
+ /// that no default, no engine and no realm decides it. **THE ERROR'S PROTOYPE IS NOT TOUCHED**, so
2929
+ /// `err instanceof TypeError` stays `true` and `Object.getPrototypeOf(err)` stays `TypeError.prototype`:
2930
+ /// the member is the error's own and the class is the error's own.
2931
+ ///
2932
+ /// **THE ARRAY IS A FRESH `[]` AT EACH THROW**, so two refusals never alias one list — a shared frozen
2933
+ /// constant would be a value a caller could observe as the *same* array across calls, and `§2.5` item 4
2934
+ /// declares a VALUE (`[]`), not a shared identity.
2935
+ function withEmptyLog(error) {
2936
+ Object.defineProperty(error, 'log', {
2937
+ value: [],
2938
+ writable: true,
2939
+ enumerable: true,
2940
+ configurable: true,
2941
+ });
2942
+ return error;
2769
2943
  }
2770
2944
 
2771
2945
  /// **A POSITION BELOW THE DECLARED ONE — `§2.12` item 4 AND `§2.4` item 9 (f)'s RULE (ii): a SHORT ARITY
2772
2946
  /// TAKES THE SAME ONE `TypeError` AND CHANGES NOTHING.** *"No assertion is made over `message`, and its
2773
2947
  /// absence is the declared reading"* — the member is not one of the three this form is observed by.
2948
+ /// **AND IT IS THE SAME ONE `TypeError` IN THE RULING'S OWN SENSE TOO: the SHORT-ARITY refusal and the
2949
+ /// OUTSIDE-VALUE refusal are ONE form, so `log: []` is set by the same `withEmptyLog` and neither refusal
2950
+ /// gains a `status`** (`surface.md §2.5` item 4's *"the three constraint methods' `TypeError`"*).
2774
2951
  function constraintArity(verb) {
2775
- throw new TypeError(`\`${verb}\` declares two positions, and this call supplied fewer`);
2952
+ throw withEmptyLog(new TypeError(`\`${verb}\` declares two positions, and this call supplied fewer`));
2776
2953
  }
2777
2954
 
2778
2955
  /// **`§2.12` ITEM 4'S TWO CALLER POSITIONS, CLASS FIRST AND IN THEIR DECLARED ORDER** (`PAR-JS-22`–`PAR-JS-24`)
@@ -2812,7 +2989,18 @@ function constraintSite(verb, instance, supplied, pair, constraint) {
2812
2989
  /// opacity is the observable** — *"it has no own enumerable member at all"* — so it is a null-prototype
2813
2990
  /// object and NOT the entry record: every datum above stays the entry's own and never crosses.
2814
2991
  function carryConstraint(state, instance, address, id, constraint) {
2815
- constraintsKernel().register(instance, address, id, constraint);
2992
+ // **⟶ AND THE REGISTRATION IS NOW A THREE-STATE ACT, WHOSE THIRD STATE LANDS AN EDIT** (`§2.12` item 3's
2993
+ // 2026-10-16 clause, read through its `A135` (3) mark; `docs/specs/storeroom-native/contract.md §7.3` (b)
2994
+ // states 1–3 and `3-bis`). `K-1` evaluates the constraint at registration: on states 1 and 3-success it
2995
+ // RETURNS the handle and no log crosses; on states 2 and 3-failure it THROWS a refusal this entry renders
2996
+ // and re-throws in the surface's own single form (`registrationCrossing` below). **THE ENTRY'S OWN
2997
+ // RECORD IS WRITTEN ONLY WHERE THE REGISTRATION STOOD**, so a refused registration leaves this state
2998
+ // exactly as it stood (`§2.12` item 3: *"NO identity is returned and NO element is carried"*).
2999
+ try {
3000
+ constraintsKernel().register(instance, address, id, constraint);
3001
+ } catch (refusal) {
3002
+ registrationCrossing(refusal);
3003
+ }
2816
3004
  const entry = {
2817
3005
  address,
2818
3006
  addressKey: JSON.stringify(address),
@@ -2825,6 +3013,54 @@ function carryConstraint(state, instance, address, id, constraint) {
2825
3013
  return entry;
2826
3014
  }
2827
3015
 
3016
+ /// **THE REGISTRATION REFUSAL'S CROSSING — THE KERNEL HANDS BACK A CODE AND ITS SLOTS, AND THIS ENTRY
3017
+ /// RENDERS THE TEXT THROUGH THE GENERATOR IT ALREADY HOLDS** (`docs/specs/storeroom-native/contract.md
3018
+ /// §8.2`'s 2026-10-16 clause, items 1–5; `surface.md §2.12` item 3's clause of the same date).
3019
+ ///
3020
+ /// **NO MESSAGE IS AUTHORED HERE AND NONE IS AUTHORED IN THE KERNEL.** `DD-52` forbids a code's message
3021
+ /// from a second source, so the sentence is produced by the store's own generator — reached through
3022
+ /// `addon_.errorMessage(code, subject[, container])`, the very path `boundaryReject` already takes — from
3023
+ /// the `§8.2` row's own SLOTS: `<CONTAINER>` the pair's own list name `constraints`, and `<SEGMENT>` the
3024
+ /// added pair's `address` spelling joined by `/`. **THE FIXED PHRASE IS THE ROW'S AND IS RENDERED VERBATIM**
3025
+ /// (`§8.2` clause 3), and no per-instant template stands.
3026
+ ///
3027
+ /// **⟶ AND THE 2026-10-17 FORGERY FIX SURVIVES INTACT, WHICH IS THIS FRAME'S HIGHEST-RISK OBLIGATION.** The
3028
+ /// classification is **IDENTITY, NOT SHAPE** — the kernel's own mark under the `Symbol.for` key both sides
3029
+ /// spell (`KERNEL_REFUSAL` above) and nothing a caller can spell — so:
3030
+ /// * **A KERNEL-BUILT REFUSAL** (its `status` a string, its slot members present) is rendered and
3031
+ /// re-thrown in the surface's single two-member-plus-`log` form below;
3032
+ /// * **EVERYTHING ELSE IS THE CALLER'S AND CROSSES AS ITSELF** — a forged two-member object, a forged
3033
+ /// three-member object, a `TypeError`, a bare string and `undefined` all reach the caller as the very
3034
+ /// value that was thrown, `caught === thrown`, and none of them reaches the generator.
3035
+ ///
3036
+ /// **AND A BODY'S OWN THROW IS THAT SECOND ARM AND NOT A THIRD**: `fail-surface.md §1.1` item 5 leaves a
3037
+ /// throwing constraint or repair body *"untouched and unconverted"*, and it carries no mark, so it is
3038
+ /// re-thrown by the one line above the render.
3039
+ function registrationCrossing(refusal) {
3040
+ if (isKernelBuiltRefusal(refusal) === false) throw refusal;
3041
+ const addon_ = withAddon();
3042
+ // THE SLOTS THE KERNEL HANDS BACK ARE THE `§8.2` ROW'S OWN, and the generator's own three-argument call
3043
+ // fills `<CONTAINER>` beside `<SEGMENT>`. Where an artefact loaded but does not carry the generator, the
3044
+ // declared absent/failed-addon state is the answer, exactly as `boundaryReject` takes it — and where a
3045
+ // marked value carries no usable slots the handler below answers it, so no unsubstituted placeholder can
3046
+ // reach a caller from this frame.
3047
+ const usable = typeof addon_.errorMessage === 'function'
3048
+ && typeof refusal.status === 'string'
3049
+ && typeof refusal.segment === 'string';
3050
+ if (usable === false) throw refusal;
3051
+ const generated = addon_.errorMessage(refusal.status, refusal.segment, refusal.container);
3052
+ // **THE FORM IS THIS SURFACE'S ONE FORM** (`§2.5` items 3–4, whose `log` is PRESENT and never absent):
3053
+ // `{status, message, log}`, the `status` the STORE's `ConstraintListInvalid`, the `message` the STORE'S
3054
+ // OWN GENERATED SENTENCE, and the `log` the synthetic attempt's log where a repair was attempted and `[]`
3055
+ // where none was. **NO `KC` TOKEN CROSSES** (`A120` (2); `§2.12` item 3 item 2): the synthetic attempt's
3056
+ // terminal token stays in the kernel and reaches no caller.
3057
+ throw {
3058
+ status: refusal.status,
3059
+ message: generated,
3060
+ log: refusalLog(refusal.log),
3061
+ };
3062
+ }
3063
+
2828
3064
  /// **THE DISABLED PAIR'S STANDING ELEMENT** — a function that PASSES (`kernel-surface.md §2.3` item 1:
2829
3065
  /// `true` is the only pass value). **THE ELEMENT IS PARKED AND NEVER WITHDRAWN**: `constraintOn` re-registers
2830
3066
  /// `entry.fn`, so *"it is the element the entry carried at that pair — never a second constraint and never a
@@ -2837,12 +3073,13 @@ function constraintParked() {
2837
3073
  /// `PAR-JS-24`'s second declared answer: at EITHER toggle, in EITHER direction, an OUTSIDE VALUE taking
2838
3074
  /// item 4's refusal, ONE THROWN `TypeError`, THE ENTRY NOT WIDENED.** It is NOT a third population route:
2839
3075
  /// were the entry widened with the function the refused call carried, a pair would stand ENABLED WITH NO
2840
- /// FUNCTION — a state no clause of that directory declares.
3076
+ /// FUNCTION — a state no clause of that directory declares. **AND IT IS THAT SAME ONE `TypeError`, carrying
3077
+ /// `log: []` on the ruling's flat reading and no `status` on rule (ii)'s** (`surface.md §2.5` item 4).
2841
3078
  function constraintUncarried(verb, pair) {
2842
- throw new TypeError(
3079
+ throw withEmptyLog(new TypeError(
2843
3080
  `the pair at the ${ARGUMENT_POSITION_FIRST} of \`${verb}\` carries no constraint in this instance, and `
2844
3081
  + 'a toggle names a pair the entry carries',
2845
- );
3082
+ ));
2846
3083
  }
2847
3084
 
2848
3085
  /**
@@ -2862,7 +3099,16 @@ function addConstraint(instance, n, pair, constraint) {
2862
3099
  if (held === undefined) {
2863
3100
  return carryConstraint(site.state, instance, site.address, site.id, constraint).identity;
2864
3101
  }
2865
- constraintsKernel().register(instance, site.address, site.id, constraint);
3102
+ // **THE OVERWRITE ARM TAKES THE SAME THREE-STATE REGISTRATION** (`§2.12` item 3's clause of 2026-10-16
3103
+ // read at its `A135` (3) mark): a second ADD at a held pair registers the supplied function through `K-1`
3104
+ // exactly as the fresh arm does, so a registration the store REFUSES refuses THIS call too — and the held
3105
+ // element is left EXACTLY AS IT STOOD, because the entry's own record is written only after the
3106
+ // registration returns (`§2.12` item 3: *"NO identity is returned and NO element is carried"*).
3107
+ try {
3108
+ constraintsKernel().register(instance, site.address, site.id, constraint);
3109
+ } catch (refusal) {
3110
+ registrationCrossing(refusal);
3111
+ }
2866
3112
  held.fn = constraint;
2867
3113
  held.enabled = true;
2868
3114
  return held.identity;
@@ -2889,7 +3135,16 @@ function constraintToggle(enabled, instance, n, pair, constraint) {
2889
3135
  const entry = site.state.constraints.get(constraintPairKey(site.address, site.id));
2890
3136
  if (entry === undefined) constraintUncarried(verb, pair);
2891
3137
  if (entry.enabled !== enabled) {
2892
- constraintsKernel().register(instance, site.address, site.id, enabled ? entry.fn : constraintParked);
3138
+ // **THE ENABLE HALF RE-REGISTERS THE PAIR'S OWN FUNCTION, SO IT TAKES THE SAME THREE-STATE REGISTRATION
3139
+ // AS EVERY OTHER REGISTRATION SITE** (`§2.12` item 3's clause of 2026-10-16 at its `A135` (3) mark;
3140
+ // `docs/specs/storeroom-native/contract.md §7.3` (b)). A registration the store REFUSES refuses THIS
3141
+ // call in the same one form, and the pair's own `enabled` member is UNMOVED — written only after the
3142
+ // registration returns — so a refused toggle leaves the pair exactly as it stood.
3143
+ try {
3144
+ constraintsKernel().register(instance, site.address, site.id, enabled ? entry.fn : constraintParked);
3145
+ } catch (refusal) {
3146
+ registrationCrossing(refusal);
3147
+ }
2893
3148
  entry.enabled = enabled;
2894
3149
  }
2895
3150
  return undefined;
@@ -2941,19 +3196,155 @@ function constraintWrite(state, instance, address, tier, value) {
2941
3196
  }
2942
3197
 
2943
3198
  /// **THE FAIL ARM'S CROSSING — `A120` (2): THE ENTRY CARRIES THE KERNEL'S TOKEN, THE THROW KEEPS THE
2944
- /// STORE'S.** `§2.12` item 1's read-through clause fixes what crosses here: **A PLAIN OBJECT OF EXACTLY THE
2945
- /// TWO MEMBERS `status` AND `message`, `status` A STRING DRAWN FROM THE STORE'S CLOSED `16`-MEMBER SET, the
2946
- /// kernel's third member `log` ABSENT AND UNREACHABLE.** The member `status` carries is the store's
2947
- /// `FileCommitFailed`, because no caller-side status can carry a `KC` token and a constraint-refused write
2948
- /// is a commit that did not stand. **A STORE VERB'S OWN REFUSAL CROSSES VERBATIM AND UNCONVERTED** (`§1.2`).
3199
+ /// STORE'S — AND THE FORM CROSSES AT THREE MEMBERS FROM 2026-10-16** (`surface.md §2.5`'s clause of that
3200
+ /// date, items 3–4 and 10 (i)–(iii); `§2.12` item 1's mark of the same date).
3201
+ ///
3202
+ /// **WHAT MOVES IS THE REACHABILITY OF `log` AND NOTHING ELSE.** The member `status` carries is still the
3203
+ /// store's `FileCommitFailed`, because no caller-side status can carry a `KC` token and a
3204
+ /// constraint-refused write is a commit that did not stand; **the kernel token does NOT enter `status`**
3205
+ /// (`A120` (2)'s rule survives whole). **A STORE VERB'S OWN REFUSAL CROSSES VERBATIM AND UNCONVERTED**
3206
+ /// (`fail-surface.md §1.2`): its `status` and its `message` are carried BYTE-FOR-BYTE, never re-mapped and
3207
+ /// never re-spelled, and `log` is ATTACHED BESIDE them as an own member — *"nothing is converted, and a
3208
+ /// member is added"* (`§2.5` item 10 (ii)).
3209
+ ///
3210
+ /// **THE TWO ARMS, EACH AT ITS OWN FORM:**
3211
+ /// * **A `KC`-TOKEN REFUSAL — THE KERNEL'S OWN PASS PRODUCED IT.** Its `{status, message, log}` is the
3212
+ /// KERNEL'S OWN three-member form (`docs/specs/storeroom-constraints/fail-surface.md §1.1`, whose member
3213
+ /// set is the same three), and it would cross UNCHANGED were it not that `status` must carry the store's
3214
+ /// `FileCommitFailed` on this surface: **the `log` it carries is the attempt's, VERBATIM, and it crosses
3215
+ /// with the store-side `status` in its place.**
3216
+ /// * **A STORE VERB'S OWN REFUSAL.** Its `status` and `message` cross verbatim and `log` is attached beside
3217
+ /// them — the attempt's log where this write's own attempt holds one, and `[]` where it does not (a `K-2`
3218
+ /// the store refused opened no attempt, so there is no attempt at all — `§2.5` item 4).
3219
+ ///
3220
+ /// **AND THE TIMING TRAP IS HONOURED, WHICH IS THE WHOLE OF ITEM 10 (iii): `log` IS TAKEN BEFORE THE
3221
+ /// ATTEMPT IS DISPOSED OF, NOT AFTER.** The kernel's terminal act has already run when this frame is
3222
+ /// reached (its `refuse` was thrown WITH the log in hand, `constraint-kernel.mjs`'s `refuse`), so the list
3223
+ /// read here is the list AS IT STOOD WHEN THE REFUSAL WAS BUILT — the failure arm's `outcome` entry
3224
+ /// included — and it is read OFF THE THROWN VALUE AND NEVER OFF A LATER READ: the registry entry is gone
3225
+ /// and a reader that reached for the attempt afterwards would reach nothing.
3226
+ ///
3227
+ /// **⟶ THE FORGERY DISCRIMINATOR, RE-EXAMINED AND REPLACED 2026-10-16, BECAUSE THE RULING MADE THE OLD ONE
3228
+ /// UNSAFE — THIS IS THE HIGH-RISK EDIT AND IT IS NAMED WITH WHAT IT WAS AND WHAT IT IS.**
3229
+ ///
3230
+ /// **WHAT IT WAS.** The previous pass fixed a broken forgery guard by discriminating on **`log`'s
3231
+ /// PRESENCE**: *a value carrying a `log` was the kernel's, and a value carrying none was the caller's.*
3232
+ /// That was sound only while the KERNEL'S OWN form was the only three-member form in the system.
3233
+ ///
3234
+ /// **WHY IT NO LONGER SUFFICES.** `surface.md §2.5` item 4 now declares **`log` flat on EVERY failure this
3235
+ /// surface throws** — so every surface-produced failure carries one, **and so does a CALLER'S forged object
3236
+ /// that happens to carry a `log` member.** A caller's constraint body may throw
3237
+ /// `{status: 'ValueNotAdmitted', message: 'FORGED BY THE CALLER', log: []}` — a plain object it authored,
3238
+ /// carrying the member the old test looked for — **and under the old test that object was RE-WRAPPED into a
3239
+ /// fresh three-member object, so `caught === thrown` was `false` for a value the caller threw.** Measured on
3240
+ /// the tree before this edit: `forged {status,message,log} => caught===thrown: false`. **A caller's own
3241
+ /// throwable must surface AS ITSELF** (`fail-surface.md §1.1` item 5 — the body's exception *"propagates out
3242
+ /// of the kernel's own invocation, untouched and unconverted"*; `kernel-surface.md §2.3` item 1 — a body's
3243
+ /// throwable *"is NOT a kernel state and NOT a store state"*), **so the test had to stop reading a member
3244
+ /// the caller can forge.**
3245
+ ///
3246
+ /// **WHAT REPLACED IT — IDENTITY, NOT SHAPE.** The kernel's own refusals are **built by the kernel**, and
3247
+ /// every one of them is thrown from `constraint-kernel.mjs`'s single `refuse` frame. The entry therefore
3248
+ /// **MARKS WHAT THE KERNEL BUILT**, at the one place the kernel's values enter this entry, **with a
3249
+ /// module-private `WeakSet`** — `kernelRefusals` above — **and this frame asks whether the handed value IS
3250
+ /// ONE OF THOSE VALUES, never whether it LOOKS LIKE one.** A caller cannot forge membership of a set it
3251
+ /// cannot reach, so:
3252
+ /// * a `KC`-token value the kernel built → **the kernel's arm**, and `FileCommitFailed` crossings below;
3253
+ /// * a store verb's own refusal (built by the addon, carrying the store's code) → the store's arm below;
3254
+ /// * **EVERYTHING ELSE IS THE CALLER'S AND CROSSES AS ITSELF** — a forged three-member object, a forged
3255
+ /// two-member object, a `TypeError`, a bare string, `undefined` — `caught === thrown` on all of them.
3256
+ ///
3257
+ /// **THE MARK IS SET WHERE THE KERNEL'S FAILURE IS FIRST SEEN** — at the two `catch` frames in
3258
+ /// `constraintWrite` above, which are the only places a kernel-thrown value reaches this entry — and **NOT
3259
+ /// by a test over members, which is the whole defect being repaired.** **IT IS A `WeakSet` AND NOT A MEMBER
3260
+ /// ON THE VALUE**: no member is added to the kernel's own form (`fail-surface.md §1.1`'s member set stays the
3261
+ /// three), nothing is mutated, nothing is frozen, and the mark is invisible to every census — while a value
3262
+ /// that is not an object (a string, `undefined`) is simply never in the set and needs no special case, since
3263
+ /// `WeakSet.has` on a primitive is `false` rather than a throw.
3264
+ /// **THE KERNEL'S OWN REFUSAL-CLASS QUESTION, AND WHY THE ENTRY ASKS THE KERNEL IT RATHER THAN READING A
3265
+ /// MEMBER** — the discriminator that replaced `log`'s presence, and the reason a `WeakSet` local to this
3266
+ /// entry will not do.
3267
+ ///
3268
+ /// **THE MARK CANNOT LIVE HERE, AND THAT WAS MEASURED RATHER THAN REASONED:** a `WeakSet` populated from the
3269
+ /// two `catch` frames in `constraintWrite` marks **EVERY** value leaving the kernel's frames — **a caller's
3270
+ /// constraint BODY throws from inside `runAttempt` too**, so the body's own throwable passes the same frame
3271
+ /// and is marked alongside the kernel's. On the tree with the `WeakSet` in place, all three of
3272
+ /// `forged {status,message}`, `forged {status,message,log}` and `TypeError` answered `caught === thrown:
3273
+ /// false`: **the mark was set by the frame and not by the author of the value.** A mark is only worth
3274
+ /// anything if the thing that SETS it is the thing that BUILT the value, and for a kernel refusal that thing
3275
+ /// is `constraint-kernel.mjs`'s own `refuse`.
3276
+ ///
3277
+ /// **SO THE KERNEL DECLARES IT, AT ITS ONE THROW SITE, UNDER A `Symbol.for` KEY BOTH SIDES SPELL** — exactly
3278
+ /// the pattern `SETTLED_ON_THE_PASSING_ARM` and `SAVE_FAILED_AT_THE_TERMINAL_ARM` already use across this
3279
+ /// same boundary (`constraint-kernel.mjs`'s `KERNEL_REFUSAL`): the entry imports no kernel at load and the
3280
+ /// kernel imports no entry, and **a symbol key is invisible to `Object.keys`**, so the thrown form's readable
3281
+ /// member set stays the three `§2.5` items 3–4 declare (`§2.5` item 9's census reads `["log","message",
3282
+ /// "status"]` and no fourth). **A CALLER'S BODY CANNOT SET IT**: the mark is written in a frame no caller
3283
+ /// reaches, and it is not a member a caller would think to spell.
3284
+ ///
3285
+ /// **AND A KERNEL THAT DID NOT CARRY THE DECLARATION ANSWERS `false`** — every value is then the caller's and
3286
+ /// surfaces as itself, which is the safe direction: a refusal crossed unconverted is the declared form once
3287
+ /// the surface stops re-wrapping it, while a caller's value crossed converted is the FINDING this whole
3288
+ /// discriminator exists to prevent.
3289
+
3290
+ /// **THE SAME `Symbol.for` KEY THE KERNEL WRITES, SPELLED HERE SO THE ENTRY IMPORTS NO KERNEL AND THE KERNEL
3291
+ /// IMPORTS NO ENTRY** — the pattern `SETTLED_ON_THE_PASSING_ARM` and `SAVE_FAILED_AT_THE_TERMINAL_ARM`
3292
+ /// already cross this boundary by (`constraint-kernel.mjs`'s `KERNEL_REFUSAL`).
3293
+ ///
3294
+ /// **IT IS A SYMBOL AND NOT A KERNEL FUNCTION, AND THE REASON IS A SPEC COUNT: `kernel-surface.md §1` item 2
3295
+ /// declares that module's export set as EXACTLY the five `K-1`–`K-5` items — *"no sixth name"* — so a
3296
+ /// predicate exported from the kernel to serve this entry would be a FINDING.** The fact travels on the
3297
+ /// VALUE, under a key both sides spell, and the kernel's namespace is untouched.
3298
+ ///
3299
+ /// **THE QUESTION IS ANSWERED WITHOUT REACHING THE KERNEL AT ALL**, which is the shape `WeakSet.has` gave
3300
+ /// for free and is what lets this entry keep loading where nothing is staged beside it: no `require` of
3301
+ /// `./src/` is triggered by a failure's own classification.
3302
+ const KERNEL_REFUSAL = Symbol.for('provident-storeroom.kernel-refusal');
3303
+
3304
+ /// **WHETHER THE HANDED VALUE IS A REFUSAL THE KERNEL ITSELF BUILT** — the discriminator that replaced
3305
+ /// `log`'s presence, answered by the mark the kernel's one `refuse` frame sets and by nothing a caller can
3306
+ /// spell. **A NON-OBJECT IS `false`** without a member read, and **a value the kernel never built is
3307
+ /// `false`** whatever members it carries.
3308
+ function isKernelBuiltRefusal(value) {
3309
+ return value !== null && typeof value === 'object' && value[KERNEL_REFUSAL] === true;
3310
+ }
3311
+
2949
3312
  function constraintCrossing(refusal) {
2950
- const status = refusal !== null && typeof refusal === 'object' ? refusal.status : undefined;
2951
- if (typeof status !== 'string' || KC_TOKENS.includes(status) === false) throw refusal;
3313
+ const isObject = refusal !== null && typeof refusal === 'object';
3314
+ const status = isObject ? refusal.status : undefined;
3315
+ // **THE CALLER'S OWN VALUE CROSSES AS ITSELF, FIRST AND UNCONDITIONALLY.** The test is IDENTITY against
3316
+ // the kernel's marked set (above) and NOT any member's presence: a caller's forged `log`, a forged
3317
+ // `status` spelling and a forged two-member object are all its own, and `caught === thrown` holds for
3318
+ // each (`fail-surface.md §1.1` item 5). A value that is not an object at all is never the kernel's either.
3319
+ if (!isObject || isKernelBuiltRefusal(refusal) === false) throw refusal;
3320
+ // THE LOG IS THE THROWN VALUE'S OWN `log` MEMBER — the same list either arm carries — and `[]` where the
3321
+ // value carries none (`§2.5` item 4: never absent, never `null`, never a non-array; a non-array here is a
3322
+ // finding at the site that produced it and is answered with the empty array rather than a shape).
3323
+ // **AND IT IS TAKEN HERE, BEFORE THE ATTEMPT IS DISPOSED OF** — item 10 (iii)'s timing trap: the list is
3324
+ // READ OFF THE THROWN VALUE, which the kernel built with the log in hand, and never off a later read.
3325
+ const log = Array.isArray(refusal.log) ? refusal.log : [];
3326
+ // **A MARKED VALUE WHOSE `status` IS NOT A `KC` TOKEN IS THE STORE VERB'S OWN REFUSAL CROSSING BACK
3327
+ // THROUGH THE KERNEL'S OWN LEG** (`constraint-kernel.mjs`'s `attempt.throwState` carries the store's code
3328
+ // at the repair arm): its `status` and `message` cross VERBATIM and `log` is attached BESIDE them —
3329
+ // *"nothing is converted, and a member is added"* (`§2.5` item 10 (ii)).
3330
+ if (typeof status !== 'string' || KC_TOKENS.includes(status) === false) {
3331
+ throw {
3332
+ status: refusal.status,
3333
+ message: refusal.message,
3334
+ log: refusalLog(log),
3335
+ };
3336
+ }
3337
+ // **THE KERNEL'S OWN `KC` REFUSAL.** Its `{status, message, log}` is the KERNEL'S OWN three-member form
3338
+ // (`docs/specs/storeroom-constraints/fail-surface.md §1.1`), and it crosses with the STORE's
3339
+ // `FileCommitFailed` in `status` because no caller-side status can carry a `KC` token and a
3340
+ // constraint-refused write is a commit that did not stand: **the kernel token does NOT enter `status`, and
3341
+ // the `log` it carries is the attempt's, VERBATIM.**
2952
3342
  throw {
2953
3343
  status: 'FileCommitFailed',
2954
3344
  message: typeof refusal.message === 'string'
2955
3345
  ? refusal.message
2956
3346
  : 'the write was refused by a constraint of this attempt',
3347
+ log: refusalLog(log),
2957
3348
  };
2958
3349
  }
2959
3350
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "provident-storeroom",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "U-STOREROOM-PUBLISH: the published Node ESM binding for the native Rust store of Provident-Storeroom — the entry resolves the scoped per-target platform package first, the checkout's own module-relative addon second, and answers the store's single declared absent-addon form when neither loads",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0",
@@ -38,11 +38,11 @@
38
38
  "src/constraint-kernel.mjs"
39
39
  ],
40
40
  "optionalDependencies": {
41
- "@auspicion/provident-storeroom-js-linux-x64-gnu": "0.3.1",
42
- "@auspicion/provident-storeroom-js-linux-arm64-gnu": "0.3.1",
43
- "@auspicion/provident-storeroom-js-darwin-x64": "0.3.1",
44
- "@auspicion/provident-storeroom-js-darwin-arm64": "0.3.1",
45
- "@auspicion/provident-storeroom-js-win32-x64-msvc": "0.3.1"
41
+ "@auspicion/provident-storeroom-js-linux-x64-gnu": "0.4.0",
42
+ "@auspicion/provident-storeroom-js-linux-arm64-gnu": "0.4.0",
43
+ "@auspicion/provident-storeroom-js-darwin-x64": "0.4.0",
44
+ "@auspicion/provident-storeroom-js-darwin-arm64": "0.4.0",
45
+ "@auspicion/provident-storeroom-js-win32-x64-msvc": "0.4.0"
46
46
  },
47
47
  "publishConfig": {
48
48
  "access": "public"
@@ -131,8 +131,27 @@ const SETTLED_ON_THE_PASSING_ARM = Symbol.for('provident-storeroom.settled-on-th
131
131
  const SAVE_FAILED_AT_THE_TERMINAL_ARM = Symbol.for('provident-storeroom.save-failed-at-the-terminal-arm');
132
132
 
133
133
  /** `fail-surface.md §1.1` — ONE THROWN PLAIN OBJECT, EXACTLY THREE MEMBERS, NEVER AN `Error`. */
134
+ const KERNEL_REFUSAL = Symbol.for('provident-storeroom.kernel-refusal');
134
135
  function refuse(status, message, log) {
135
- throw { status, message, log: log === undefined ? [] : log };
136
+ throw {
137
+ status,
138
+ message,
139
+ log: log === undefined ? [] : log,
140
+ [KERNEL_REFUSAL]: true,
141
+ };
142
+ }
143
+
144
+ /// **WHETHER A VALUE IS A REFUSAL THIS KERNEL BUILT** — the entry's crossing and this kernel's own repair
145
+ /// arm both ask this and nothing else.
146
+ ///
147
+ /// **IT IS NOT AN EXPORT, AND THE REASON IS THE SPEC'S OWN CLOSED COUNT:** `kernel-surface.md §1` item 2
148
+ /// declares the module's export set as **EXACTLY the five `K-1`–`K-5` items** — *"the kernel exports no
149
+ /// route, no addon handle and no sixth name"* — so a predicate exported from here would be a SIXTH NAME and
150
+ /// a FINDING. **The mark is therefore read through the `Symbol.for` key itself, which both sides spell**
151
+ /// (`KERNEL_REFUSAL` above), and the fact travels on the VALUE rather than in the module's namespace —
152
+ /// exactly as `SETTLED_ON_THE_PASSING_ARM` and `SAVE_FAILED_AT_THE_TERMINAL_ARM` already travel.
153
+ function isKernelRefusal(value) {
154
+ return value !== null && typeof value === 'object' && value[KERNEL_REFUSAL] === true;
136
155
  }
137
156
 
138
157
  // ---------------------------------------------------------------------------------------------
@@ -380,9 +399,364 @@ export function register(store, address, id, constraint) {
380
399
  } else {
381
400
  standing.constraint = constraint;
382
401
  }
402
+
403
+
404
+ // ═══════════════════════════════════════════════════════════════════════════════════════════════
405
+ // THE THIRD STEP — THE REGISTRATION-TIME EVALUATION (`docs/specs/storeroom-native/contract.md §7.3`
406
+ // (b) states 1–3 and its `3-bis` clause of 2026-10-16; `kernel-surface.md §2.1` item 1's third step).
407
+ // ═══════════════════════════════════════════════════════════════════════════════════════════════
408
+ //
409
+ // **WHAT THIS STEP OWES, IN THE RULING'S OWN TERMS: after channels (i) and (ii) are passed and the pair
410
+ // stands in the registry, the kernel EVALUATES THAT ONE CONSTRAINT AGAINST THE STORE'S CURRENT STATE,
411
+ // ONCE, BEFORE THE HANDLE IS RETURNED.** The scope is THAT ONE PAIR and no other: no pass is opened over
412
+ // the registry and no other registered pair is re-evaluated.
413
+ //
414
+ // **⟶ THE THREE STATES, EACH ANSWERED HERE AND AT NO OTHER SITE:**
415
+ // (i) the state PASSES → the call returns the handle exactly as before, and nothing else happened;
416
+ // (ii) it VIOLATES and NO repair is registered → the registration is REFUSED;
417
+ // (iii) it VIOLATES and a repair IS registered → THE REPAIR IS ATTEMPTED on the synthetic attempt
418
+ // `3-bis` (a) declares, and its outcome answers the call as (i) or as (ii).
419
+ //
420
+ // **AND WHAT THE KERNEL HANDS THE SURFACE IS A CODE AND ITS SLOTS, NEVER A SENTENCE.** This module owns
421
+ // no message generator, and `kernel-surface.md §1` item 2 closes its surface at the FIVE `K-1`…`K-5`
422
+ // items with no sixth name — so it imports none, is handed none, and declares no channel to one. The
423
+ // refusal it throws carries `status` (the STORE's member, `A120` (2)) and the `§8.2` row's own slot
424
+ // VALUES, and the surface renders the text through the generator it already holds. **NO `KC` TOKEN IS
425
+ // MINTED:** the synthetic attempt's own terminal token stays inside this module (`registrationRefusal`).
426
+ const refused = registrationEvaluation(kernel, store, address, id, constraint);
427
+ if (refused !== null) {
428
+ // **A REFUSED REGISTRATION LEAVES THE REGISTRY EXACTLY AS IT STOOD** (`§2.1` item 1's sentence, whose
429
+ // regulatory force reaches this third refusing act — `§7.3` (b) state 2's own reading of it): the pair
430
+ // row this call wrote is withdrawn, with its handle and its place in the address's order list.
431
+ withdrawRegistration(kernel, address, id, standing === undefined, home);
432
+ throw refused;
433
+ }
434
+ return home;
435
+ }
436
+
437
+ /**
438
+ * **WITHDRAWING THE REGISTRY ROW A REFUSED REGISTRATION WROTE** — `kernel-surface.md §2.1` item 1: *"a
439
+ * refused registration leaves the registry exactly as it stood"*, read at `docs/specs/storeroom-native/
440
+ * contract.md §7.3` (b) state 2 by that item's own clause (*"the sentence's `2` counts `KC` CHANNELS and
441
+ * the registration-time refusal is a THIRD REFUSING ACT carrying no `KC` token, so the sentence's FIGURE IS
442
+ * UNMOVED while its regulatory force (no entry on a refusal) reaches this third act"*).
443
+ *
444
+ * **WHAT IT UNDOES IS THIS CALL'S OWN WRITE AND NOTHING ELSE**, which is why the prior-standing fact is
445
+ * passed in: on the FRESH arm the pair row, its handle and its address-list entry all go; on the
446
+ * REPLACEMENT arm (a second `register` under a pair that already stood) the row's own POSITION and handle
447
+ * are left exactly as they were — the pair's idempotence rule (`CC-7`) puts the replaced registration's
448
+ * position back by never moving it.
449
+ */
450
+ function withdrawRegistration(kernel, address, id, fresh, home) {
451
+ if (!fresh) return;
452
+ const key = pairKey(address, id);
453
+ kernel.pairs.delete(key);
454
+ kernel.handles.delete(key);
455
+ const token = addressToken(address);
456
+ const list = kernel.byAddress.get(token);
457
+ if (list !== undefined) {
458
+ const at = list.indexOf(key);
459
+ if (at >= 0) list.splice(at, 1);
460
+ if (list.length === 0) kernel.byAddress.delete(token);
461
+ }
462
+ // THE ADDRESS'S HOME ENTRY STANDS: it was minted by the store's own `listen`, which this act has already
463
+ // performed, and no clause of this unit declares a kernel-side withdrawal of it (`§2.1` item 1: *"nothing
464
+ // withdraws a constraint's store registration"* — `unlisten` is the app's own verb and never this one's).
383
465
  return home;
384
466
  }
385
467
 
468
+ /**
469
+ * **THE REGISTRATION-TIME EVALUATION, AT ITS ONE SITE** (`docs/specs/storeroom-native/contract.md §7.3`
470
+ * (b) and its `3-bis` clause of 2026-10-16; `kernel-surface.md §2.1` item 1's third step and `§2.3` item
471
+ * 1's clause of 2026-10-17). It answers `null` on state 1 and on state 3's passing arm, and **the refusal
472
+ * to throw** on state 2 and on state 3's failing one.
473
+ *
474
+ * **THE EVALUATION'S CONTEXT IS `§2.3` ITEM 1'S CLAUSE OF 2026-10-17, MEMBER FOR MEMBER, AND IT IS THE
475
+ * SAME FIVE MEMBERS AS AT A LANDING** — `address` the pair's own; `tier` ABSENT, spelled `null`; `value`
476
+ * THE STORE'S CURRENT VALUE AT THE PAIR'S ADDRESS, READ AND NOT LANDED; `attempt` the synthetic attempt's
477
+ * `AttemptRef` on state 3 and `null` on states 1/2; `op` ABSENT, spelled `null`. **A SIXTH MEMBER IS
478
+ * REFUSED BY NAME** (`5 + 1 = 6` is refused at that item's (6)), and both `null`s are THAT CLAUSE's own
479
+ * spellings of an absence inside a closed record, taken from the `RollbackStep.checkpoint` precedent, and
480
+ * are not tokens minted here.
481
+ *
482
+ * **THE `value` IS OBTAINED BY THE STORE'S OWN `read` AT THE PAIR'S ADDRESS WITH THE TIER ARGUMENT
483
+ * OMITTED** — the zero-tier call — **and where that read REFUSES `AddressNotFound` the member carries
484
+ * `undefined`**, which is that clause's (3) (e) arm. **NO `null` IS MINTED FOR IT** (`DD-12` forbids a
485
+ * READ answering one) and no `AddressNotFound` code is put in a `Value` slot: the fresh-pair outcome is
486
+ * the CALLER'S OWN BODY's answer to absence, and no clause decides which a given body is.
487
+ *
488
+ * **⟶ AND THE BODY'S OWN THROW IS NOT CONVERTED HERE.** A throw out of the constraint body at this instant
489
+ * SURFACES AS ITSELF (`fail-surface.md §1.1` item 5, at `kernel-surface.md §2.3` item 1's clause of
490
+ * 2026-10-17): not re-shaped into this module's form, not wrapped, and carrying no `KC` token. So the
491
+ * invocation below is NOT wrapped — a throwing body reaches the caller as the very value it threw.
492
+ */
493
+ function registrationEvaluation(kernel, store, address, id, constraint) {
494
+ const outcome = constraint(registrationContext(store, address, null));
495
+ // THE OUTCOME IS `PAR-C-5`'S CLOSED THREE-ARM SET, read as the landing pass reads it: `true` is the pass
496
+ // arm; an object carrying `message` is the violation arm (its `repair`, where present, the repair the
497
+ // caller registered); a value outside the three arms is READ AS the `{message}` arm (`VA-11`) and never as
498
+ // an arm of its own. **A REPAIR THE OUTCOME DOES NOT CARRY IS NO REPAIR REGISTERED FOR THE PAIR.**
499
+ if (outcome === true) return null;
500
+ const repair = outcome !== null && typeof outcome === 'object' && 'message' in outcome
501
+ && 'repair' in outcome && typeof outcome.repair === 'function'
502
+ ? outcome.repair
503
+ : null;
504
+ // STATE 2 — THE STATE VIOLATES IT AND NO REPAIR IS REGISTERED. Nothing is attempted and no attempt is
505
+ // opened; the refusal carries the store's code and the row's own slots.
506
+ if (repair === null) return registrationRefusal(address, id, []);
507
+ // STATE 3 — THE REPAIR IS ATTEMPTED, on the synthetic attempt `3-bis` (a) declares.
508
+ return registrationAttempt(kernel, store, { address, id, repair });
509
+ }
510
+
511
+ /// **THE FIVE-MEMBER EVALUATION CONTEXT** (`kernel-surface.md §2.3` item 1's clause of 2026-10-17), built
512
+ /// at ONE site so states 1, 2 and 3 hand the caller's body the SAME record and only `attempt` moves:
513
+ /// `null` on states 1 and 2, the synthetic attempt's `AttemptRef` on state 3.
514
+ function registrationContext(store, address, attemptRef) {
515
+ return {
516
+ address: address.slice(),
517
+ // `tier` — ABSENT, and `op` — ABSENT: the two members carrying the landing's own absence, spelled
518
+ // `null` on that clause's (2) and (5).
519
+ tier: null,
520
+ // `value` — READ, not landed, and `undefined` at an address holding nothing (that clause's (3) (e)).
521
+ value: readCurrent(store, address),
522
+ attempt: attemptRef,
523
+ op: null,
524
+ };
525
+ }
526
+
527
+ /// The store's current value at an address, read NOT landed: the zero-tier call whose tier argument is
528
+ /// OMITTED, and `undefined` where that read refuses.
529
+ function readCurrent(store, address) {
530
+ try {
531
+ return store.read(address);
532
+ } catch (refused) {
533
+ return undefined;
534
+ }
535
+ }
536
+
537
+ /**
538
+ * **THE SIX-MEMBER `RepairContext` THE REPAIR IS HANDED AT REGISTRATION** (`kernel-surface.md §2.3` item
539
+ * 2's shape, its sixth member `pending: Handle[]` added 2026-10-15; `surface.md §2.11` clause 6, the one
540
+ * home of the architect's ruling that a repair *"IS PASSED THE COMMIT IT IS PART OF"*).
541
+ *
542
+ * **THE REPAIR'S CONTEXT IS NOT THE CONSTRAINT'S CONTEXT, AND THE TWO ARE NOT INTERCHANGEABLE**: the
543
+ * constraint receives the FIVE-member `AttemptContext` and the repair the SIX-member `RepairContext`, whose
544
+ * extra member is the commit's own `pending` — *"so that they can make their own write call use that
545
+ * commit"*. **THE SYNTHETIC ATTEMPT'S OWN `commit` MEMBER IS WHAT THIS SLOT CARRIES** (`3-bis` (a): *"the
546
+ * `CommitRecord` of the registration act"*), handed as a FRESH LIST the way the landing instant hands it, so
547
+ * the record's member is never aliased and a repair that mutated its context's list moves nothing on the
548
+ * commit.
549
+ *
550
+ * **AND THE ABSENCE AT THIS INSTANT IS SPELLED BY THE `AttemptContext`'S OWN CLAUSE, NOT MINTED HERE:** there
551
+ * is no landing, so `op` is `null` (that clause's (5)) and `tier` is `null` (its (2)) — the two absences the
552
+ * `RollbackStep.checkpoint` precedent already fixes — while `value` is the store's CURRENT value at the
553
+ * pair's address, read and not landed (its (3)). **`id` IS THE PAIR'S OWN**, which the constraint's context
554
+ * does not carry at all, the repair's shape declaring it.
555
+ */
556
+ function registrationRepairContext(store, address, id, commitRecord) {
557
+ return {
558
+ address: address.slice(),
559
+ id,
560
+ // `tier` — ABSENT, spelled `null`; `value` — READ, not landed; `op` — ABSENT, spelled `null`.
561
+ tier: null,
562
+ value: readCurrent(store, address),
563
+ op: null,
564
+ // THE COMMIT THE REPAIR IS PART OF — a FRESH LIST, never the record's own member (`§2.3` item 2).
565
+ pending: Array.isArray(commitRecord.pending) ? commitRecord.pending.slice() : [],
566
+ };
567
+ }
568
+
569
+ /**
570
+ * **STATE 3 — THE SYNTHETIC ATTEMPT AND THE REPAIR IT CARRIES** (`docs/specs/storeroom-native/contract.md
571
+ * §7.3` (b) `3-bis` (a)–(f); `attempt-lifecycle.md §2.4` items 1, 3, 4 arm (b)).
572
+ *
573
+ * **THE ATTEMPT'S RECORD IS ITEM 1's NINE MEMBERS UNCHANGED — NO TENTH MEMBER IS MINTED AND NO MEMBER'S
574
+ * DOMAIN MOVES:** `ref`, `commit`, `ops`, `log`, `ran`, `appliedRepairs`, `open`, `rollback`, `checkpoint`.
575
+ * **ITS `address` IS THE PAIR'S OWN**, **`ITS `checkpoint` BEGINS `null`*** — that member's declared `null`
576
+ * arm, because no landing at that address has yet left it valid for THIS attempt — and **its `ref` is a
577
+ * kernel-minted `AttemptRef` unique within the instance**. **Its `log` is a real `LogEntry[]` carrying this
578
+ * kernel's own `seq` ordinal**, and the `constraint-check` and `repair-run` entries arm (b) appends stand in
579
+ * it. **IT IS TERMINAL-AWARE ON BOTH ARMS**: it reaches `PASSED` or `FAILING` and closes, and no
580
+ * registration leaves an open attempt in the registry.
581
+ *
582
+ * **THE OP THE REPAIR LANDS IS HELD BY THIS ATTEMPT AND NOTHING ELSE** — `3-bis` (a)'s selection of the
583
+ * synthetic branch, so principle (1) (*"a repair's op is an attempt's op"*) still binds and no op is
584
+ * admitted outside one.
585
+ *
586
+ * **AND ITS OP LANDS DURABLY** (`3-bis` (f)): the repair's edit goes through the store's OWN verbs, its
587
+ * `op` is a real `JournalOp` in the store's own journal, readable back through every read verb at that
588
+ * address, and it stands after the registration returns. **THIS IS NOT A DRY RUN**, and no clause of that
589
+ * contract may be read as one. **ON SUCCESS NO LOG CROSSES** (`3-bis` (c), under `A135` (1)'s
590
+ * failure-only bubbling): the caller receives the identity ALONE, and the repair's outcome is carried by
591
+ * this attempt's own `log` and `ops` — the two carriers that clause fixes.
592
+ *
593
+ * **ON FAILURE THE REGISTRATION IS REFUSED** (`3-bis` (d)'s arms (d)/(e)/(f)): the store's
594
+ * `ConstraintListInvalid` is answered in the SAME form and with the SAME THREE SLOTS as state 2's. The
595
+ * synthetic attempt's `KC-4`/`KC-5`/`KC-6` **stays inside this module** and reaches no caller, because the
596
+ * caller's act is the registration and it is the registration that is refused (`§7.3` (e)'s re-reading).
597
+ */
598
+ function registrationAttempt(kernel, store, pair) {
599
+ const address = pair.address;
600
+ const key = pairKey(address, pair.id);
601
+ ATTEMPTS += 1;
602
+ const attempt = {
603
+ ref: { id: `attempt-${ATTEMPTS}` },
604
+ store,
605
+ address: address.slice(),
606
+ tier: null,
607
+ value: undefined,
608
+ // `commit` — THE REGISTRATION ACT'S OWN `CommitRecord` (`3-bis` (a)): this kernel's four members, with
609
+ // no write's op and no write's triggered set, because a registration lands no `K-2` of its own.
610
+ commit: { attempt: null, op: null, triggered: [], pending: [] },
611
+ write: null,
612
+ ops: [],
613
+ log: [],
614
+ ran: [],
615
+ appliedRepairs: [],
616
+ rollback: [],
617
+ checkpoint: null,
618
+ checkedOff: [],
619
+ status: 'open',
620
+ report: null,
621
+ };
622
+
623
+ // ARM (b) VERBATIM: the `constraint-check` entry and the `repair-run` entry are appended, the repair runs
624
+ // through the caller's own verb, and the op its `{ok: true, op}` return names is added to `ops` while its
625
+ // pair is appended to BOTH `ran` and `appliedRepairs` (`3-bis` (b): the pair JOINS both members — of the
626
+ // SYNTHETIC attempt, and of no other). **THE PAIR ENTERS `ran` BEFORE THE REPAIR RUNS**, which is that
627
+ // arm's own ordering and is what makes the repeat arms reachable at the re-run below.
628
+ append(attempt, 'constraint-check', pair.id, null, `the evaluation of ${pair.id}`);
629
+ attempt.ran.push(key);
630
+ append(attempt, 'repair-run', pair.id, null, 'the pair\'s repair was attempted at registration');
631
+
632
+ let result;
633
+ try {
634
+ result = pair.repair(registrationRepairContext(store, address, pair.id, attempt.commit));
635
+ } catch (body) {
636
+ // A REPAIR WHOSE BODY THROWS IS A FAILED REPAIR AND THE REGISTRATION IS REFUSED — the caller's act is
637
+ // the registration, so the refusal is this module's one form (`3-bis` (d); the `KC` boundary at (e)).
638
+ // **THE BODY'S THROWABLE IS NOT CONVERTED INTO A STORE FORM AND IS NOT REACHED BY THE CALLER HERE**: it
639
+ // is caught so the attempt can close and the registration can be refused in the declared form; a drive
640
+ // that expected the body's own value out of `addConstraint` has read a route no clause declares.
641
+ closeRegistrationAttempt(attempt);
642
+ return registrationRefusal(address, pair.id, attempt.log);
643
+ }
644
+
645
+ const ok = result !== null && typeof result === 'object' && result.ok === true;
646
+ const produced = ok ? landedOp(attempt, result, null) : null;
647
+ if (produced === null) {
648
+ // ARM (d) — THE REPAIR PRODUCED NO OP: `{ok: false, message}`, an outside-form return, or an
649
+ // `ok === true` return whose `op` is absent, `undefined` or not the one it landed.
650
+ closeRegistrationAttempt(attempt);
651
+ return registrationRefusal(address, pair.id, attempt.log);
652
+ }
653
+
654
+ attempt.ops.push(produced);
655
+ attempt.appliedRepairs.push(key);
656
+ const entry = attempt.log[attempt.log.length - 1];
657
+ entry.opId = produced.opId;
658
+ entry.message = `the repair ${pair.id} landed ${produced.opId}`;
659
+
660
+ // THE RE-RUN — `3-bis` (d)'s arms (e)/(f) and `3-bis` (e)'s ordinary landing rules: the repair's op
661
+ // LANDED, so the pairs registered at ITS OWN landing's address are evaluated by the ordinary pass
662
+ // (`kernel-surface.md §2.3` item 1), in first-registration order, against THAT op.
663
+ const failed = registrationRerun(kernel, attempt, produced);
664
+ if (failed !== null) {
665
+ closeRegistrationAttempt(attempt);
666
+ return registrationRefusal(address, pair.id, attempt.log);
667
+ }
668
+ // THE PASSING ARM: `PASSED` → `CLOSED` and the registration STANDS. **NO LOG CROSSES**, and the repair's
669
+ // edit STANDS in the store — the side effect the architect's trust clause licenses (`3-bis` (f)).
670
+ closeRegistrationAttempt(attempt, 'passed');
671
+ return null;
672
+ }
673
+
674
+ /// **THE SYNTHETIC ATTEMPT'S RE-RUN** — every pair standing at the attempt's own address, evaluated once
675
+ /// against the repair's own op (`attempt-lifecycle.md §2.4` item 5 (iv)'s evaluated set, which the
676
+ /// registration instant neither widens nor displaces). Answers `null` where the re-run passes and the arm's
677
+ /// token where it does not.
678
+ ///
679
+ /// **THE ARM IS READ OFF THE PAIR THAT FAILED AND OFF NOTHING ELSE** (item 4's disjointness rule): the
680
+ /// pair under repair is IN `ran` — arm (b) wrote it — and arm (b) has just put it in `appliedRepairs`, so a
681
+ /// repeat by the repair's OWN edit reaches `(e)`; a pair IN `ran` and NOT in `appliedRepairs` reaches
682
+ /// `(f)`. **`(c)` is unreachable here**, the pair's own function having already run at this instant.
683
+ function registrationRerun(kernel, attempt, produced) {
684
+ const list = kernel.byAddress.get(addressToken(attempt.address));
685
+ if (list === undefined) return null;
686
+ for (const key of list.slice()) {
687
+ const pair = kernel.pairs.get(key);
688
+ if (pair === undefined) continue;
689
+ const outcome = pair.constraint({
690
+ address: attempt.address.slice(),
691
+ tier: produced.tier === undefined ? null : produced.tier,
692
+ value: produced.after === undefined ? undefined : produced.after.value,
693
+ attempt: attempt.ref,
694
+ op: produced,
695
+ });
696
+ if (outcome === true) continue;
697
+ attempt.terminalArm = attempt.appliedRepairs.includes(key) ? 'KC-5' : 'KC-6';
698
+ return attempt.terminalArm;
699
+ }
700
+ return null;
701
+ }
702
+
703
+ /**
704
+ * **THE REFUSAL THE REGISTRATION ANSWERS — `ConstraintListInvalid` WITH ITS `§8.2`-GENERATED MESSAGE —
705
+ * COMPOSED HERE AS A CODE AND ITS SLOTS, AND RENDERED BY THE SURFACE.**
706
+ *
707
+ * **⟶ THIS IS THE ROUTE THE ARCHITECT SETTLED, AND IT IS NOT A MESSAGE FROM A SECOND SOURCE.** `DD-52`
708
+ * forbids a code's message being produced from a second source, and `§8.2`'s one row declares the slots
709
+ * this instant supplies: **`<CONTAINER>` the pair's own list name, `constraints`**; and **`<SEGMENT>` the
710
+ * ADDED PAIR's `address` spelling, joined by `/`** — the pair's OWN address and not a failing element's,
711
+ * because at this instant the entry is WELL-FORMED and the pair is SUBMITTED rather than found wrong.
712
+ * (`<KEYLIST>`, the row's third slot, is the added pair's members present; no slot of it is asserted here,
713
+ * `§8.2` clause 3 declaring that the sentence the slots make is asserted by NO clause of that contract.)
714
+ *
715
+ * **THE FIXED PHRASE *"is not a valid constraint entry in"* IS RENDERED VERBATIM AND IS NOT RE-AUTHORED** —
716
+ * `§8.2`'s clause 3 of 2026-10-16, which names the honest consequence: at this instant the sentence's SHAPE
717
+ * reports an entry that failed its own validity check while the state is a well-formed pair whose FUNCTION
718
+ * DID NOT PASS. **A HAND-AUTHORED REGISTRATION MESSAGE IS A FAIL OF `P-TP-9` AND NONE STANDS HERE**: not a
719
+ * byte of the text is written in this module, and the sentence is produced by the store's own generator at
720
+ * the surface's existing `errorMessage` path.
721
+ *
722
+ * **THE VALUE CARRIES THIS MODULE'S OWN MARK** (`KERNEL_REFUSAL`) so the surface can tell it from a
723
+ * caller's throw, and the mark is set HERE — in the frame that BUILT the value — and never by a test over
724
+ * members. **A CALLER'S OWN THROWN VALUE STILL SURFACES AS ITSELF**: the 2026-10-17 forgery fix's whole
725
+ * point, and the five shapes are re-probed with this arm in place.
726
+ */
727
+ function registrationRefusal(address, id, log) {
728
+ return {
729
+ status: 'ConstraintListInvalid',
730
+ segment: address.map((segment) => String(segment)).join('/'),
731
+ container: 'constraints',
732
+ id,
733
+ log: Array.isArray(log) ? log : [],
734
+ [KERNEL_REFUSAL]: true,
735
+ };
736
+ }
737
+
738
+ /// **THE SYNTHETIC ATTEMPT'S TERMINAL ACT — `PASSED` OR `FAILING`, AND `CLOSED` FROM THOSE TWO AND FROM
739
+ /// NOWHERE ELSE** (`attempt-lifecycle.md §2.4` item 3). It reaches neither the per-op rollback composition
740
+ /// nor the delivery seam: **the registration instant opens no `K-2`, delivers no listener and composes no
741
+ /// rollback** — the repair's edit STANDS on the passing arm (`3-bis` (f)), and a failed repair's own state
742
+ /// is left where the store's own verb left it (`3-bis` (d): the store's state is left where the composition
743
+ /// restored it, which for an attempt with no rollback composed is the state the verb produced).
744
+ function closeRegistrationAttempt(attempt, outcome = 'failed') {
745
+ attempt.status = 'closed';
746
+ const report = {
747
+ attempt: attempt.ref,
748
+ outcome,
749
+ ops: attempt.ops.slice(),
750
+ log: attempt.log,
751
+ rollback: [],
752
+ };
753
+ attempt.report = report;
754
+ CLOSED.set(attempt.ref.id, report);
755
+ LIVE.delete(attempt.ref.id);
756
+ return report;
757
+ }
758
+
759
+
386
760
  /** The store holds ONE registration per address, and its `listen` takes a function. */
387
761
  function noopListener() {}
388
762
 
@@ -908,10 +1282,24 @@ function evaluate(kernel, attempt, landing) {
908
1282
  // (the store's form is `{status, message}`, carrying no `log` member — `§1.2` item 2; the
909
1283
  // kernel's own form carries three members, and a `KC` token is never named as a store code).
910
1284
  // The entry's `state` stays `null`; the thrown form's `status` is `KC-4`.
1285
+ // **⟶ THE TEST THAT THIS THROWABLE IS *NOT* THE KERNEL'S OWN WAS `!('log' in body)`, AND THAT
1286
+ // TEST DIED ON 2026-10-16 WITH THE FLAT `log` RULING — THIS IS THE SECOND SITE THE RULING BROKE AND
1287
+ // IS REPORTED AS A FINDING, NOT SILENTLY REPAIRED.** The old test read *"the store's form carries two
1288
+ // members and the kernel's carries three, so a `log` member means the kernel built it"*. **`surface.md
1289
+ // §2.5` item 4 now puts `log` on EVERY failure the JS surface throws, so a STORE REFUSAL REACHING
1290
+ // THIS FRAME THROUGH THE PACKAGE CARRIES A `log` AND THE OLD TEST READ IT AS THE KERNEL'S OWN** —
1291
+ // measured: the two `S-JOIN` `WriteParentNotLink` cells went red with the caller's `status` reading
1292
+ // `WriteParentNotLink` instead of `KC-4`, because `storeCode` was answered `null` and the refusal fell
1293
+ // through to the unconverted `throw body` below.
1294
+ //
1295
+ // **THE REPLACEMENT IS THE SAME ONE THE ENTRY'S CROSSING TOOK — THE KERNEL'S OWN REFUSAL-CLASS MARK
1296
+ // AND NEVER A MEMBER'S PRESENCE** (`KERNEL_REFUSAL` above): a value this kernel built is marked, and
1297
+ // everything unmarked that carries a store code IS a store code, whatever members the surface has
1298
+ // attached to it on its way back. A `KC` token is still never a store code on either spelling.
911
1299
  const storeCode = body !== null && typeof body === 'object'
1300
+ && isKernelRefusal(body) === false
912
1301
  && typeof body.status === 'string'
913
1302
  && body.status.length > 0
914
- && !('log' in body)
915
1303
  && !KC_TOKENS.includes(body.status)
916
1304
  ? body.status
917
1305
  : null;