provident-storeroom 0.3.1 → 0.5.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 +124 -6
- package/index.mjs +476 -26
- package/package.json +6 -6
- package/src/constraint-kernel.mjs +429 -6
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}
|
|
406
|
-
/// VERBATIM** (`§2.5` items 1–2, `DD-40`): this function constructs the
|
|
407
|
-
///
|
|
408
|
-
|
|
409
|
-
|
|
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(
|
|
1923
|
+
id = addon_.storeCreate(encoded);
|
|
1822
1924
|
} catch (refusal) {
|
|
1823
1925
|
fail(refusal);
|
|
1824
1926
|
}
|
|
@@ -1895,6 +1997,16 @@ export function storeCreate(cfg) {
|
|
|
1895
1997
|
constraintOff(pair, constraint) {
|
|
1896
1998
|
return constraintToggle(false, instance, arguments.length, pair, constraint);
|
|
1897
1999
|
},
|
|
2000
|
+
/// **`surface.md §2.4` item 9 (f)'s `constraints` clause of 2026-10-17: `a.constraints() -> Array<{ address,
|
|
2001
|
+
/// id }>` — THE REGISTERED-PAIR READ, the thirteenth own member (`10 + 1 + 1 + 1 = 13` ✓; `PAR-JS-27`;
|
|
2002
|
+
/// `§2.12` item 2-bis).** **THE RECEIVER IS THE STORE, THE CALL TAKES NO ARGUMENT (arity `0`) AND IT
|
|
2003
|
+
/// THROWS NOTHING** — there is no outside argument for the class test to refuse, and the call makes no
|
|
2004
|
+
/// store call, mints no code, appends no journal entry and changes no node. **It is NOT a named export of
|
|
2005
|
+
/// the entry** (`package.md §1.3` item 3; `§2.9` item 1's `A127` clause, `11 → 1` ✓): it is reached
|
|
2006
|
+
/// through the factory's own product alone.
|
|
2007
|
+
constraints() {
|
|
2008
|
+
return enumerateConstraints(state);
|
|
2009
|
+
},
|
|
1898
2010
|
/// `surface.md §2.4` item 5 (b): `register(handle, listener) -> undefined` — the OPAQUE handle a verb
|
|
1899
2011
|
/// returned or the construction adopted, and ANY JS function. **It is NOT a named export of the entry**
|
|
1900
2012
|
/// (`package.md §1.3` item 3): it is reached through the factory's own product alone.
|
|
@@ -1922,7 +2034,18 @@ export function storeCreate(cfg) {
|
|
|
1922
2034
|
const encoded = constraintEntry(element, i);
|
|
1923
2035
|
if (encoded.bad !== undefined) continue;
|
|
1924
2036
|
if (typeof element.constraint !== 'function') continue;
|
|
1925
|
-
|
|
2037
|
+
// **⟶ AND THIS SITE TAKES THE THREE-STATE REGISTRATION TOO** (`§2.12` item 3's clause of 2026-10-16
|
|
2038
|
+
// at its `A135` (3) mark; `docs/specs/storeroom-native/contract.md §7.3` (b)). **THE BATCH ROUTE AND THE
|
|
2039
|
+
// ADD ROUTE REACH THE SAME `K-1`**, so a batch element the current state violates — with no repair
|
|
2040
|
+
// standing, or with one that does not resolve it — refuses the CONSTRUCTION in this surface's one
|
|
2041
|
+
// failure form, exactly as the ADD route refuses the call. **THE STATE 3 SUCCESS ARM IS THE ONE THAT
|
|
2042
|
+
// MOVES THE STORE**: the repair's edit stands, the registration stands, and the construction returns
|
|
2043
|
+
// its instance with no log crossing (`3-bis` (c)).
|
|
2044
|
+
try {
|
|
2045
|
+
carryConstraint(state, instance, encoded.address.s, encoded.id, element.constraint);
|
|
2046
|
+
} catch (refusal) {
|
|
2047
|
+
registrationCrossing(refusal);
|
|
2048
|
+
}
|
|
1926
2049
|
}
|
|
1927
2050
|
}
|
|
1928
2051
|
// **⟶ AND THE CONSTRUCTION'S OWN ADOPTION ENTERS THE PACKAGE'S HOME MIRROR** (`§2.4` item 7 (b)'s dated
|
|
@@ -2504,9 +2627,12 @@ function settleOn(state, record, supplied) {
|
|
|
2504
2627
|
// `crossing.md §1.7`): an absent argument, every non-object and every `Proxy` is refused before any
|
|
2505
2628
|
// marker is read or set.
|
|
2506
2629
|
if (!supplied || record === null || typeof record !== 'object' || types.isProxy(record)) {
|
|
2507
|
-
|
|
2630
|
+
// **AND IT CARRIES `log: []` ON THE RULING'S FLAT READING** (`surface.md §2.5` item 4 names the
|
|
2631
|
+
// registration site's `TypeError` among the arms that carry the empty array; the `status` this form
|
|
2632
|
+
// never had is still not minted — `§2.4` item 9 (b)'s *"its `status` member MUST BE ABSENT"* stands).
|
|
2633
|
+
throw withEmptyLog(new TypeError(
|
|
2508
2634
|
`settle's argument is ${classSpelling(record)}, and the ordering seam takes a record identity this instance adopted`,
|
|
2509
|
-
);
|
|
2635
|
+
));
|
|
2510
2636
|
}
|
|
2511
2637
|
// **⟶ ONE WRITE, ONE ADOPTION, AND TWO IDENTITIES CARRY IT** (`§2.4` item 9's table rows (a) and (b);
|
|
2512
2638
|
// `PAR-JS-19`: *"the adoption happens AT the first call, and the SECOND call for that identity is the
|
|
@@ -2542,9 +2668,9 @@ function settleOn(state, record, supplied) {
|
|
|
2542
2668
|
}
|
|
2543
2669
|
if (!pre) {
|
|
2544
2670
|
if (record.pending === undefined) {
|
|
2545
|
-
throw new TypeError(
|
|
2671
|
+
throw withEmptyLog(new TypeError(
|
|
2546
2672
|
`settle's argument is ${classSpelling(record)}, and the ordering seam takes a record identity this instance adopted`,
|
|
2547
|
-
);
|
|
2673
|
+
));
|
|
2548
2674
|
}
|
|
2549
2675
|
// INSTANT (a): the adoption. The ledger entry stands EMPTY until the verb answers, so the write that
|
|
2550
2676
|
// drains it is the one write identity this adoption is for.
|
|
@@ -2761,18 +2887,79 @@ function constraintPairKey(address, id) {
|
|
|
2761
2887
|
/// **THE ONE REFUSAL `§2.12` ITEM 4 DECLARES, TAKEN BEFORE ANY ACT AND LEAVING NOTHING CHANGED** — a JS
|
|
2762
2888
|
/// `TypeError`, its `status` member ABSENT, no `message` member of this unit's own, **the store's closed
|
|
2763
2889
|
/// `16`-member set neither minted nor widened, and the store reached by no call this refusal makes.**
|
|
2890
|
+
///
|
|
2891
|
+
/// **⟶ AND THE `TypeError` CARRIES `log: []` FROM 2026-10-16, AND THIS IS THE ONE PLACE THE FLAT RULING AND
|
|
2892
|
+
/// `A127`'S TWO REFUSAL RULES MEET — SO THE RECONCILIATION IS STATED RATHER THAN LEFT TO THE READER**
|
|
2893
|
+
/// (`surface.md §2.5` item 4, which names *"the three constraint methods' `TypeError`"* among the arms that
|
|
2894
|
+
/// *"all carry `log: []`"*; `§2.12` item 4's replacement clause and `§2.4` item 9 (f)'s rule (ii), which fix
|
|
2895
|
+
/// the class, the absent `status` and the change-nothing atomicity).
|
|
2896
|
+
///
|
|
2897
|
+
/// **THE TWO RULES ARE NOT IN TENSION AND NEITHER MOVES:** rule (ii) declares the refusal is **a `TypeError`
|
|
2898
|
+
/// CARRYING NO `status` MEMBER** — and it still carries none: the member below is written on the *error
|
|
2899
|
+
/// object* and is `log`, not `status`, and **`'status' in err` is still `false` on every call of this
|
|
2900
|
+
/// method.** The ruling does not re-class the refusal as a store refusal, does not mint a `status`, does not
|
|
2901
|
+
/// reach the store and does not change the call's effects — *"no store call is made, no pair is added,
|
|
2902
|
+
/// enabled or disabled, no journal entry is appended and no code is minted"* stands whole. **THE ONE THING
|
|
2903
|
+
/// THE RULING ADDS IS A MEMBER, AND A `TypeError` IS AN ORDINARY OBJECT: an own enumerable data member can
|
|
2904
|
+
/// be set on it without making it any less an instance of `TypeError` and of nothing else** — which is the
|
|
2905
|
+
/// single question that had to be answered before this could be written, and it is answered by the class,
|
|
2906
|
+
/// not by a judgement here (`Object.keys(new TypeError('x'))` is `[]` and the object is EXTENSIBLE).
|
|
2907
|
+
///
|
|
2908
|
+
/// **SO THE DECLARED FORM DOES CARRY A THIRD MEMBER, AND THIS IS *NOT* A SPEC CONFLICT: the collision the
|
|
2909
|
+
/// task warned of would be a form that had to become *"a different form"* to hold `log`, and it does not —
|
|
2910
|
+
/// the class (`TypeError`, and of nothing else), the ABSENT `status`, the change-nothing atomicity, the
|
|
2911
|
+
/// caller's own `message` text and the one-`TypeError`-for-both-refusals rule all cross this frame
|
|
2912
|
+
/// untouched. What changes is `Object.keys` on the thrown error, from `[]` to `["log"]`.**
|
|
2913
|
+
///
|
|
2914
|
+
/// **THE MEMBER IS SET WITH `Object.defineProperty` RATHER THAN BY ASSIGNMENT, AND THE REASON IS THE ONE
|
|
2915
|
+
/// `§2.5` ITEM 9 DECLARES: THE DESCRIPTOR MUST BE ORDINARY — own, enumerable, a data member, writable and
|
|
2916
|
+
/// configurable.** A plain `err.log = []` on an error object achieves exactly that descriptor on V8 and every
|
|
2917
|
+
/// engine this package supports, **but it is written with `defineProperty` HERE because an error's own
|
|
2918
|
+
/// members are not universally ordinary across realms and a runtime that made `Error.prototype.log` an
|
|
2919
|
+
/// accessor would silently divert the write**, and the declaration is cheap where the alternative is a
|
|
2920
|
+
/// silent miss on a member the census reads. **THE PROHIBITION IN `§2.5` ITEM 9 (*"written with an object
|
|
2921
|
+
/// literal, not `Object.defineProperty`"*) BINDS THE STORE'S PLAIN-OBJECT FORM AND ITS `log`, WHICH THIS
|
|
2922
|
+
/// PACKAGE WRITES WITH AN OBJECT LITERAL IN `fail` ABOVE AND IN `constraintCrossing` BELOW; it cannot bind a
|
|
2923
|
+
/// `TypeError`, because a `TypeError` has no object literal and its class is what rule (ii) declares. The
|
|
2924
|
+
/// ITEM'S PURPOSE — that a canonical census sees the member — is the property both routes preserve, and the
|
|
2925
|
+
/// descriptor is asserted explicitly below so the purpose is met member for member.**
|
|
2764
2926
|
function constraintRefuse(where, value) {
|
|
2765
|
-
|
|
2927
|
+
const error = new TypeError(
|
|
2766
2928
|
`the ${where} of this call is ${classSpelling(value)}, and it is not a value this position's domain `
|
|
2767
2929
|
+ 'admits',
|
|
2768
2930
|
);
|
|
2931
|
+
throw withEmptyLog(error);
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
/// **THE ONE PLACE `log: []` IS SET ON A REFUSAL THAT IS NOT AN OBJECT LITERAL** — the three constraint
|
|
2935
|
+
/// methods' `TypeError` and nothing else. **`surface.md §2.5` item 4 calls for the EMPTY ARRAY on exactly
|
|
2936
|
+
/// these arms** — *"the EMPTY ARRAY, never an absent member, never `null`, and never a placeholder entry"* —
|
|
2937
|
+
/// and item 9 calls for an **own enumerable data member**, which is the descriptor written here BY HAND so
|
|
2938
|
+
/// that no default, no engine and no realm decides it. **THE ERROR'S PROTOYPE IS NOT TOUCHED**, so
|
|
2939
|
+
/// `err instanceof TypeError` stays `true` and `Object.getPrototypeOf(err)` stays `TypeError.prototype`:
|
|
2940
|
+
/// the member is the error's own and the class is the error's own.
|
|
2941
|
+
///
|
|
2942
|
+
/// **THE ARRAY IS A FRESH `[]` AT EACH THROW**, so two refusals never alias one list — a shared frozen
|
|
2943
|
+
/// constant would be a value a caller could observe as the *same* array across calls, and `§2.5` item 4
|
|
2944
|
+
/// declares a VALUE (`[]`), not a shared identity.
|
|
2945
|
+
function withEmptyLog(error) {
|
|
2946
|
+
Object.defineProperty(error, 'log', {
|
|
2947
|
+
value: [],
|
|
2948
|
+
writable: true,
|
|
2949
|
+
enumerable: true,
|
|
2950
|
+
configurable: true,
|
|
2951
|
+
});
|
|
2952
|
+
return error;
|
|
2769
2953
|
}
|
|
2770
2954
|
|
|
2771
2955
|
/// **A POSITION BELOW THE DECLARED ONE — `§2.12` item 4 AND `§2.4` item 9 (f)'s RULE (ii): a SHORT ARITY
|
|
2772
2956
|
/// TAKES THE SAME ONE `TypeError` AND CHANGES NOTHING.** *"No assertion is made over `message`, and its
|
|
2773
2957
|
/// absence is the declared reading"* — the member is not one of the three this form is observed by.
|
|
2958
|
+
/// **AND IT IS THE SAME ONE `TypeError` IN THE RULING'S OWN SENSE TOO: the SHORT-ARITY refusal and the
|
|
2959
|
+
/// OUTSIDE-VALUE refusal are ONE form, so `log: []` is set by the same `withEmptyLog` and neither refusal
|
|
2960
|
+
/// gains a `status`** (`surface.md §2.5` item 4's *"the three constraint methods' `TypeError`"*).
|
|
2774
2961
|
function constraintArity(verb) {
|
|
2775
|
-
throw new TypeError(`\`${verb}\` declares two positions, and this call supplied fewer`);
|
|
2962
|
+
throw withEmptyLog(new TypeError(`\`${verb}\` declares two positions, and this call supplied fewer`));
|
|
2776
2963
|
}
|
|
2777
2964
|
|
|
2778
2965
|
/// **`§2.12` ITEM 4'S TWO CALLER POSITIONS, CLASS FIRST AND IN THEIR DECLARED ORDER** (`PAR-JS-22`–`PAR-JS-24`)
|
|
@@ -2812,7 +2999,18 @@ function constraintSite(verb, instance, supplied, pair, constraint) {
|
|
|
2812
2999
|
/// opacity is the observable** — *"it has no own enumerable member at all"* — so it is a null-prototype
|
|
2813
3000
|
/// object and NOT the entry record: every datum above stays the entry's own and never crosses.
|
|
2814
3001
|
function carryConstraint(state, instance, address, id, constraint) {
|
|
2815
|
-
|
|
3002
|
+
// **⟶ AND THE REGISTRATION IS NOW A THREE-STATE ACT, WHOSE THIRD STATE LANDS AN EDIT** (`§2.12` item 3's
|
|
3003
|
+
// 2026-10-16 clause, read through its `A135` (3) mark; `docs/specs/storeroom-native/contract.md §7.3` (b)
|
|
3004
|
+
// states 1–3 and `3-bis`). `K-1` evaluates the constraint at registration: on states 1 and 3-success it
|
|
3005
|
+
// RETURNS the handle and no log crosses; on states 2 and 3-failure it THROWS a refusal this entry renders
|
|
3006
|
+
// and re-throws in the surface's own single form (`registrationCrossing` below). **THE ENTRY'S OWN
|
|
3007
|
+
// RECORD IS WRITTEN ONLY WHERE THE REGISTRATION STOOD**, so a refused registration leaves this state
|
|
3008
|
+
// exactly as it stood (`§2.12` item 3: *"NO identity is returned and NO element is carried"*).
|
|
3009
|
+
try {
|
|
3010
|
+
constraintsKernel().register(instance, address, id, constraint);
|
|
3011
|
+
} catch (refusal) {
|
|
3012
|
+
registrationCrossing(refusal);
|
|
3013
|
+
}
|
|
2816
3014
|
const entry = {
|
|
2817
3015
|
address,
|
|
2818
3016
|
addressKey: JSON.stringify(address),
|
|
@@ -2825,6 +3023,54 @@ function carryConstraint(state, instance, address, id, constraint) {
|
|
|
2825
3023
|
return entry;
|
|
2826
3024
|
}
|
|
2827
3025
|
|
|
3026
|
+
/// **THE REGISTRATION REFUSAL'S CROSSING — THE KERNEL HANDS BACK A CODE AND ITS SLOTS, AND THIS ENTRY
|
|
3027
|
+
/// RENDERS THE TEXT THROUGH THE GENERATOR IT ALREADY HOLDS** (`docs/specs/storeroom-native/contract.md
|
|
3028
|
+
/// §8.2`'s 2026-10-16 clause, items 1–5; `surface.md §2.12` item 3's clause of the same date).
|
|
3029
|
+
///
|
|
3030
|
+
/// **NO MESSAGE IS AUTHORED HERE AND NONE IS AUTHORED IN THE KERNEL.** `DD-52` forbids a code's message
|
|
3031
|
+
/// from a second source, so the sentence is produced by the store's own generator — reached through
|
|
3032
|
+
/// `addon_.errorMessage(code, subject[, container])`, the very path `boundaryReject` already takes — from
|
|
3033
|
+
/// the `§8.2` row's own SLOTS: `<CONTAINER>` the pair's own list name `constraints`, and `<SEGMENT>` the
|
|
3034
|
+
/// added pair's `address` spelling joined by `/`. **THE FIXED PHRASE IS THE ROW'S AND IS RENDERED VERBATIM**
|
|
3035
|
+
/// (`§8.2` clause 3), and no per-instant template stands.
|
|
3036
|
+
///
|
|
3037
|
+
/// **⟶ AND THE 2026-10-17 FORGERY FIX SURVIVES INTACT, WHICH IS THIS FRAME'S HIGHEST-RISK OBLIGATION.** The
|
|
3038
|
+
/// classification is **IDENTITY, NOT SHAPE** — the kernel's own mark under the `Symbol.for` key both sides
|
|
3039
|
+
/// spell (`KERNEL_REFUSAL` above) and nothing a caller can spell — so:
|
|
3040
|
+
/// * **A KERNEL-BUILT REFUSAL** (its `status` a string, its slot members present) is rendered and
|
|
3041
|
+
/// re-thrown in the surface's single two-member-plus-`log` form below;
|
|
3042
|
+
/// * **EVERYTHING ELSE IS THE CALLER'S AND CROSSES AS ITSELF** — a forged two-member object, a forged
|
|
3043
|
+
/// three-member object, a `TypeError`, a bare string and `undefined` all reach the caller as the very
|
|
3044
|
+
/// value that was thrown, `caught === thrown`, and none of them reaches the generator.
|
|
3045
|
+
///
|
|
3046
|
+
/// **AND A BODY'S OWN THROW IS THAT SECOND ARM AND NOT A THIRD**: `fail-surface.md §1.1` item 5 leaves a
|
|
3047
|
+
/// throwing constraint or repair body *"untouched and unconverted"*, and it carries no mark, so it is
|
|
3048
|
+
/// re-thrown by the one line above the render.
|
|
3049
|
+
function registrationCrossing(refusal) {
|
|
3050
|
+
if (isKernelBuiltRefusal(refusal) === false) throw refusal;
|
|
3051
|
+
const addon_ = withAddon();
|
|
3052
|
+
// THE SLOTS THE KERNEL HANDS BACK ARE THE `§8.2` ROW'S OWN, and the generator's own three-argument call
|
|
3053
|
+
// fills `<CONTAINER>` beside `<SEGMENT>`. Where an artefact loaded but does not carry the generator, the
|
|
3054
|
+
// declared absent/failed-addon state is the answer, exactly as `boundaryReject` takes it — and where a
|
|
3055
|
+
// marked value carries no usable slots the handler below answers it, so no unsubstituted placeholder can
|
|
3056
|
+
// reach a caller from this frame.
|
|
3057
|
+
const usable = typeof addon_.errorMessage === 'function'
|
|
3058
|
+
&& typeof refusal.status === 'string'
|
|
3059
|
+
&& typeof refusal.segment === 'string';
|
|
3060
|
+
if (usable === false) throw refusal;
|
|
3061
|
+
const generated = addon_.errorMessage(refusal.status, refusal.segment, refusal.container);
|
|
3062
|
+
// **THE FORM IS THIS SURFACE'S ONE FORM** (`§2.5` items 3–4, whose `log` is PRESENT and never absent):
|
|
3063
|
+
// `{status, message, log}`, the `status` the STORE's `ConstraintListInvalid`, the `message` the STORE'S
|
|
3064
|
+
// OWN GENERATED SENTENCE, and the `log` the synthetic attempt's log where a repair was attempted and `[]`
|
|
3065
|
+
// where none was. **NO `KC` TOKEN CROSSES** (`A120` (2); `§2.12` item 3 item 2): the synthetic attempt's
|
|
3066
|
+
// terminal token stays in the kernel and reaches no caller.
|
|
3067
|
+
throw {
|
|
3068
|
+
status: refusal.status,
|
|
3069
|
+
message: generated,
|
|
3070
|
+
log: refusalLog(refusal.log),
|
|
3071
|
+
};
|
|
3072
|
+
}
|
|
3073
|
+
|
|
2828
3074
|
/// **THE DISABLED PAIR'S STANDING ELEMENT** — a function that PASSES (`kernel-surface.md §2.3` item 1:
|
|
2829
3075
|
/// `true` is the only pass value). **THE ELEMENT IS PARKED AND NEVER WITHDRAWN**: `constraintOn` re-registers
|
|
2830
3076
|
/// `entry.fn`, so *"it is the element the entry carried at that pair — never a second constraint and never a
|
|
@@ -2837,12 +3083,13 @@ function constraintParked() {
|
|
|
2837
3083
|
/// `PAR-JS-24`'s second declared answer: at EITHER toggle, in EITHER direction, an OUTSIDE VALUE taking
|
|
2838
3084
|
/// item 4's refusal, ONE THROWN `TypeError`, THE ENTRY NOT WIDENED.** It is NOT a third population route:
|
|
2839
3085
|
/// 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.
|
|
3086
|
+
/// FUNCTION — a state no clause of that directory declares. **AND IT IS THAT SAME ONE `TypeError`, carrying
|
|
3087
|
+
/// `log: []` on the ruling's flat reading and no `status` on rule (ii)'s** (`surface.md §2.5` item 4).
|
|
2841
3088
|
function constraintUncarried(verb, pair) {
|
|
2842
|
-
throw new TypeError(
|
|
3089
|
+
throw withEmptyLog(new TypeError(
|
|
2843
3090
|
`the pair at the ${ARGUMENT_POSITION_FIRST} of \`${verb}\` carries no constraint in this instance, and `
|
|
2844
3091
|
+ 'a toggle names a pair the entry carries',
|
|
2845
|
-
);
|
|
3092
|
+
));
|
|
2846
3093
|
}
|
|
2847
3094
|
|
|
2848
3095
|
/**
|
|
@@ -2862,7 +3109,16 @@ function addConstraint(instance, n, pair, constraint) {
|
|
|
2862
3109
|
if (held === undefined) {
|
|
2863
3110
|
return carryConstraint(site.state, instance, site.address, site.id, constraint).identity;
|
|
2864
3111
|
}
|
|
2865
|
-
|
|
3112
|
+
// **THE OVERWRITE ARM TAKES THE SAME THREE-STATE REGISTRATION** (`§2.12` item 3's clause of 2026-10-16
|
|
3113
|
+
// read at its `A135` (3) mark): a second ADD at a held pair registers the supplied function through `K-1`
|
|
3114
|
+
// exactly as the fresh arm does, so a registration the store REFUSES refuses THIS call too — and the held
|
|
3115
|
+
// element is left EXACTLY AS IT STOOD, because the entry's own record is written only after the
|
|
3116
|
+
// registration returns (`§2.12` item 3: *"NO identity is returned and NO element is carried"*).
|
|
3117
|
+
try {
|
|
3118
|
+
constraintsKernel().register(instance, site.address, site.id, constraint);
|
|
3119
|
+
} catch (refusal) {
|
|
3120
|
+
registrationCrossing(refusal);
|
|
3121
|
+
}
|
|
2866
3122
|
held.fn = constraint;
|
|
2867
3123
|
held.enabled = true;
|
|
2868
3124
|
return held.identity;
|
|
@@ -2889,12 +3145,70 @@ function constraintToggle(enabled, instance, n, pair, constraint) {
|
|
|
2889
3145
|
const entry = site.state.constraints.get(constraintPairKey(site.address, site.id));
|
|
2890
3146
|
if (entry === undefined) constraintUncarried(verb, pair);
|
|
2891
3147
|
if (entry.enabled !== enabled) {
|
|
2892
|
-
|
|
3148
|
+
// **THE ENABLE HALF RE-REGISTERS THE PAIR'S OWN FUNCTION, SO IT TAKES THE SAME THREE-STATE REGISTRATION
|
|
3149
|
+
// AS EVERY OTHER REGISTRATION SITE** (`§2.12` item 3's clause of 2026-10-16 at its `A135` (3) mark;
|
|
3150
|
+
// `docs/specs/storeroom-native/contract.md §7.3` (b)). A registration the store REFUSES refuses THIS
|
|
3151
|
+
// call in the same one form, and the pair's own `enabled` member is UNMOVED — written only after the
|
|
3152
|
+
// registration returns — so a refused toggle leaves the pair exactly as it stood.
|
|
3153
|
+
try {
|
|
3154
|
+
constraintsKernel().register(instance, site.address, site.id, enabled ? entry.fn : constraintParked);
|
|
3155
|
+
} catch (refusal) {
|
|
3156
|
+
registrationCrossing(refusal);
|
|
3157
|
+
}
|
|
2893
3158
|
entry.enabled = enabled;
|
|
2894
3159
|
}
|
|
2895
3160
|
return undefined;
|
|
2896
3161
|
}
|
|
2897
3162
|
|
|
3163
|
+
/// **THE REGISTERED-PAIR READ — `surface.md §2.4` item 9 (f)'s `constraints` clause of 2026-10-17, items 2–8,
|
|
3164
|
+
/// AND ITS REGISTER ROW `PAR-JS-27` (`parameter-semantics.md §2.27`).** `a.constraints() -> Array<{ address,
|
|
3165
|
+
/// id }>`: **a FRESH JS ARRAY on every call, whose every element is a FRESH PLAIN OBJECT carrying EXACTLY
|
|
3166
|
+
/// TWO MEMBERS** — `address`, a FRESH JS array of the store's own segments, and `id`, the constraint's own
|
|
3167
|
+
/// BARE `id`, a `string` — the same two data the kernel's own registry is keyed by.
|
|
3168
|
+
///
|
|
3169
|
+
/// **THE SOURCE IS THE ENTRY'S OWN `state.constraints`, AND ITS SHAPE IS ALREADY THE ANSWER'S**: a per-instance
|
|
3170
|
+
/// `Map` keyed by `constraintPairKey(address, id)` whose every value is the record `carryConstraint` writes —
|
|
3171
|
+
/// `{ address, addressKey, id, fn, enabled, identity }`. So the read is a CARRIAGE READ and no kernel item is
|
|
3172
|
+
/// touched or minted: `K-1`–`K-5` stand exactly as printed, the kernel's extent stays FIVE and no `K-6` is
|
|
3173
|
+
/// proposed (`§2.4` item 9 (f), item 8). **NO KERNEL MODULE IS EVEN LOADED HERE** — `constraintsKernel()` is
|
|
3174
|
+
/// not called, so a product that never carried and never asked for a constraint still reads `[]` on a tree
|
|
3175
|
+
/// that stages nothing beside it (`kernel-surface.md §1` item 1's lazy resolution).
|
|
3176
|
+
///
|
|
3177
|
+
/// **THE FOUR DECLARED EXCLUSIONS, EACH HONOURED AT THIS SITE AND NAMED HERE SO THE CODE CAN BE READ AGAINST
|
|
3178
|
+
/// THEM:**
|
|
3179
|
+
/// * **(1) NO CONSTRAINT FUNCTION IS RETURNED** (item 3, four grounds, the operative one for this frame being
|
|
3180
|
+
/// the anti-pattern rulings: *do not hand out a value whose later use the contract cannot bound*). The
|
|
3181
|
+
/// element is BUILT FRESH from `entry.address` and `entry.id`, so `entry.fn` is never read, referenced or
|
|
3182
|
+
/// copied — and a disabled pair's parked stub is not reachable either, because a function is never touched
|
|
3183
|
+
/// at all.
|
|
3184
|
+
/// * **(2) NO OPAQUE IDENTITY IS EXPOSED** (item 4; `PAR-JS-25`'s opacity would break the moment a consumer
|
|
3185
|
+
/// read one out of the array). `entry.identity` is not read and no element carries it.
|
|
3186
|
+
/// * **(3) NO ORDER IS PROMISED, AND NONE IS MANUFACTURED** (item 6): the enumeration is `Map` iteration order
|
|
3187
|
+
/// and nothing else — **this function does NOT sort, and deliberately does not** — so a drive compares the
|
|
3188
|
+
/// pairs as a SET and never as a sequence (`DD-22`; `§2.7` item 3). No registration order, address order or
|
|
3189
|
+
/// `seq`-like ordinal is minted here, and none is asserted of it.
|
|
3190
|
+
/// * **(4) A DISABLED PAIR DOES APPEAR** (item 5): `constraintOff` is a TOGGLE and NOT A REMOVAL, so a pair
|
|
3191
|
+
/// whose `entry.enabled` is `false` is STILL CARRIED and is enumerated — **the read does not consult
|
|
3192
|
+
/// `enabled` at all**, and it returns no `enabled` member either (a third member is a value no clause
|
|
3193
|
+
/// declares).
|
|
3194
|
+
///
|
|
3195
|
+
/// **AND THE TWO EXCLUSIONS ITEM 7 DECLARES ARE STRUCTURES AND NOT TESTS TAKEN HERE**: (i) a well-formed
|
|
3196
|
+
/// `cfg.constraints` element that carried no function never reached `carryConstraint` (`storeCreate`'s batch
|
|
3197
|
+
/// loop skips it), so it is no entry and cannot appear; and (ii) a refused registration wrote no entry
|
|
3198
|
+
/// (`carryConstraint`: *"THE ENTRY'S OWN RECORD IS WRITTEN ONLY WHERE THE REGISTRATION STOOD"*), so it
|
|
3199
|
+
/// cannot appear either. **THE SAME TWO MEMBERS ON EVERY ELEMENT AND NO THIRD**, and the `[]` arm is this
|
|
3200
|
+
/// member's declared value where the entry carries no pair at all (`PAR-JS-27`'s `domain` cell).
|
|
3201
|
+
function enumerateConstraints(state) {
|
|
3202
|
+
const pairs = [];
|
|
3203
|
+
for (const entry of state.constraints.values()) {
|
|
3204
|
+
// A FRESH PLAIN OBJECT PER CALL AND A FRESH SEGMENT ARRAY WITHIN IT (`slice`): a caller that mutates a
|
|
3205
|
+
// returned element, or an element's `address`, changes nothing the next call returns — and nothing of the
|
|
3206
|
+
// entry's own record either, the two members being copies of the pair's own data.
|
|
3207
|
+
pairs.push({ address: entry.address.slice(), id: entry.id });
|
|
3208
|
+
}
|
|
3209
|
+
return pairs;
|
|
3210
|
+
}
|
|
3211
|
+
|
|
2898
3212
|
/// **WHETHER THIS INSTANCE CARRIES A PAIR AT THIS WRITE'S ADDRESS** (`§2.12` item 1's preamble clause (a)) —
|
|
2899
3213
|
/// the gate stage 1 takes before the kernel is reached at all. **THE CLASS DECISION COMES FIRST AND NO TRAP
|
|
2900
3214
|
/// IS RUN ON ANY PATH** (`DD-34`): a `Proxy` address, a class extending `Array` and every non-array lies
|
|
@@ -2941,19 +3255,155 @@ function constraintWrite(state, instance, address, tier, value) {
|
|
|
2941
3255
|
}
|
|
2942
3256
|
|
|
2943
3257
|
/// **THE FAIL ARM'S CROSSING — `A120` (2): THE ENTRY CARRIES THE KERNEL'S TOKEN, THE THROW KEEPS THE
|
|
2944
|
-
/// STORE'S
|
|
2945
|
-
///
|
|
2946
|
-
///
|
|
2947
|
-
///
|
|
2948
|
-
///
|
|
3258
|
+
/// STORE'S — AND THE FORM CROSSES AT THREE MEMBERS FROM 2026-10-16** (`surface.md §2.5`'s clause of that
|
|
3259
|
+
/// date, items 3–4 and 10 (i)–(iii); `§2.12` item 1's mark of the same date).
|
|
3260
|
+
///
|
|
3261
|
+
/// **WHAT MOVES IS THE REACHABILITY OF `log` AND NOTHING ELSE.** The member `status` carries is still the
|
|
3262
|
+
/// store's `FileCommitFailed`, because no caller-side status can carry a `KC` token and a
|
|
3263
|
+
/// constraint-refused write is a commit that did not stand; **the kernel token does NOT enter `status`**
|
|
3264
|
+
/// (`A120` (2)'s rule survives whole). **A STORE VERB'S OWN REFUSAL CROSSES VERBATIM AND UNCONVERTED**
|
|
3265
|
+
/// (`fail-surface.md §1.2`): its `status` and its `message` are carried BYTE-FOR-BYTE, never re-mapped and
|
|
3266
|
+
/// never re-spelled, and `log` is ATTACHED BESIDE them as an own member — *"nothing is converted, and a
|
|
3267
|
+
/// member is added"* (`§2.5` item 10 (ii)).
|
|
3268
|
+
///
|
|
3269
|
+
/// **THE TWO ARMS, EACH AT ITS OWN FORM:**
|
|
3270
|
+
/// * **A `KC`-TOKEN REFUSAL — THE KERNEL'S OWN PASS PRODUCED IT.** Its `{status, message, log}` is the
|
|
3271
|
+
/// KERNEL'S OWN three-member form (`docs/specs/storeroom-constraints/fail-surface.md §1.1`, whose member
|
|
3272
|
+
/// set is the same three), and it would cross UNCHANGED were it not that `status` must carry the store's
|
|
3273
|
+
/// `FileCommitFailed` on this surface: **the `log` it carries is the attempt's, VERBATIM, and it crosses
|
|
3274
|
+
/// with the store-side `status` in its place.**
|
|
3275
|
+
/// * **A STORE VERB'S OWN REFUSAL.** Its `status` and `message` cross verbatim and `log` is attached beside
|
|
3276
|
+
/// them — the attempt's log where this write's own attempt holds one, and `[]` where it does not (a `K-2`
|
|
3277
|
+
/// the store refused opened no attempt, so there is no attempt at all — `§2.5` item 4).
|
|
3278
|
+
///
|
|
3279
|
+
/// **AND THE TIMING TRAP IS HONOURED, WHICH IS THE WHOLE OF ITEM 10 (iii): `log` IS TAKEN BEFORE THE
|
|
3280
|
+
/// ATTEMPT IS DISPOSED OF, NOT AFTER.** The kernel's terminal act has already run when this frame is
|
|
3281
|
+
/// reached (its `refuse` was thrown WITH the log in hand, `constraint-kernel.mjs`'s `refuse`), so the list
|
|
3282
|
+
/// read here is the list AS IT STOOD WHEN THE REFUSAL WAS BUILT — the failure arm's `outcome` entry
|
|
3283
|
+
/// included — and it is read OFF THE THROWN VALUE AND NEVER OFF A LATER READ: the registry entry is gone
|
|
3284
|
+
/// and a reader that reached for the attempt afterwards would reach nothing.
|
|
3285
|
+
///
|
|
3286
|
+
/// **⟶ THE FORGERY DISCRIMINATOR, RE-EXAMINED AND REPLACED 2026-10-16, BECAUSE THE RULING MADE THE OLD ONE
|
|
3287
|
+
/// UNSAFE — THIS IS THE HIGH-RISK EDIT AND IT IS NAMED WITH WHAT IT WAS AND WHAT IT IS.**
|
|
3288
|
+
///
|
|
3289
|
+
/// **WHAT IT WAS.** The previous pass fixed a broken forgery guard by discriminating on **`log`'s
|
|
3290
|
+
/// PRESENCE**: *a value carrying a `log` was the kernel's, and a value carrying none was the caller's.*
|
|
3291
|
+
/// That was sound only while the KERNEL'S OWN form was the only three-member form in the system.
|
|
3292
|
+
///
|
|
3293
|
+
/// **WHY IT NO LONGER SUFFICES.** `surface.md §2.5` item 4 now declares **`log` flat on EVERY failure this
|
|
3294
|
+
/// surface throws** — so every surface-produced failure carries one, **and so does a CALLER'S forged object
|
|
3295
|
+
/// that happens to carry a `log` member.** A caller's constraint body may throw
|
|
3296
|
+
/// `{status: 'ValueNotAdmitted', message: 'FORGED BY THE CALLER', log: []}` — a plain object it authored,
|
|
3297
|
+
/// carrying the member the old test looked for — **and under the old test that object was RE-WRAPPED into a
|
|
3298
|
+
/// fresh three-member object, so `caught === thrown` was `false` for a value the caller threw.** Measured on
|
|
3299
|
+
/// the tree before this edit: `forged {status,message,log} => caught===thrown: false`. **A caller's own
|
|
3300
|
+
/// throwable must surface AS ITSELF** (`fail-surface.md §1.1` item 5 — the body's exception *"propagates out
|
|
3301
|
+
/// of the kernel's own invocation, untouched and unconverted"*; `kernel-surface.md §2.3` item 1 — a body's
|
|
3302
|
+
/// throwable *"is NOT a kernel state and NOT a store state"*), **so the test had to stop reading a member
|
|
3303
|
+
/// the caller can forge.**
|
|
3304
|
+
///
|
|
3305
|
+
/// **WHAT REPLACED IT — IDENTITY, NOT SHAPE.** The kernel's own refusals are **built by the kernel**, and
|
|
3306
|
+
/// every one of them is thrown from `constraint-kernel.mjs`'s single `refuse` frame. The entry therefore
|
|
3307
|
+
/// **MARKS WHAT THE KERNEL BUILT**, at the one place the kernel's values enter this entry, **with a
|
|
3308
|
+
/// module-private `WeakSet`** — `kernelRefusals` above — **and this frame asks whether the handed value IS
|
|
3309
|
+
/// ONE OF THOSE VALUES, never whether it LOOKS LIKE one.** A caller cannot forge membership of a set it
|
|
3310
|
+
/// cannot reach, so:
|
|
3311
|
+
/// * a `KC`-token value the kernel built → **the kernel's arm**, and `FileCommitFailed` crossings below;
|
|
3312
|
+
/// * a store verb's own refusal (built by the addon, carrying the store's code) → the store's arm below;
|
|
3313
|
+
/// * **EVERYTHING ELSE IS THE CALLER'S AND CROSSES AS ITSELF** — a forged three-member object, a forged
|
|
3314
|
+
/// two-member object, a `TypeError`, a bare string, `undefined` — `caught === thrown` on all of them.
|
|
3315
|
+
///
|
|
3316
|
+
/// **THE MARK IS SET WHERE THE KERNEL'S FAILURE IS FIRST SEEN** — at the two `catch` frames in
|
|
3317
|
+
/// `constraintWrite` above, which are the only places a kernel-thrown value reaches this entry — and **NOT
|
|
3318
|
+
/// by a test over members, which is the whole defect being repaired.** **IT IS A `WeakSet` AND NOT A MEMBER
|
|
3319
|
+
/// ON THE VALUE**: no member is added to the kernel's own form (`fail-surface.md §1.1`'s member set stays the
|
|
3320
|
+
/// three), nothing is mutated, nothing is frozen, and the mark is invisible to every census — while a value
|
|
3321
|
+
/// that is not an object (a string, `undefined`) is simply never in the set and needs no special case, since
|
|
3322
|
+
/// `WeakSet.has` on a primitive is `false` rather than a throw.
|
|
3323
|
+
/// **THE KERNEL'S OWN REFUSAL-CLASS QUESTION, AND WHY THE ENTRY ASKS THE KERNEL IT RATHER THAN READING A
|
|
3324
|
+
/// MEMBER** — the discriminator that replaced `log`'s presence, and the reason a `WeakSet` local to this
|
|
3325
|
+
/// entry will not do.
|
|
3326
|
+
///
|
|
3327
|
+
/// **THE MARK CANNOT LIVE HERE, AND THAT WAS MEASURED RATHER THAN REASONED:** a `WeakSet` populated from the
|
|
3328
|
+
/// two `catch` frames in `constraintWrite` marks **EVERY** value leaving the kernel's frames — **a caller's
|
|
3329
|
+
/// constraint BODY throws from inside `runAttempt` too**, so the body's own throwable passes the same frame
|
|
3330
|
+
/// and is marked alongside the kernel's. On the tree with the `WeakSet` in place, all three of
|
|
3331
|
+
/// `forged {status,message}`, `forged {status,message,log}` and `TypeError` answered `caught === thrown:
|
|
3332
|
+
/// false`: **the mark was set by the frame and not by the author of the value.** A mark is only worth
|
|
3333
|
+
/// anything if the thing that SETS it is the thing that BUILT the value, and for a kernel refusal that thing
|
|
3334
|
+
/// is `constraint-kernel.mjs`'s own `refuse`.
|
|
3335
|
+
///
|
|
3336
|
+
/// **SO THE KERNEL DECLARES IT, AT ITS ONE THROW SITE, UNDER A `Symbol.for` KEY BOTH SIDES SPELL** — exactly
|
|
3337
|
+
/// the pattern `SETTLED_ON_THE_PASSING_ARM` and `SAVE_FAILED_AT_THE_TERMINAL_ARM` already use across this
|
|
3338
|
+
/// same boundary (`constraint-kernel.mjs`'s `KERNEL_REFUSAL`): the entry imports no kernel at load and the
|
|
3339
|
+
/// kernel imports no entry, and **a symbol key is invisible to `Object.keys`**, so the thrown form's readable
|
|
3340
|
+
/// member set stays the three `§2.5` items 3–4 declare (`§2.5` item 9's census reads `["log","message",
|
|
3341
|
+
/// "status"]` and no fourth). **A CALLER'S BODY CANNOT SET IT**: the mark is written in a frame no caller
|
|
3342
|
+
/// reaches, and it is not a member a caller would think to spell.
|
|
3343
|
+
///
|
|
3344
|
+
/// **AND A KERNEL THAT DID NOT CARRY THE DECLARATION ANSWERS `false`** — every value is then the caller's and
|
|
3345
|
+
/// surfaces as itself, which is the safe direction: a refusal crossed unconverted is the declared form once
|
|
3346
|
+
/// the surface stops re-wrapping it, while a caller's value crossed converted is the FINDING this whole
|
|
3347
|
+
/// discriminator exists to prevent.
|
|
3348
|
+
|
|
3349
|
+
/// **THE SAME `Symbol.for` KEY THE KERNEL WRITES, SPELLED HERE SO THE ENTRY IMPORTS NO KERNEL AND THE KERNEL
|
|
3350
|
+
/// IMPORTS NO ENTRY** — the pattern `SETTLED_ON_THE_PASSING_ARM` and `SAVE_FAILED_AT_THE_TERMINAL_ARM`
|
|
3351
|
+
/// already cross this boundary by (`constraint-kernel.mjs`'s `KERNEL_REFUSAL`).
|
|
3352
|
+
///
|
|
3353
|
+
/// **IT IS A SYMBOL AND NOT A KERNEL FUNCTION, AND THE REASON IS A SPEC COUNT: `kernel-surface.md §1` item 2
|
|
3354
|
+
/// declares that module's export set as EXACTLY the five `K-1`–`K-5` items — *"no sixth name"* — so a
|
|
3355
|
+
/// predicate exported from the kernel to serve this entry would be a FINDING.** The fact travels on the
|
|
3356
|
+
/// VALUE, under a key both sides spell, and the kernel's namespace is untouched.
|
|
3357
|
+
///
|
|
3358
|
+
/// **THE QUESTION IS ANSWERED WITHOUT REACHING THE KERNEL AT ALL**, which is the shape `WeakSet.has` gave
|
|
3359
|
+
/// for free and is what lets this entry keep loading where nothing is staged beside it: no `require` of
|
|
3360
|
+
/// `./src/` is triggered by a failure's own classification.
|
|
3361
|
+
const KERNEL_REFUSAL = Symbol.for('provident-storeroom.kernel-refusal');
|
|
3362
|
+
|
|
3363
|
+
/// **WHETHER THE HANDED VALUE IS A REFUSAL THE KERNEL ITSELF BUILT** — the discriminator that replaced
|
|
3364
|
+
/// `log`'s presence, answered by the mark the kernel's one `refuse` frame sets and by nothing a caller can
|
|
3365
|
+
/// spell. **A NON-OBJECT IS `false`** without a member read, and **a value the kernel never built is
|
|
3366
|
+
/// `false`** whatever members it carries.
|
|
3367
|
+
function isKernelBuiltRefusal(value) {
|
|
3368
|
+
return value !== null && typeof value === 'object' && value[KERNEL_REFUSAL] === true;
|
|
3369
|
+
}
|
|
3370
|
+
|
|
2949
3371
|
function constraintCrossing(refusal) {
|
|
2950
|
-
const
|
|
2951
|
-
|
|
3372
|
+
const isObject = refusal !== null && typeof refusal === 'object';
|
|
3373
|
+
const status = isObject ? refusal.status : undefined;
|
|
3374
|
+
// **THE CALLER'S OWN VALUE CROSSES AS ITSELF, FIRST AND UNCONDITIONALLY.** The test is IDENTITY against
|
|
3375
|
+
// the kernel's marked set (above) and NOT any member's presence: a caller's forged `log`, a forged
|
|
3376
|
+
// `status` spelling and a forged two-member object are all its own, and `caught === thrown` holds for
|
|
3377
|
+
// each (`fail-surface.md §1.1` item 5). A value that is not an object at all is never the kernel's either.
|
|
3378
|
+
if (!isObject || isKernelBuiltRefusal(refusal) === false) throw refusal;
|
|
3379
|
+
// THE LOG IS THE THROWN VALUE'S OWN `log` MEMBER — the same list either arm carries — and `[]` where the
|
|
3380
|
+
// value carries none (`§2.5` item 4: never absent, never `null`, never a non-array; a non-array here is a
|
|
3381
|
+
// finding at the site that produced it and is answered with the empty array rather than a shape).
|
|
3382
|
+
// **AND IT IS TAKEN HERE, BEFORE THE ATTEMPT IS DISPOSED OF** — item 10 (iii)'s timing trap: the list is
|
|
3383
|
+
// READ OFF THE THROWN VALUE, which the kernel built with the log in hand, and never off a later read.
|
|
3384
|
+
const log = Array.isArray(refusal.log) ? refusal.log : [];
|
|
3385
|
+
// **A MARKED VALUE WHOSE `status` IS NOT A `KC` TOKEN IS THE STORE VERB'S OWN REFUSAL CROSSING BACK
|
|
3386
|
+
// THROUGH THE KERNEL'S OWN LEG** (`constraint-kernel.mjs`'s `attempt.throwState` carries the store's code
|
|
3387
|
+
// at the repair arm): its `status` and `message` cross VERBATIM and `log` is attached BESIDE them —
|
|
3388
|
+
// *"nothing is converted, and a member is added"* (`§2.5` item 10 (ii)).
|
|
3389
|
+
if (typeof status !== 'string' || KC_TOKENS.includes(status) === false) {
|
|
3390
|
+
throw {
|
|
3391
|
+
status: refusal.status,
|
|
3392
|
+
message: refusal.message,
|
|
3393
|
+
log: refusalLog(log),
|
|
3394
|
+
};
|
|
3395
|
+
}
|
|
3396
|
+
// **THE KERNEL'S OWN `KC` REFUSAL.** Its `{status, message, log}` is the KERNEL'S OWN three-member form
|
|
3397
|
+
// (`docs/specs/storeroom-constraints/fail-surface.md §1.1`), and it crosses with the STORE's
|
|
3398
|
+
// `FileCommitFailed` in `status` because no caller-side status can carry a `KC` token and a
|
|
3399
|
+
// constraint-refused write is a commit that did not stand: **the kernel token does NOT enter `status`, and
|
|
3400
|
+
// the `log` it carries is the attempt's, VERBATIM.**
|
|
2952
3401
|
throw {
|
|
2953
3402
|
status: 'FileCommitFailed',
|
|
2954
3403
|
message: typeof refusal.message === 'string'
|
|
2955
3404
|
? refusal.message
|
|
2956
3405
|
: 'the write was refused by a constraint of this attempt',
|
|
3406
|
+
log: refusalLog(log),
|
|
2957
3407
|
};
|
|
2958
3408
|
}
|
|
2959
3409
|
|