provident-storeroom 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.guide.md +166 -0
- package/index.d.ts +65 -0
- package/index.mjs +68 -12
- package/package.json +6 -6
- package/src/entry/constraints.mjs +941 -109
- package/src/entry/delivery.mjs +19 -4
- package/src/entry/frame.mjs +2 -1
- package/src/entry/kernel-attempt.mjs +151 -16
- package/src/entry/kernel-commit.mjs +2 -2
- package/src/entry/kernel-foundations.mjs +94 -3
- package/src/entry/kernel-registration.mjs +64 -10
- package/src/entry/state.mjs +377 -5
|
@@ -4,19 +4,26 @@ import { appendOwn, fail, refusalLog } from './refusal.mjs';
|
|
|
4
4
|
import { withAddon, require_ } from './artefact.mjs';
|
|
5
5
|
import { classSpelling, isAdmittedArray, isPlainObjectValue } from './class-decision.mjs';
|
|
6
6
|
import { constraintAddress } from './frame.mjs';
|
|
7
|
-
import { homeAddressKey, isStoreReceiver, openCommits } from './state.mjs';
|
|
7
|
+
import { currentWindow, homeAddressKey, installRestartConsumer, isStoreReceiver, openCommits, closeCommit, openCommit, windowMark } from './state.mjs';
|
|
8
8
|
// **THE KERNEL'S OWN RECORD, FOR ONE FIELD AND ONE ONLY** (`D-46`/`D-30`): `kernelFor(store)` answers the
|
|
9
9
|
// instance's kernel record — the same accessor every kernel act takes the instance through — and
|
|
10
10
|
// `reversalAtRest` below reads that record's own `live` map for the count of OPEN ATTEMPTS. `kernel-foundations`
|
|
11
11
|
// carries NO import of its own (`kernel-surface.md §1` item 1's empty-footprint clause), so this reach adds no
|
|
12
12
|
// load path, no addon call and no store act; it is a FIELD READ of state the instance already owns, taken the
|
|
13
13
|
// way the kernel's four part modules take it.
|
|
14
|
-
|
|
14
|
+
//
|
|
15
|
+
// **⟶ AND `append` FROM 2026-10-27 — THE ONE ORDINAL MINTING SITE, TAKEN FOR THE REPORT'S OWN COPY OF THE
|
|
16
|
+
// RESTARTED CHECK'S ENTRY (`carryRestartRefusal`).** The entry that reaches a driver through the closed
|
|
17
|
+
// report is IN THE ATTEMPT'S LOG, whose entries carry `seq` ascending from `1` (`kernel-surface.md §2.5` item
|
|
18
|
+
// 1; `assertLogEntry`'s own member set). The copy is therefore minted by the kernel's own append — the same
|
|
19
|
+
// function the pass appends with — rather than pushed here with a member set of its own; the REFUSAL's own
|
|
20
|
+
// list keeps its five members and no `seq`, because no attempt stands at the judgement that built it
|
|
21
|
+
// (`D-41` item 4). Two records, two honest forms, one append.
|
|
22
|
+
import { append, externalCall, kernelFor } from './kernel-foundations.mjs';
|
|
15
23
|
// **⟶ AND THE CARRIERS, ADDED 2026-10-26 FOR THE REFUSAL'S OWN UNDOING (`DEF-W`'s `(a)`).** The
|
|
16
24
|
// compensating act below reaches the store's own verb at its entry, with the SAME carrier forms every member
|
|
17
25
|
// hands it (`carrier.mjs` is the boundary's one encoder for the three positions and imports nothing of this
|
|
18
26
|
// file, so this reach adds no cycle and no second conversion rule).
|
|
19
|
-
import { encodeAddress, encodeTier, encodeValue } from './carrier.mjs';
|
|
20
27
|
|
|
21
28
|
// ═══════════════════════════════════════════════════════════════════════════════════════════════════════
|
|
22
29
|
// THE POST-CREATION CONSTRAINT SET — `surface.md §2.12` items 1–5, `A126` (2026-10-16), AND ITS TWO ROUTES
|
|
@@ -750,6 +757,15 @@ function carriesConstraintAt(state, address) {
|
|
|
750
757
|
*/
|
|
751
758
|
export function constraintWrite(state, instance, address, tier, value) {
|
|
752
759
|
const kernel = constraintsKernel();
|
|
760
|
+
// **⟶ THE EPOCH RULE'S FRAME IS GONE WITH THE CONSUMER IT GUARDED, 2026-10-27 — `D-42`'s REQUEST NOW NAMES
|
|
761
|
+
// THE WINDOW THAT RAISED IT (`state.mjs`'s `currentWindow`), AND `runAttempt`'s drain COMPARES THE TWO
|
|
762
|
+
// IDENTITIES.** The bytes that stood here were `if (CHECK_DEPTH === 0) clearStaleRestart(instance);` and
|
|
763
|
+
// `CHECK_DEPTH += 1;`, with a matching clear at the failing arm and a decrement in the `finally`: a stack
|
|
764
|
+
// depth in THIS frame standing in for *"a request belongs to the act that raised it"* (`D-42` item `3`).
|
|
765
|
+
// **THEY ARE DELETED, NOT MOVED** — the fact they approximated is now the store's own (a commit identity,
|
|
766
|
+
// minted with the opening and answered by every joining call), so there is no counting frame to be found in
|
|
767
|
+
// the wrong place and none to be bypassed by a driver that never reaches this member. **ONE MECHANISM, NOT
|
|
768
|
+
// TWO.**
|
|
753
769
|
let record;
|
|
754
770
|
try {
|
|
755
771
|
record = kernel.commit(instance, address, tier, value);
|
|
@@ -761,8 +777,30 @@ export function constraintWrite(state, instance, address, tier, value) {
|
|
|
761
777
|
try {
|
|
762
778
|
report = kernel.runAttempt(instance, record);
|
|
763
779
|
} catch (refusal) {
|
|
780
|
+
// **A FAILING ATTEMPT IS THE TERMINAL CALL'S OWN REFUSAL, AND ITS FLOOR HAS ALREADY PUT THE STORE BACK
|
|
781
|
+
// TO THE STATE IT FOUND** (`D-40`) — and the restart does not run over a floor-restored state, **NOW BY
|
|
782
|
+
// CONSTRUCTION RATHER THAN BY THIS FRAME'S CARE**: `runAttempt`'s drain is reached only where its pass
|
|
783
|
+
// answered a report, and a failing pass throws before the drain (the passing arm alone, `D-42` item
|
|
784
|
+
// `2`'s own reading, taken structurally). A request the failing pass's bodies raised stands with that
|
|
785
|
+
// pass's window identity and dies at the next pass's drain — **A FAILING NESTED WRITE's request is in the
|
|
786
|
+
// ENCLOSING window, so the delivery's outer pass still consumes it, exactly as the old outer-frame clear
|
|
787
|
+
// left it in hand.**
|
|
764
788
|
constraintCrossing(refusal);
|
|
765
789
|
}
|
|
790
|
+
// **⟶ AND THE RESTART'S REFUSAL, WHERE THE RESTARTED CHECK REFUSED — `D-42` (2026-10-27), REACHED THROUGH
|
|
791
|
+
// THE REPORT SINCE 2026-10-27.** The attempt's own terminal arm returned (its pass, its save and its
|
|
792
|
+
// delivery all ran, so a listener body's `rollback` and a constraint body's `rollback` have both been
|
|
793
|
+
// taken), and `runAttempt` — INSIDE ITS OWN COMMIT SCOPE — drained the request and re-ran the check from
|
|
794
|
+
// its beginning (`drainRestartRequests`). **WHAT THIS FRAME DOES NOW IS REFUSE, AND IT REFUSES WITH THE
|
|
795
|
+
// VERY VALUE THE RESTARTED CHECK BUILT** — carried on the report under the symbol both sides spell, and
|
|
796
|
+
// thrown here as itself: the same plain `{status, message, log}`, the same rank-`20` status, one log entry,
|
|
797
|
+
// and the store already restored by that refusal's own compensating act. **NOTHING IS RE-RENDERED AND NO
|
|
798
|
+
// SENTENCE IS AUTHORED HERE** (`DD-52`). **A WRITE WHOSE WINDOW HELD ONLY LAWFUL ACTIONS FINDS NO CARRIED
|
|
799
|
+
// REFUSAL AND RETURNS ITS RECORD UNCHANGED.**
|
|
800
|
+
const restarted = report !== null && typeof report === 'object' ? report[RESTART_REFUSAL] : undefined;
|
|
801
|
+
if (restarted !== undefined) {
|
|
802
|
+
constraintCrossing(restarted);
|
|
803
|
+
}
|
|
766
804
|
// **⟶ THE PASSING ARM RETURNS THE REPORT THE ATTEMPT ITSELF BUILT — `D-40`'S SECOND HALF (`DEF-M` (2)),
|
|
767
805
|
// 2026-10-26.** **WHAT IT WAS:** `return answer` returned the **STORE LEG'S** record — the one `index.mjs`
|
|
768
806
|
// builds from the store's first reply at this verb — and DISCARDED the report `runAttempt` had just
|
|
@@ -946,6 +984,24 @@ const BODY_THREW_STATUS = 'ConstraintBodyThrew';
|
|
|
946
984
|
/// by save failures only.
|
|
947
985
|
const CONSTRAINT_PASS_REFUSED = 'ConstraintPassRefused';
|
|
948
986
|
|
|
987
|
+
/// **THE SET'S FIFTEENTH MEMBER, SPELLED ONCE — AND THE ONE THING THE RESTORE'S SAVE CAN ANSWER** (`src/error.rs`'s
|
|
988
|
+
/// `CODES`, `[&str; 20]`, rank `15`; `§8.1` #15 and `§8.2`'s row). **IT IS READ HERE TO CLASSIFY THE STORE'S ANSWER
|
|
989
|
+
/// AND IS NEVER MINTED HERE** (`DD-40`): `restoreMark` answers it when the restore's own save cannot land, and
|
|
990
|
+
/// **that arm is NOT a refused mark** — the store's replay has already run, so the in-memory state IS the restored
|
|
991
|
+
/// state and only the bytes at the path were not updated (`src/store.rs`'s `restoreMark`, 2026-10-27).
|
|
992
|
+
const FILE_COMMIT_FAILED = 'FileCommitFailed';
|
|
993
|
+
|
|
994
|
+
/// **WHETHER THE STORE'S ANSWER TO THE MARK IS ITS SAVE'S FAILURE RATHER THAN A REFUSED MARK** — the two arms
|
|
995
|
+
/// `restoreMark` can answer with an error, told apart by the status they carry and by nothing else. **A REFUSED
|
|
996
|
+
/// MARK** (`JournalOpUnknown`, `AddressMalformed`) leaves the store at the state it held, so nothing may be
|
|
997
|
+
/// counted as restored; **A FAILED SAVE** (`FileCommitFailed`) leaves the restore's state STANDING in memory and
|
|
998
|
+
/// only the file behind it stale. The answer is the refusal record itself on the save arm and `null` otherwise.
|
|
999
|
+
function saveRefused(refused) {
|
|
1000
|
+
if (refused === null || typeof refused !== 'object') return null;
|
|
1001
|
+
const status = ownDataMember(refused, 'status');
|
|
1002
|
+
return status === FILE_COMMIT_FAILED ? refused : null;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
949
1005
|
/// **WHETHER THE HANDED VALUE CARRIES THE KERNEL'S BODY-THROW MARK, AND WHAT THE MARK CARRIES** — the mark's
|
|
950
1006
|
/// presence is the identity and the record under it is the two slots the generator's sentence needs. **A
|
|
951
1007
|
/// NON-OBJECT IS `null`** without a member read, and **a value the kernel never caught from a body is `null`**
|
|
@@ -1190,6 +1246,29 @@ function constraintCrossing(refusal) {
|
|
|
1190
1246
|
/// measurement of convenience: judging a step *"would invoke bodies mid-attempt and break `D-40`'s 'leaves
|
|
1191
1247
|
/// the store exactly as it found it'"* (`§2.6` item 1). A verb window is in flight whatever its attempt map
|
|
1192
1248
|
/// says, and its state is not the state that stands.
|
|
1249
|
+
///
|
|
1250
|
+
/// **⟶ AND THE SECOND DIRECTION IS CLOSED BY `D-44`, 2026-10-27 — THE PARAGRAPH ABOVE IS READ THROUGH THIS
|
|
1251
|
+
/// ONE AND NOTHING BELOW IT MOVES.** *"There should be no state where a constraint is being checked without an
|
|
1252
|
+
/// open commit. Any action that would cause a constraint check should open a commit before beginning"*
|
|
1253
|
+
/// (`strata/decisions.md` · `D-44`), and the state it names by hand is exactly the one printed above: *"`D-42`'s
|
|
1254
|
+
/// window `4` (a pass driven by hand, `open=0`/`live=1`): **that state must not exist**."* **SO A PASS DRIVEN
|
|
1255
|
+
/// STRAIGHT THROUGH `K-2`/`K-3` NOW SEES `open` `1`, `live` `1`** — the pass opens its own scope
|
|
1256
|
+
/// (`kernel-attempt.mjs`'s `runAttempt`, through the `commit-scope` channel `state.mjs` installs) — **and
|
|
1257
|
+
/// `reversalAtRest` IS UNMOVED**: both conjuncts stand, the restart is not a third conjunct, and a reversal
|
|
1258
|
+
/// inside a directly driven pass is still a STEP (the `live` conjunct decides it now, where before either
|
|
1259
|
+
/// conjunct would have).
|
|
1260
|
+
///
|
|
1261
|
+
/// **⟶ AND THE PARAGRAPH JUST ABOVE IS SUPERSEDED ON ONE SENTENCE, 2026-10-27 — THIS FILE DOES NOW CONSUME THAT
|
|
1262
|
+
/// PASS'S REQUEST, AND IT DOES SO WHERE THE SCOPE IS OWNED.** The bytes that stood here read *"WHAT THIS FILE
|
|
1263
|
+
/// STILL DOES NOT DO FOR THAT PASS IS CONSUME ITS REQUEST: the restart's only consumer is `constraintWrite`'s
|
|
1264
|
+
/// `restartInvalidatedCheck`, and a directly driven pass has no such frame above it, so a body's request dies
|
|
1265
|
+
/// with its window through the epoch rule (`clearStaleRestart`)"*, and **`clearStaleRestart` and the
|
|
1266
|
+
/// `CHECK_DEPTH` frame that guarded it are DELETED with that sentence** (`drainRestartRequests` below; the
|
|
1267
|
+
/// request now names the window that raised it, `currentWindow` in `state.mjs`). **`D-44`'s declared consequence
|
|
1268
|
+
/// is delivered rather than restated** — *"If every check has a commit, every request has a consumer, and the
|
|
1269
|
+
/// consumer stops being a property of one call site"* — **and `reversalAtRest` is STILL UNMOVED**: the
|
|
1270
|
+
/// conjunction keeps both conjuncts, the restart is not a third conjunct, and the invariant stays the
|
|
1271
|
+
/// PRECONDITION of the check (`open` `≥` `1`), enforced at the check.
|
|
1193
1272
|
/// **SO THE DISCRIMINATOR ANSWERS *AT REST* IFF BOTH ARE ZERO**, which matches the clause's words and its
|
|
1194
1273
|
/// reason at once, **AND IT STILL CANNOT FAIL**: the open-commit count is taken through `state.mjs`'s
|
|
1195
1274
|
/// exported `openCommits(store)` — a PLAIN ACCESSOR over the same index the channel reads, NOT the channel
|
|
@@ -1208,11 +1287,334 @@ function reversalAtRest(instance) {
|
|
|
1208
1287
|
return openCommits(instance) === 0 && kernelFor(instance).live.size === 0;
|
|
1209
1288
|
}
|
|
1210
1289
|
|
|
1290
|
+
// ═══════════════════════════════════════════════════════════════════════════════════════════════════════
|
|
1291
|
+
// **⟶ ADDED 2026-10-27 — `D-42`: AN ACTION INSIDE AN OPEN COMMIT RESTARTS THE CONSTRAINT CHECK**
|
|
1292
|
+
// ═══════════════════════════════════════════════════════════════════════════════════════════════════════
|
|
1293
|
+
//
|
|
1294
|
+
// **THE RULING IS THE ARCHITECT'S, VERBATIM: *"Actions inside of an open commit start the constraint check
|
|
1295
|
+
// over again."*** (`strata/decisions.md` · `D-42`). **THE WINDOW IT CLOSES, AS THE DOWNSTREAM MEASURED IT:** a
|
|
1296
|
+
// reversal issued INSIDE an open commit — from a listener body, from a constraint body — was UNJUDGED (the
|
|
1297
|
+
// conjunction above), **so its violating effect STOOD** — *"zero judgement invocations inside a body, while
|
|
1298
|
+
// the identical call one frame out is refused and restored"* (`D-41` item `3`), **the conservative direction
|
|
1299
|
+
// turned out to be the permissive one.**
|
|
1300
|
+
//
|
|
1301
|
+
// **THE ANSWER IS NEITHER TO JUDGE THE STEP NOR TO LEAVE IT.** **Judging the reversal at its own instant is
|
|
1302
|
+
// what the conjunction refuses and `D-38` refuses by name** (a per-step check of an intermediate state,
|
|
1303
|
+
// invoking bodies mid-attempt). **So the action is RECORDED and the check it invalidated IS RESTARTED — from
|
|
1304
|
+
// its beginning — at the one place the check runs and once the window that held it has finished:**
|
|
1305
|
+
// * **NOT A PER-STEP JUDGEMENT**: the `rollback` call itself still answers its declared record
|
|
1306
|
+
// (`{opId, undoneOps, restoredTo}`, `PAR-JS-9`), no body is invoked at its instant, and the reversal is
|
|
1307
|
+
// never judged *as a step*;
|
|
1308
|
+
// * **NOT A RE-ENTRY INTO THE ATTEMPT**: the attempt's own pass is untouched; what restarts is the check
|
|
1309
|
+
// the action invalidated — the reversal's judgement — and it runs as a FRESH pass over EVERY enabled pair
|
|
1310
|
+
// from the first, against the state the action left (`judgeReversal` over the watch below);
|
|
1311
|
+
// * **NOT MID-UNWIND**: the kernel's own unwinding (`kernel-terminal.mjs`'s `composeRollback`) reaches the
|
|
1312
|
+
// addon's `rollback` entry DIRECTLY and never this member, so it raises no restart and invokes no body
|
|
1313
|
+
// inside the composition. **A RESTART IS ONLY EVER RAISED BY A CONSUMER'S OWN `rollback` MEMBER CALL.**
|
|
1314
|
+
//
|
|
1315
|
+
// **THE CHECK'S OWN BEGINNING IS THE WATCH'S WALK** (`watchStanding` below): every enabled pair's every
|
|
1316
|
+
// address, in `D-39`'s registration order — the same first address and the same first pair the at-rest
|
|
1317
|
+
// judgement begins at. **THE RESTART THEREFORE ASKS THE SAME CHECK THE AT-REST CONTROL ASKS, at the state
|
|
1318
|
+
// the action left**, which is why its outcome is the declared one member for member: the one plain form
|
|
1319
|
+
// (`{status, message, log}`), the set's rank-`20` member `ConstraintPassRefused`, and **the store restored by
|
|
1320
|
+
// the refusal's own compensating act** (`restoreReversal` → the store's `restoreMark`, the journal's head —
|
|
1321
|
+
// and a reversal appends no journal entry, so that head describes the state that stood BEFORE the action).
|
|
1322
|
+
//
|
|
1323
|
+
// **TERMINATION, AND WHAT BOUNDS IT.** A restart asks pair bodies, and a pair body MAY ACT (it is the
|
|
1324
|
+
// caller's code): an action raised while a restart is running raises a NEW request, which the same loop
|
|
1325
|
+
// consumes — so a body that acts on every ask would otherwise restart the check for ever. **THE LOOP IS
|
|
1326
|
+
// BOUNDED AT `RESTART_LIMIT` RESTARTS PER PASS SCOPE** (`drainRestartRequests`; the frame moved from the
|
|
1327
|
+
// terminal call to the check's own scope on 2026-10-27, and the figure and the never-reset rule did not), and the budget is
|
|
1328
|
+
// SPENT, not reset, by a request raised inside a restart. **A CHECK THAT WILL NOT SETTLE IS A CHECK THAT DOES
|
|
1329
|
+
// NOT PASS** (`D-41` item `4`'s own direction: *"a reversal nobody could judge is a reversal nobody could
|
|
1330
|
+
// approve"*), so the arm past the budget refuses — the same plain form, the same rank-`20` status, the same
|
|
1331
|
+
// compensating restore — and its one log entry says the budget was spent. **THE MEASURED COUNT IS THE
|
|
1332
|
+
// CELL'S**: `tests/e2e/in-commit-restart.test.mjs` drives a pair that acts on every ask and reads the ask
|
|
1333
|
+
// count the bound produces.
|
|
1334
|
+
|
|
1335
|
+
/// **THE PER-INSTANCE RESTART RECORD, AND IT IS THE INSTANCE'S OWN** (`D-30`; `D-46`): a `WeakMap` keyed by
|
|
1336
|
+
/// the store object, so a second store is a second record, the record dies with its store, and **NO MEMBER IS
|
|
1337
|
+
/// ADDED TO THE PRODUCT, TO A RECORD OR TO THE KERNEL** (`A117` (D6)'s four-member guardrail is untouched).
|
|
1338
|
+
///
|
|
1339
|
+
/// **`pending` IS THE REQUEST** — `{ watched, reversalId, window }`:
|
|
1340
|
+
/// * `watched` the check's own beginning captured BEFORE the action ran (`reversalWatch`);
|
|
1341
|
+
/// * `reversalId` the store's own echo of the id the reversal named (attached by `judgeReversal` in the same
|
|
1342
|
+
/// frame, one line after the action);
|
|
1343
|
+
/// * **⟶ `window` the IDENTITY OF THE COMMIT THE ACTION WAS TAKEN IN** (`state.mjs`'s `currentWindow`, minted
|
|
1344
|
+
/// with the opening and answered by every joining call), **ADDED 2026-10-27 — AND IT IS WHAT RETIRES THE
|
|
1345
|
+
/// COUNTING FRAME.** `D-42`'s own sentence is *"a request belongs to the act that raised it"*; while the
|
|
1346
|
+
/// only consumer was `constraintWrite` that fact had to be approximated by a stack depth in that frame
|
|
1347
|
+
/// (`CHECK_DEPTH`, whose one read cleared a request at the outermost write). **The store already knows
|
|
1348
|
+
/// which commit is open** — it opened it — so the request now NAMES that commit and the consumer compares
|
|
1349
|
+
/// the two identities. A request raised in a window whose check never ran (a `delete`'s delivery is the one
|
|
1350
|
+
/// the declaration names) therefore dies at the next pass's drain **by identity and not by inference**, and
|
|
1351
|
+
/// a request raised earlier in the SAME window (a listener body's, consumed by a nested write's own drain or
|
|
1352
|
+
/// by the enclosing pass's) still belongs to that window and is still consumed.
|
|
1353
|
+
const RESTARTS = new WeakMap();
|
|
1354
|
+
|
|
1355
|
+
/// **HOW MANY RESTARTS ONE PASS'S COMMIT SCOPE MAY TAKE** — the bound `drainRestartRequests` spends. Three is
|
|
1356
|
+
/// the declared figure: two fewer than any arm of this package's own batteries drives, and enough that a lawful
|
|
1357
|
+
/// in-commit action's single restart never meets it.
|
|
1358
|
+
///
|
|
1359
|
+
/// **⟶ AND WHAT IT NOW COUNTS IS *RESTARTS PER SCOPE*, NOT PER WRITE, 2026-10-27.** The figure and the
|
|
1360
|
+
/// spend-and-never-reset rule are unmoved (`D-42` item `3`); **what moved with the consumer is the frame the
|
|
1361
|
+
/// count belongs to**: one drain is one pass's scope — the pass the kernel ran, direct or production — and a
|
|
1362
|
+
/// request raised INSIDE a restart is consumed by that same drain and spends that same budget. **A NESTED
|
|
1363
|
+
/// pass (a listener body's own write) is a scope of its own and has its own budget**, exactly as the nested
|
|
1364
|
+
/// `constraintWrite` frame had its own before the move; the count was never shared across nesting levels and is
|
|
1365
|
+
/// not now.
|
|
1366
|
+
export const RESTART_LIMIT = 3;
|
|
1367
|
+
|
|
1368
|
+
/// **THE RESTART RECORD, CREATED ON THE FIRST ACTION AND NEVER ON A LAWFUL WRITE'S PATH**: the read is a
|
|
1369
|
+
/// `WeakMap.get` and the creation happens only in `reversalWatch`'s in-flight arm.
|
|
1370
|
+
function restartRecord(instance) {
|
|
1371
|
+
let record = RESTARTS.get(instance);
|
|
1372
|
+
if (record === undefined) {
|
|
1373
|
+
record = { pending: null };
|
|
1374
|
+
RESTARTS.set(instance, record);
|
|
1375
|
+
}
|
|
1376
|
+
return record;
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
/// **⟶ THE RESTART ITSELF, MOVED 2026-10-27 TO WHERE THE COMMIT SCOPE IS OWNED — `runAttempt`'s drain.**
|
|
1380
|
+
///
|
|
1381
|
+
/// **WHAT IT WAS, AND THE FINDING THAT MOVED IT.** It was `restartInvalidatedCheck(instance)`, called by
|
|
1382
|
+
/// `constraintWrite` after the write's terminal call, and its own header said so: *"it is reached at the ONE
|
|
1383
|
+
/// place the check runs after the window that held the action has finished: `constraintWrite`."* **`D-44` then
|
|
1384
|
+
/// made every check run inside a commit scope and named the consequence it could not yet deliver** — *"If every
|
|
1385
|
+
/// check has a commit, every request has a consumer, and the consumer stops being a property of one call
|
|
1386
|
+
/// site"* — **and the window it left is measured at `tests/e2e/direct-pass-commit-invariant.test.mjs`: a pass
|
|
1387
|
+
/// driven straight through `K-2`/`K-3` has no `constraintWrite` frame above it**, so a constraint body's
|
|
1388
|
+
/// violating `rollback` inside it was neither judged at its instant nor restarted, and the pair was never asked
|
|
1389
|
+
/// at the state the action left.
|
|
1390
|
+
///
|
|
1391
|
+
/// **SO THE CONSUMER IS NOW THE PASS'S OWN SCOPE.** `kernel-attempt.mjs`'s `runAttempt` runs its pass inside
|
|
1392
|
+
/// `state.mjs`'s commit scope and then calls the store's `restart-drain` channel **inside that same scope**,
|
|
1393
|
+
/// handing the report the pass answered with; this function is the implementation that channel is given
|
|
1394
|
+
/// (`installRestartConsumer` below). **ONE MECHANISM, NOT TWO**: there is no second consumer, no counting frame
|
|
1395
|
+
/// and no call site to be bypassed — the pass that asks the pairs is the frame that consumes what its own
|
|
1396
|
+
/// bodies raised, whichever driver called it.
|
|
1397
|
+
///
|
|
1398
|
+
/// **EACH ROUND CONSUMES ONE REQUEST OF THIS WINDOW AND ASKS EVERY ENABLED PAIR THE WATCH CARRIED, IN ORDER,
|
|
1399
|
+
/// AT THE STATE THE ACTION LEFT** (`judgeReversal`: the `moved` test, the first-violating-pair rule and the
|
|
1400
|
+
/// refusal's restoring compensation are that function's own and are not re-implemented here). **THE ROUND IS
|
|
1401
|
+
/// THE RE-RUN**: the attempt's own pass is untouched and not re-entered (`D-42`: *"NOT A RE-ENTRY INTO THE
|
|
1402
|
+
/// ATTEMPT"*); what restarts is the check the action invalidated, from its first pair, at the state the action
|
|
1403
|
+
/// left.
|
|
1404
|
+
///
|
|
1405
|
+
/// **A VIOLATION IS CARRIED INTO THE REPORT AND NOT THROWN OUT OF THE KERNEL** (`carryRestartRefusal` below):
|
|
1406
|
+
/// `runAttempt` answers a report whose `outcome` is `'failed'` and whose log holds the refusal's entry, and
|
|
1407
|
+
/// `constraintWrite` — the entry — is the frame that refuses on the write's path. **THAT IS THE ONE FORM BOTH
|
|
1408
|
+
/// DRIVERS CAN READ**: a write meets the same plain `{status, message, log}` it met before (the carried refusal,
|
|
1409
|
+
/// byte for byte), and a bare `K-3` meets a REPORT that says the restarted pass refused — it never throws,
|
|
1410
|
+
/// because the pass it was asked to run passed and the refusal is a later check's.
|
|
1411
|
+
///
|
|
1412
|
+
/// **A LAWFUL STATE REFUSES NOTHING**: the round asks and passes, the request is consumed, and the report
|
|
1413
|
+
/// stands exactly as the pass built it (`outcome` `'passed'`), so a write whose window held only lawful actions
|
|
1414
|
+
/// returns its own record unchanged.
|
|
1415
|
+
///
|
|
1416
|
+
/// **THE BOUND, IN ONE SENTENCE: rounds are counted per pass scope and not reset, so the loop runs at most
|
|
1417
|
+
/// `RESTART_LIMIT` restarted rounds however many actions a body raises inside it; the arm past the budget
|
|
1418
|
+
/// carries the same form and the same status and restores what the request's own watch recorded as owed.**
|
|
1419
|
+
/// A request whose watch is empty is a check with no pair to ask: it consumes its request and returns, so an
|
|
1420
|
+
/// empty watch can neither loop nor exhaust the budget.
|
|
1421
|
+
export function drainRestartRequests(instance, report) {
|
|
1422
|
+
const record = RESTARTS.get(instance);
|
|
1423
|
+
if (record === undefined) return report;
|
|
1424
|
+
// THE WINDOW THE DRAINING PASS RUNS IN — the pass's own scope is open above this call (`D-44`), so a request
|
|
1425
|
+
// raised by a body of that pass carries this same identity and one raised in an earlier window does not.
|
|
1426
|
+
const window = currentWindow(instance);
|
|
1427
|
+
let rounds = 0;
|
|
1428
|
+
for (;;) {
|
|
1429
|
+
const request = record.pending;
|
|
1430
|
+
if (request === null) return report;
|
|
1431
|
+
// **A REQUEST BELONGS TO THE ACT THAT RAISED IT — MEASURED** (`D-42` item `3`'s closing sentence): a request
|
|
1432
|
+
// standing from a window this pass did not open has no consumer HERE, and it is dropped rather than
|
|
1433
|
+
// attributed to an unrelated check. **IT DIES WITH ITS WINDOW, AND THAT IS THE DECLARED FAIL-STATE**
|
|
1434
|
+
// (`D-43` item `2`: the file reloads or the client regenerates the store). **TWO WINDOWS HOLD A COMMIT AND
|
|
1435
|
+
// RUN NO PASS, AND THEY ARE NAMED RATHER THAN LEFT TO A MEASUREMENT**: a `delete`'s listener delivery (a
|
|
1436
|
+
// delete consults no constraint, `D-1-bis`) and a REGISTRATION's own evaluation (`addConstraint`/
|
|
1437
|
+
// `register`, whose body is asked at an instant no attempt of the pass kind stands at — `context.attempt`
|
|
1438
|
+
// is `null` there). A request raised by a body inside either one has no consumer and dies here.
|
|
1439
|
+
if (request.window !== window) {
|
|
1440
|
+
record.pending = null;
|
|
1441
|
+
return report;
|
|
1442
|
+
}
|
|
1443
|
+
record.pending = null;
|
|
1444
|
+
if (request.watched.length === 0) continue;
|
|
1445
|
+
rounds += 1;
|
|
1446
|
+
if (rounds > RESTART_LIMIT) {
|
|
1447
|
+
// THE CHECK DID NOT SETTLE: THE SAME FORM, THE SAME STATUS, THE SAME COMPENSATION (`D-41` item `4`'s
|
|
1448
|
+
// direction), and the log entry says the budget was spent rather than that a pair refused.
|
|
1449
|
+
const one = request.watched[0];
|
|
1450
|
+
const after = standingAt(instance, one.address);
|
|
1451
|
+
const undo = restoreReversal(instance, request.watched);
|
|
1452
|
+
return carryRestartRefusal(report,
|
|
1453
|
+
reversalRefusal(one, after, null, request.reversalId, undo, null, true));
|
|
1454
|
+
}
|
|
1455
|
+
try {
|
|
1456
|
+
judgeReversal(instance, request.watched, request.reversalId);
|
|
1457
|
+
} catch (refused) {
|
|
1458
|
+
// THE REFUSAL IS THE OUTCOME: the store was restored by its own compensation inside `judgeReversal`, and
|
|
1459
|
+
// a request raised by the refusal's own bodies stands for nobody — the restarted check is over, so the
|
|
1460
|
+
// drain neither asks again nor spends a further round.
|
|
1461
|
+
record.pending = null;
|
|
1462
|
+
return carryRestartRefusal(report, refused);
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
/// **⟶ ADDED 2026-10-28 — `D-49`: THE DISCARD'S WITNESS, AND IT IS READ BY THE ACT WHOSE WINDOW DISCARDED THE
|
|
1468
|
+
/// REQUEST.**
|
|
1469
|
+
///
|
|
1470
|
+
/// **THE RULING, THE ARCHITECT, VERBATIM: *"Make discard observable"*** (`strata/decisions.md` · `D-49`), and
|
|
1471
|
+
/// **`DEF-AH` is the defect it answers**: a restart request raised inside one of the two windows that run **no
|
|
1472
|
+
/// pass** — a `delete`'s listener delivery, and a registration's own evaluation — **died with its window and the
|
|
1473
|
+
/// caller could not learn that it did.** **The fail-state stands** (`D-43` item 2, both exits) — **what was
|
|
1474
|
+
/// missing was the WITNESS.**
|
|
1475
|
+
///
|
|
1476
|
+
/// **WHAT THIS FUNCTION IS, AND WHAT IT IS NOT.**
|
|
1477
|
+
/// * **IT RUNS NO PASS, NO BODY AND NO JUDGEMENT.** It reads the instance's own restart record — the record
|
|
1478
|
+
/// `reversalWatch` raised the request in — and answers a fresh copy of the two facts a consumer needs: the
|
|
1479
|
+
/// id the reversal named (`reversalId`, the store's own echo) and the addresses the discarded check would
|
|
1480
|
+
/// have been asked at (`the watch's addresses`, deduplicated by spelling and copied segment for segment).
|
|
1481
|
+
/// **THE STORE IS NOT TOUCHED, NO CODE IS MINTED, NO LOG ENTRY IS APPENDED AND NO MEMBER OF ANY RECORD IS
|
|
1482
|
+
/// MOVED** — the `D-49` bar: *"a witness is not a refusal: the act still answers what it answered, the
|
|
1483
|
+
/// discard is reported beside it, and nothing new is minted in the closed status set."*
|
|
1484
|
+
/// * **IT CONSUMES THE REQUEST IT REPORTS.** A request whose window is the caller's has no consumer that could
|
|
1485
|
+
/// ever run it (the window's act ran no pass, and a later pass compares the identity and drops it — the
|
|
1486
|
+
/// drain's own arm), so clearing the slot here moves no behaviour: it is the same clearing the drain would
|
|
1487
|
+
/// perform on a mismatched window and the at-rest watch performs on a new reversal. **IT ONLY EVER CLEARS A
|
|
1488
|
+
/// REQUEST OF THE WINDOW HANDED IN** — a request raised in another window is left exactly where it stands,
|
|
1489
|
+
/// so an enclosing act's own consumer is never robbed of it.
|
|
1490
|
+
/// * **IT IS NOT THE DRAIN.** `drainRestartRequests` is the consumer of a pass's own window and RUNS the
|
|
1491
|
+
/// restarted check; this function is the consumer of a window that has none and only REPORTS it. **Two
|
|
1492
|
+
/// consumers, two windows, and neither takes the other's request** (`D-44`: *"every request has a
|
|
1493
|
+
/// consumer"* — for the two passless windows the consumer is the caller's own record).
|
|
1494
|
+
///
|
|
1495
|
+
/// **THE BOUND, STATED SO THE WITNESS IS NOT READ AS MORE THAN IT IS.** The restart record holds **ONE** pending
|
|
1496
|
+
/// request (a second in-flight action overwrites the first — the record's own declared shape, UNMOVED by this
|
|
1497
|
+
/// pass), so the witness reports the LAST request the window raised and no list of earlier ones exists to report.
|
|
1498
|
+
/// **The registration window is the other named window and it has no such reader**: its answer is an identity, and
|
|
1499
|
+
/// the identity is opaque by declaration, so nothing this function could answer would reach it without a new
|
|
1500
|
+
/// surface — `D-49`'s own instruction is to say so rather than to invent one.
|
|
1501
|
+
export function witnessDiscardedReversal(instance, window) {
|
|
1502
|
+
const record = RESTARTS.get(instance);
|
|
1503
|
+
// NO ACTION WAS EVER TAKEN ON THIS INSTANCE, OR THE LAST ONE WAS ALREADY CONSUMED: nothing stands to report.
|
|
1504
|
+
if (record === undefined || record.pending === null) return null;
|
|
1505
|
+
const request = record.pending;
|
|
1506
|
+
// **A REQUEST BELONGS TO THE ACT THAT RAISED IT** (`D-42` item 3, measured by the `window` stamp of
|
|
1507
|
+
// 2026-10-27): a request standing from another window is that window's and is left where it stands.
|
|
1508
|
+
if (request.window !== window) return null;
|
|
1509
|
+
record.pending = null;
|
|
1510
|
+
const addresses = [];
|
|
1511
|
+
const spellings = [];
|
|
1512
|
+
for (let index = 0; index < request.watched.length; index += 1) {
|
|
1513
|
+
const address = request.watched[index].address;
|
|
1514
|
+
const spelling = homeAddressKey(address);
|
|
1515
|
+
let seen = false;
|
|
1516
|
+
for (let known = 0; known < spellings.length; known += 1) {
|
|
1517
|
+
if (spellings[known] === spelling) {
|
|
1518
|
+
seen = true;
|
|
1519
|
+
break;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
// ONE ADDRESS ONCE: two pairs over one address (or one pair naming it twice) are one address the check owed,
|
|
1523
|
+
// and the witness reports the subject and not the walk.
|
|
1524
|
+
if (seen) continue;
|
|
1525
|
+
appendOwn(spellings, spelling);
|
|
1526
|
+
// **A FRESH SEGMENT LIST PER ADDRESS** (`crossing.md §1.1`'s copy-out discipline): the pair's own array is
|
|
1527
|
+
// the registry's and is never handed to a caller.
|
|
1528
|
+
const copy = [];
|
|
1529
|
+
for (let segment = 0; segment < address.length; segment += 1) appendOwn(copy, address[segment]);
|
|
1530
|
+
appendOwn(addresses, copy);
|
|
1531
|
+
}
|
|
1532
|
+
// THE STORE'S OWN ECHO OF THE ID THE REVERSAL NAMED — `null` where the reversal's call answered no id (the
|
|
1533
|
+
// request stands and the act's answer did not reach the echo, which is a real arm a caller can see).
|
|
1534
|
+
return {
|
|
1535
|
+
opId: typeof request.reversalId === 'string' ? request.reversalId : null,
|
|
1536
|
+
addresses,
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
/// **⟶ THE REFUSAL'S ONE CARRIER TO WHICHEVER DRIVER ASKED — ADDED 2026-10-27.**
|
|
1541
|
+
///
|
|
1542
|
+
/// **THE REPORT IS AMENDED IN TWO PLAIN MEMBERS AND CARRIES THE REFUSAL WHOLE UNDER A THIRD, SYMBOL-KEYED
|
|
1543
|
+
/// ONE:**
|
|
1544
|
+
/// * **`report.outcome` BECOMES `'failed'`** — the attempt's answer is the restarted check's. The pass it
|
|
1545
|
+
/// ran DID pass, and the state that pass approved does not stand: the action taken inside its window was
|
|
1546
|
+
/// reversed and the check that state was re-judged by refused it, so the store is back at the journal's
|
|
1547
|
+
/// head and not at the pass's own op. **THE TWO-ARM MEMBER KEEPS ITS TWO ARMS** (`'passed'`/`'failed'`,
|
|
1548
|
+
/// `attempt-lifecycle.md §2.4` item 3's terminal-arm clause): no third value is minted;
|
|
1549
|
+
/// * **THE REFUSAL'S OWN LOG ENTRY IS APPENDED TO THE ATTEMPT'S LOG** — one `constraint-check` entry naming
|
|
1550
|
+
/// the pair that refused the state the action left and saying what the refusal's compensating act did
|
|
1551
|
+
/// (`undoSpelling`). **IT ENTERS THROUGH THE KERNEL'S OWN `append`**, so it carries the log's six declared
|
|
1552
|
+
/// members and the log's own ordinal: the entry the driver reads in `report.log` is a log entry of the
|
|
1553
|
+
/// attempt's log and not a record of another kind. **THE REFUSAL'S OWN LIST KEEPS ITS FIVE MEMBERS AND NO
|
|
1554
|
+
/// `seq`** — that list is the judgement's and no attempt log stands at its own instant (`D-41` item `4`) —
|
|
1555
|
+
/// so the copy is the report's and the original is the refusal's, each honest in its own record;
|
|
1556
|
+
/// * **AND THE REFUSAL ITSELF TRAVELS UNDER `RESTART_REFUSAL`** so that `constraintWrite` re-throws THE VERY
|
|
1557
|
+
/// VALUE the restarted check built — same `status`, same `message`, same `log` — with nothing re-rendered
|
|
1558
|
+
/// and no second spelling of the store's sentence (`DD-52`).
|
|
1559
|
+
///
|
|
1560
|
+
/// **NO MEMBER IS ADDED TO THE REPORT'S READABLE SHAPE**: it keeps its five (`attempt`, `outcome`, `ops`,
|
|
1561
|
+
/// `log`, `rollback`), the symbol key is invisible to `Object.keys` and to `Object.getOwnPropertyNames`
|
|
1562
|
+
/// (`A117` (D6)), and `K-5` answers the same list a `K-3` answered because it is the same object.
|
|
1563
|
+
const RESTART_REFUSAL = Symbol.for('provident-storeroom.restart-refusal');
|
|
1564
|
+
|
|
1565
|
+
/// **THE AMENDMENT ITSELF — the one site that writes the report a restarted check refused.**
|
|
1566
|
+
function carryRestartRefusal(report, refusal) {
|
|
1567
|
+
report.outcome = 'failed';
|
|
1568
|
+
const carried = refusal !== null && typeof refusal === 'object' && Array.isArray(refusal.log)
|
|
1569
|
+
? refusal.log
|
|
1570
|
+
: [];
|
|
1571
|
+
// THE APPEND IS THE KERNEL'S OWN (`append`): a local holder carrying the report's own list, so the ordinal
|
|
1572
|
+
// is `log.length + 1` exactly as every other entry of this log was minted, and no `Array.prototype.push` is
|
|
1573
|
+
// read on this path (`contract.md §2.1`'s clause of 2026-10-24 on `F8-2`).
|
|
1574
|
+
const log = { log: report.log };
|
|
1575
|
+
for (let index = 0; index < carried.length; index += 1) {
|
|
1576
|
+
const entry = carried[index];
|
|
1577
|
+
append(log, entry.kind, entry.id, entry.opId, entry.message, entry.state);
|
|
1578
|
+
}
|
|
1579
|
+
Object.defineProperty(report, RESTART_REFUSAL, {
|
|
1580
|
+
value: refusal,
|
|
1581
|
+
writable: false,
|
|
1582
|
+
enumerable: false,
|
|
1583
|
+
configurable: true,
|
|
1584
|
+
});
|
|
1585
|
+
return report;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
// **⟶ AND THE CHANNEL IS GIVEN ITS IMPLEMENTATION HERE, AT THIS FILE'S OWN MODULE SCOPE.** `state.mjs` owns
|
|
1589
|
+
// the seam and may not import this file (`constraints.mjs` imports IT, and the kernel imports neither), so the
|
|
1590
|
+
// consumer is injected rather than imported: one registration, one consumer, and the kernel reaches it by the
|
|
1591
|
+
// `Symbol.for('provident-storeroom.restart-drain')` channel `installAttemptSeam` installs on every store.
|
|
1592
|
+
installRestartConsumer(drainRestartRequests);
|
|
1593
|
+
|
|
1211
1594
|
/// **THE WATCH — THE PRE-REVERSAL STANDING OF EVERY ENABLED PAIR'S EVERY ADDRESS**, taken before the addon's
|
|
1212
|
-
/// `rollback` entry is called. **IT IS A LIST OF `{entry, address, before}` AND
|
|
1213
|
-
/// the pair's own record (so the judgement needs no second lookup and no registry
|
|
1214
|
-
/// the address is the pair's own segment array (never a copy, never mutated here)
|
|
1215
|
-
/// store
|
|
1595
|
+
/// `rollback` entry is called. **IT IS A LIST OF `{entry, address, before, beforeTier, beforeTiers}` AND
|
|
1596
|
+
/// NOTHING ELSE**: the entry is the pair's own record (so the judgement needs no second lookup and no registry
|
|
1597
|
+
/// read after the reversal), the address is the pair's own segment array (never a copy, never mutated here)
|
|
1598
|
+
/// and the standing is what the store held when the reversal was asked for.
|
|
1599
|
+
///
|
|
1600
|
+
/// **⟶ AND THE WATCH CAPTURES THE TIER AND NOT ONLY THE VALUE, 2026-10-27 — `D-41` ITEM `2`, MEASURED.** The
|
|
1601
|
+
/// list this clause declares was `{entry, address, before}` and `before` was the CROSS-TIER read alone, so the
|
|
1602
|
+
/// restore could not know **where** the value stood and put everything back at `mem` (`restoreReversal` below
|
|
1603
|
+
/// states what that cost). **THE TIERS ARE THREE AND RANKED `file` > `mem` > `temp`** (`src/records.rs`'s
|
|
1604
|
+
/// `Tier`), **the zero-tier `read` answers the LOWEST-tier version present at each key** (`src/store.rs`'s
|
|
1605
|
+
/// `select_member`), **and the tier argument narrows that same read to one tier** (`src/args.rs`'s
|
|
1606
|
+
/// `read_tier_sel`) — so the watch takes the standing the judgement reads
|
|
1607
|
+
/// AND one narrowed read per tier:
|
|
1608
|
+
/// * **`before`** is the same cross-tier standing it always was (the judgement's subject and the "touched"
|
|
1609
|
+
/// test are unchanged, `sameStanding`);
|
|
1610
|
+
/// * **`beforeTiers`** is every tier at which the address STOOD, captured in the store's canonical
|
|
1611
|
+
/// `file` · `mem` · `temp` order, each with the value that tier answers — **the exact state a restore has
|
|
1612
|
+
/// to put back**, one write per tier, and the only way a value at `file` survives;
|
|
1613
|
+
/// * **`beforeTier`** is the tier the cross-tier read drew from (the lowest-rank standing tier), or `null`
|
|
1614
|
+
/// where the address stood at no tier at all — *"where the value stood"*, spelled once for the message.
|
|
1615
|
+
/// **THE ABSENT ARM IS THE ZERO-READ'S OWN**: where the cross-tier read refuses, the address stands at no
|
|
1616
|
+
/// tier, so `before` is `undefined`, `beforeTiers` is `[]` and `beforeTier` is `null` — the state the restore
|
|
1617
|
+
/// must return the address to by REMOVING what the reversal left there.
|
|
1216
1618
|
///
|
|
1217
1619
|
/// **IT IS EMPTY WHERE THE ENTRY CARRIES NO PAIR**, so the whole judgement — and every read it would take —
|
|
1218
1620
|
/// is skipped for the overwhelming majority of `rollback` calls, and a store that never registered a
|
|
@@ -1220,13 +1622,49 @@ function reversalAtRest(instance) {
|
|
|
1220
1622
|
export function reversalWatch(state, instance) {
|
|
1221
1623
|
const watched = [];
|
|
1222
1624
|
if (state.constraints.size === 0) return watched;
|
|
1223
|
-
// A REVERSAL INSIDE AN OPEN COMMIT
|
|
1224
|
-
//
|
|
1225
|
-
//
|
|
1226
|
-
|
|
1227
|
-
//
|
|
1228
|
-
//
|
|
1229
|
-
//
|
|
1625
|
+
// **⟶ AND A REVERSAL INSIDE AN OPEN COMMIT IS NO LONGER LEFT UNJUDGED — `D-42`, 2026-10-27.** The bytes
|
|
1626
|
+
// below stood as *"the watch answers `[]` there, so no read is taken and no body is invoked"*, and the
|
|
1627
|
+
// SECOND HALF of that sentence is now WITHDRAWN BY NAME: **no body is invoked here (the action is not judged
|
|
1628
|
+
// at its instant — the step is still not judged as a step), while the WATCH IS TAKEN and the check is
|
|
1629
|
+
// RESTARTED where the check runs** (`drainRestartRequests`). **THE READS ARE THE SAME READS THE AT-REST
|
|
1630
|
+
// JUDGEMENT TAKES AND THEY ARE THE RESTART'S DEBT RECORD**: what stood at each enabled pair's address before
|
|
1631
|
+
// the action ran — the state the refusal's compensating act owes back, and the baseline its verification
|
|
1632
|
+
// reads. **A REVERSAL INSIDE AN OPEN COMMIT OR AN OPEN ATTEMPT IS STILL NOT A TERMINAL STATE** and
|
|
1633
|
+
// `reversalAtRest` is UNCHANGED (the conjunction keeps both conjuncts; the restart is not a third conjunct):
|
|
1634
|
+
// what moves is only what happens to the request after the window closes.
|
|
1635
|
+
//
|
|
1636
|
+
// **⟶ AND FROM 2026-10-27 THE REQUEST NAMES THE WINDOW IT WAS RAISED IN** (`currentWindow`, `state.mjs`): the
|
|
1637
|
+
// identity of the commit open at this instant, minted with the opening. **THAT STAMP IS THE WHOLE OF THE
|
|
1638
|
+
// EPOCH RULE NOW** — the consumer (`drainRestartRequests`) compares it against the window the draining pass
|
|
1639
|
+
// runs in, so *"a request belongs to the act that raised it"* (`D-42` item `3`) is MEASURED at this line and
|
|
1640
|
+
// checked at that one, and the `CHECK_DEPTH` frame that once approximated it is deleted with its clears.
|
|
1641
|
+
if (reversalAtRest(instance) === false) {
|
|
1642
|
+
restartRecord(instance).pending = {
|
|
1643
|
+
watched: watchStanding(state, instance),
|
|
1644
|
+
reversalId: null,
|
|
1645
|
+
window: currentWindow(instance),
|
|
1646
|
+
};
|
|
1647
|
+
return watched;
|
|
1648
|
+
}
|
|
1649
|
+
// **AND AN AT-REST CALL PROVES THE PREVIOUS WINDOW HAS ENDED**: a request still standing there belongs to a
|
|
1650
|
+
// window whose check never ran (a `delete`'s delivery is the one the declaration names), and the act that
|
|
1651
|
+
// raised it is over — so it dies here rather than being attributed to this reversal.
|
|
1652
|
+
const record = RESTARTS.get(instance);
|
|
1653
|
+
if (record !== undefined) record.pending = null;
|
|
1654
|
+
return watchStanding(state, instance);
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
/// **THE CHECK'S OWN BEGINNING — THE WATCH'S WALK, TAKEN AS ONE FUNCTION SO THE AT-REST JUDGEMENT AND THE
|
|
1658
|
+
/// RESTART BEGIN AT THE SAME FIRST PAIR.**
|
|
1659
|
+
///
|
|
1660
|
+
/// **THE WALK IS `D-39`'S DECLARED ORDER** — the record's own `registrationSeq`, collected and ordered exactly
|
|
1661
|
+
/// as `enumerateConstraints` collects and orders its answer — so the pair the judgement reaches FIRST is the
|
|
1662
|
+
/// pair `constraints()` names first, and not whichever pair a toggle happened to move. **A PAIR WHOSE ELEMENT
|
|
1663
|
+
/// DOES NOT STAND A REGISTRATION IS NOT EVEN CAPTURED** (`withdrawStanding`'s own predicate, and its own
|
|
1664
|
+
/// ground: a disabled pair's registry standing is a CARRIAGE fact, not a listener) — so the restart asks
|
|
1665
|
+
/// nothing on a disabled pair's address and the budget cannot be spent on one.
|
|
1666
|
+
function watchStanding(state, instance) {
|
|
1667
|
+
const watched = [];
|
|
1230
1668
|
const carried = [];
|
|
1231
1669
|
for (const entry of state.constraints.values()) {
|
|
1232
1670
|
appendOwn(carried, entry);
|
|
@@ -1234,17 +1672,56 @@ export function reversalWatch(state, instance) {
|
|
|
1234
1672
|
carried.sort((left, right) => left.registrationSeq - right.registrationSeq);
|
|
1235
1673
|
for (let index = 0; index < carried.length; index += 1) {
|
|
1236
1674
|
const entry = carried[index];
|
|
1237
|
-
// THE PAIR'S ELEMENT MUST STAND A REGISTRATION FOR IT TO BE ASKED ANYTHING (`withdrawStanding`'s own
|
|
1238
|
-
// predicate, and its own ground: a disabled pair's registry standing is a CARRIAGE fact, not a listener).
|
|
1239
1675
|
if (entry.enabled !== true) continue;
|
|
1240
1676
|
for (let position = 0; position < entry.addresses.length; position += 1) {
|
|
1241
1677
|
const address = entry.addresses[position];
|
|
1242
|
-
|
|
1678
|
+
const captured = captureStanding(instance, address);
|
|
1679
|
+
appendOwn(watched, {
|
|
1680
|
+
entry,
|
|
1681
|
+
address,
|
|
1682
|
+
before: captured.before,
|
|
1683
|
+
beforeTier: captured.beforeTier,
|
|
1684
|
+
beforeTiers: captured.tiers,
|
|
1685
|
+
});
|
|
1243
1686
|
}
|
|
1244
1687
|
}
|
|
1245
1688
|
return watched;
|
|
1246
1689
|
}
|
|
1247
1690
|
|
|
1691
|
+
/// **THE THREE TIER TOKENS, IN THE CANONICAL ORDER A RESTORE MUST WRITE THEM** — `file` · `mem` · `temp`
|
|
1692
|
+
/// (`src/records.rs`'s `canonical_tiers`, rank DESCENDING). **THE ORDER IS NOT COSMETIC: a write purges every
|
|
1693
|
+
/// version at `rank ≤ rank(write tier)` at the addressed key** (`src/store.rs`'s `W-6`, the `doomed` filter),
|
|
1694
|
+
/// **so writing the captured tiers from the most persistent to the least reconstructs a shadow exactly** —
|
|
1695
|
+
/// `file`, then `mem`, then `temp`: each write purges only what it outranks and therefore cannot destroy a tier
|
|
1696
|
+
/// already put back.
|
|
1697
|
+
const STANDING_TIERS = ['file', 'mem', 'temp'];
|
|
1698
|
+
|
|
1699
|
+
/// **WHAT STOOD AT ONE ADDRESS, CAPTURED BEFORE THE REVERSAL** — the cross-tier standing the judgement reads
|
|
1700
|
+
/// (and the "touched" test compares), the tier that standing was drawn from, and every tier at which the
|
|
1701
|
+
/// address stood with the value that tier answers. **AN ADDRESS THAT STANDS AT NO TIER IS THE ZERO-READ'S OWN
|
|
1702
|
+
/// ABSENCE**: the cross-tier `read` refuses, no narrowed read is taken, and `tiers` is `[]` — the ONE state the
|
|
1703
|
+
/// restore returns the address to by removal rather than by a write.
|
|
1704
|
+
function captureStanding(instance, address) {
|
|
1705
|
+
const before = standingAt(instance, address);
|
|
1706
|
+
const tiers = [];
|
|
1707
|
+
// THE NARROWED READS ARE TAKEN ONLY WHERE SOMETHING STANDS: the zero-tier read cannot succeed at an address
|
|
1708
|
+
// that holds an anchor at no tier, so absence is decided once and costs no further read.
|
|
1709
|
+
if (before !== undefined) {
|
|
1710
|
+
for (let index = 0; index < STANDING_TIERS.length; index += 1) {
|
|
1711
|
+
const tier = STANDING_TIERS[index];
|
|
1712
|
+
const stood = standingAtTier(instance, address, tier);
|
|
1713
|
+
if (stood.stood === true) appendOwn(tiers, { tier, value: stood.value });
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
return {
|
|
1717
|
+
before,
|
|
1718
|
+
// THE TIER THE CROSS-TIER READ DREW FROM — the lowest-rank standing tier, which is the LAST entry of
|
|
1719
|
+
// `tiers` because `STANDING_TIERS` is rank-descending — and `null` where the address stood at no tier.
|
|
1720
|
+
beforeTier: tiers.length === 0 ? null : tiers[tiers.length - 1].tier,
|
|
1721
|
+
tiers,
|
|
1722
|
+
};
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1248
1725
|
/// **THE JUDGEMENT — THE TERMINAL STATE, ASKED OF EVERY PAIR THE REVERSAL TOUCHED, ONCE.** It answers
|
|
1249
1726
|
/// `undefined` on the lawful arm (**and the caller's record then crosses unchanged**) and THROWS the surface's
|
|
1250
1727
|
/// one plain form on the refusing arm. `reversalId` is the store's own echo of the id the reversal named
|
|
@@ -1262,97 +1739,362 @@ export function reversalWatch(state, instance) {
|
|
|
1262
1739
|
/// **AND THE RESTORE IS NOT JUDGED AND RECURSES INTO NOTHING** (`restoreReversal` below states both): it is a
|
|
1263
1740
|
/// COMPENSATING ACT and not a consumer write, it reaches the store verb at its entry — no `K-2`, no pass, no
|
|
1264
1741
|
/// listener delivery and no second `rollback` — and every address it touches is one the watch already read.
|
|
1742
|
+
///
|
|
1743
|
+
/// **⟶ AND A JUDGEMENT THAT CANNOT COMPLETE FAILS CLOSED, 2026-10-27 — `D-41` ITEM `4`, MEASURED.** A pair body
|
|
1744
|
+
/// that THREW at this judgement used to propagate out of this function **with the reversal's effect STANDING and
|
|
1745
|
+
/// the refusal's `log` `[]`**: the reversal had already happened, so the store was left at the very state nobody
|
|
1746
|
+
/// could judge and the consumer was told nothing about it. **A reversal nobody could judge is a reversal nobody
|
|
1747
|
+
/// could approve**, so the throwing arm is treated as the violating arm: **every address the reversal moved is
|
|
1748
|
+
/// restored, and the call refuses with a log that NAMES THE THROWING PAIR** — the same treatment a violation
|
|
1749
|
+
/// gets. The crossed code stays the body's own rank-`18` member (`ConstraintBodyThrew`, the code that says what
|
|
1750
|
+
/// actually happened: a body threw), while the treatment — restore, one log entry naming the pair, one plain
|
|
1751
|
+
/// form — is the violation's.
|
|
1265
1752
|
export function judgeReversal(instance, watched, reversalId) {
|
|
1266
|
-
// THE
|
|
1267
|
-
//
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
const
|
|
1275
|
-
if (
|
|
1276
|
-
|
|
1753
|
+
// **⟶ AND THE IN-FLIGHT ARM IS THE REQUEST'S OTHER HALF, `D-42` (2026-10-27).** `reversalWatch` answers
|
|
1754
|
+
// `[]` for an action taken inside an open window — no body is invoked at the reversal's instant and the step
|
|
1755
|
+
// is still not judged as a step — **and this frame is where the store's own echo of the id the reversal
|
|
1756
|
+
// named reaches the request the watch raised**: the id is the refusal's `opId` when the restart refuses, so
|
|
1757
|
+
// the declared log entry names the act, exactly as the at-rest control's does. **NO ASK AND NO READ IS TAKEN
|
|
1758
|
+
// HERE** — the restart is not this frame's, and an empty watch with no request standing (the at-rest arm of a
|
|
1759
|
+
// store whose every pair is disabled) is a judgement over nothing and answers `undefined` as it always did.
|
|
1760
|
+
if (watched.length === 0) {
|
|
1761
|
+
const record = RESTARTS.get(instance);
|
|
1762
|
+
if (record !== undefined && record.pending !== null && record.pending.reversalId === null) {
|
|
1763
|
+
record.pending.reversalId = typeof reversalId === 'string' ? reversalId : null;
|
|
1764
|
+
}
|
|
1765
|
+
return undefined;
|
|
1277
1766
|
}
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1767
|
+
// **⟶ AND THE AT-REST JUDGEMENT RUNS INSIDE A COMMIT, 2026-10-27 — `D-44`'s INVARIANT AND `DEF-AE`'S CACHE.**
|
|
1768
|
+
// `D-44`: *"There should be no state where a constraint is being checked without an open commit. Any action that
|
|
1769
|
+
// would cause a constraint check should open a commit before beginning."* **THE AT-REST JUDGEMENT WAS THE ONE
|
|
1770
|
+
// CHECK THAT RAN OUTSIDE ONE** — `reversalWatch` had already decided `reversalAtRest` on the count this call
|
|
1771
|
+
// found (`open` `0`, `live` `0`), so the discriminator's reading is unmoved by the opening that follows it —
|
|
1772
|
+
// **and the window it opens is what carries the mark the restore owes back** (`state.mjs`'s `openCommit` caches
|
|
1773
|
+
// the journal's last valid position at the opening; `windowMark` answers it). **A REVERSAL APPENDS NO ENTRY**, so
|
|
1774
|
+
// the mark taken here is still the PRE-REVERSAL state — which is why the at-rest control restores exactly what
|
|
1775
|
+
// it restored before. **ON THE RESTART ARM THIS CALL JOINS** the pass's window (the drain runs inside the pass's
|
|
1776
|
+
// own scope, `kernel-attempt.mjs`) and re-caches nothing, so the mark in flight stays the OUTERMOST opening's:
|
|
1777
|
+
// the position the attempt found. **THE `finally` RELEASES THE WINDOW ON EVERY ARM, INCLUDING THE THROWING ONE**,
|
|
1778
|
+
// because a refusal that leaves a commit standing is the count this package's own cells measure.
|
|
1779
|
+
const opened = openCommit(instance);
|
|
1780
|
+
try {
|
|
1781
|
+
// THE MOVED SET IS TAKEN FIRST, ONCE: the judgement's subject is the CHANGE the reversal made and nothing
|
|
1782
|
+
// wider, and the same list is what a refusal has to put back — with the tier capture the watch took, so a
|
|
1783
|
+
// restore knows WHERE each value stood and not merely what it was.
|
|
1784
|
+
const moved = [];
|
|
1785
|
+
for (let index = 0; index < watched.length; index += 1) {
|
|
1786
|
+
const one = watched[index];
|
|
1787
|
+
// THE ADDRESS IS READ AGAIN, AT THE STATE THE REVERSAL LEFT. **A STANDING THIS REVERSAL DID NOT MOVE IS
|
|
1788
|
+
// NOT A STANDING IT LEFT**, so the pair is not asked and cannot refuse the reversal for a state the
|
|
1789
|
+
// reversal found.
|
|
1790
|
+
const after = standingAt(instance, one.address);
|
|
1791
|
+
if (sameStanding(one.before, after) === true) continue;
|
|
1792
|
+
appendOwn(moved, {
|
|
1793
|
+
entry: one.entry,
|
|
1794
|
+
address: one.address,
|
|
1795
|
+
before: one.before,
|
|
1796
|
+
beforeTier: one.beforeTier,
|
|
1797
|
+
beforeTiers: one.beforeTiers,
|
|
1798
|
+
after,
|
|
1799
|
+
});
|
|
1800
|
+
}
|
|
1801
|
+
for (let index = 0; index < moved.length; index += 1) {
|
|
1802
|
+
const one = moved[index];
|
|
1803
|
+
// **THE BODY'S THROW IS THE JUDGEMENT'S OWN CATCH AND NOT A PROPAGATING VALUE** — `reversalOutcome` converts
|
|
1804
|
+
// a body's throwable to the surface's rank-`18` form and re-throws anything unmarked as itself, and BOTH
|
|
1805
|
+
// arrive here: the reversal has run, so a judgement that cannot complete restores and refuses (below).
|
|
1806
|
+
let outcome;
|
|
1807
|
+
try {
|
|
1808
|
+
outcome = reversalOutcome(instance, one.entry, one.address, one.after);
|
|
1809
|
+
} catch (thrown) {
|
|
1810
|
+
const undo = restoreReversal(instance, moved);
|
|
1811
|
+
throw reversalRefusal(one, one.after, null, reversalId, undo, thrown);
|
|
1812
|
+
}
|
|
1813
|
+
if (outcome === true) continue;
|
|
1814
|
+
// **THE FIRST VIOLATING PAIR DECIDES AND THE SECOND IS NOT EVALUATED** (`attempt-lifecycle.md §2.4` item 5
|
|
1815
|
+
// (ii)–(iii), at the reversal's own instant) — and BEFORE the refusal is built, EVERY address the reversal
|
|
1816
|
+
// moved is put back, so the store the consumer meets holds no state this refusal refused.
|
|
1817
|
+
const undo = restoreReversal(instance, moved);
|
|
1818
|
+
throw reversalRefusal(one, one.after, reversalSaid(outcome), reversalId, undo, null);
|
|
1819
|
+
}
|
|
1820
|
+
return undefined;
|
|
1821
|
+
} finally {
|
|
1822
|
+
closeCommit(instance, opened);
|
|
1287
1823
|
}
|
|
1288
|
-
return undefined;
|
|
1289
1824
|
}
|
|
1290
1825
|
|
|
1291
|
-
/// **THE REFUSAL'S OWN UNDOING —
|
|
1826
|
+
/// **THE REFUSAL'S OWN UNDOING — THE STORE RETURNS ITS OWN STATE TO ITS JOURNAL MARK, AND THE WATCH SAYS WHAT
|
|
1827
|
+
/// STOOD AGAIN.** **⟶ REWRITTEN 2026-10-27 (THE ARCHITECT'S RULING): `restoreReversal` NO LONGER WRITES
|
|
1828
|
+
/// ANYTHING.** It calls ONE store verb — `restoreMark`, the journal's second consumer beside `rollback`, reached
|
|
1829
|
+
/// at the boundary's own entry exactly as `rollback` is — and the STORE decides what the pre-reversal state was,
|
|
1830
|
+
/// from ITS OWN RECORD.
|
|
1292
1831
|
///
|
|
1293
|
-
/// **WHY
|
|
1294
|
-
///
|
|
1295
|
-
///
|
|
1296
|
-
///
|
|
1297
|
-
///
|
|
1298
|
-
///
|
|
1832
|
+
/// **WHY THE CAPTURE-AND-WRITE IS GONE, STATED AS THE MEASUREMENT THAT RETIRED IT.** The restore used to
|
|
1833
|
+
/// reconstruct the state ADDRESS BY ADDRESS and TIER BY TIER from what a READ draws: the watch's per-tier
|
|
1834
|
+
/// readings of each enabled pair's address. That cannot rebuild a shadow INSIDE a subtree (a version standing
|
|
1835
|
+
/// one level BELOW the pair is captured only inside its parent's assembled value, so writing that value back at
|
|
1836
|
+
/// the parent's tier moves the descendant's tier with it), and it cannot cross the store's monotonicity clause
|
|
1837
|
+
/// (a `file` version cannot be written back under a parent the reversal left at `mem`). **And it rewrote BY HAND
|
|
1838
|
+
/// what the store can REPLAY EXACTLY**: the journal records every operation's address, its before AND its after,
|
|
1839
|
+
/// per version and per tier, and `restoreMark` re-states that record (`src/store.rs`'s `§6.6` is the primitive's
|
|
1840
|
+
/// declaration). The two shapes the capture could not reach are the two cells added to
|
|
1841
|
+
/// `tests/e2e/refused-reversal-restore.test.mjs` — the MIXED-DEPTH SHADOW and the HIGHER-TIER/PARENT case —
|
|
1842
|
+
/// and both were RED under the capture-and-write.
|
|
1843
|
+
///
|
|
1844
|
+
/// **THE MARK IS THE JOURNAL'S HEAD, AND IT IS NAMED BY SUPPLYING NO POSITION.** A reversal appends no entry
|
|
1845
|
+
/// (`src/store.rs`'s `rollback`), so after the reversal ran the journal's head still describes the state that
|
|
1846
|
+
/// stood BEFORE it — the state this act owes back. The call therefore passes NO position at all, which the
|
|
1847
|
+
/// boundary's own codec folds to the carrier's ABSENT arm (`crossing.md §1.3`): the store's own spelling for
|
|
1848
|
+
/// *"the head"*.
|
|
1849
|
+
///
|
|
1850
|
+
/// **⟶ AND THE TWO PARAGRAPHS ABOVE ARE READ THROUGH THEIR MARK, 2026-10-27 — THE ARCHITECT'S RULING, VERBATIM:
|
|
1851
|
+
/// *"Cache the restoreMark when opening a commit, based on the last valid state/op of the journal."*** `RCA-8(g)`
|
|
1852
|
+
/// ANNOTATE-BESIDE: **every byte above stands and this clause is the operative statement of WHICH mark the act
|
|
1853
|
+
/// names.** **THE HEAD IS NO LONGER TRUSTED, AND THE REASON IS THE MEASUREMENT `DEF-AE` FILED:** *"a reversal
|
|
1854
|
+
/// appends no journal entry, so the head describes the state that stood before the action"* is TRUE OF A REVERSAL
|
|
1855
|
+
/// TAKEN AT REST and FALSE OF ONE TAKEN INSIDE A WRITE'S COMMIT — **in the restart arm the enclosing write's own op
|
|
1856
|
+
/// stands at the head when the listener's reversal runs**, so the head described the WRITE'S LANDING and the
|
|
1857
|
+
/// compensation restored the refusal's own value: **the store stood at `7` where the attempt found `9`, and the
|
|
1858
|
+
/// write that reported the refusal had landed its value.** **SO THE ACT NAMES THE MARK ITS COMMIT CACHED AT ITS
|
|
1859
|
+
/// OPENING** — `state.mjs`'s `openCommit` reads the store's own `journalMark` (`src/store.rs`: the last VALID
|
|
1860
|
+
/// mark, which is the head at that instant and is named as a VALUE) and stands it on the window; `windowMark`
|
|
1861
|
+
/// answers it here, and the store's `restoreMark` replays to it. **THE INSTANT IS THE WHOLE FIX**: the opening
|
|
1862
|
+
/// precedes anything the commit lands, so the cached position is the state the attempt FOUND — the pre-attempt
|
|
1863
|
+
/// state, which is what a failed attempt owes back. **A JOIN RE-CACHES NOTHING** (`D-45`/`D-46` decide which
|
|
1864
|
+
/// openings are outermost: a repair's write and a pass's scope join, so they take the outermost mark and not a
|
|
1865
|
+
/// later one), and **a callback's own commit is its own opening with its own cache** (a listener body's call names
|
|
1866
|
+
/// nothing and opens, so the mark it restores to is where ITS window opened). **THE MARK IS OPAQUE HERE**: the
|
|
1867
|
+
/// store answered a carrier — `{k:'s', v:<op id>}`, or `{k:'F'}` for the FLOOR, the state the store was born with
|
|
1868
|
+
/// when the journal held no entry at the opening — and this act hands the very same carrier back. **NEITHER THE
|
|
1869
|
+
/// PACKAGE NOR THIS FUNCTION COMPOSES A POSITION.**
|
|
1870
|
+
///
|
|
1871
|
+
/// **AND A WINDOW WITH NO CACHE IS A WINDOW THAT NEVER OPENED: THIS ACT REFUSES RATHER THAN FALLING BACK TO THE
|
|
1872
|
+
/// HEAD** — the head is the value this ruling exists to stop trusting, and a silent fall-back would restore it
|
|
1873
|
+
/// while a consumer was told the reversal was undone. **THE REFUSAL IS THE ACT'S, NOT THE CALL'S**: no store verb
|
|
1874
|
+
/// is invoked, no status is minted (`DD-40`), every address the reversal moved is reported as NOT restored with
|
|
1875
|
+
/// what stands there instead, and the log entry says the window carried no cached mark — so the crossed form, its
|
|
1876
|
+
/// `status` and its member set are unmoved and the consumer is never told a restoration happened that did not.
|
|
1877
|
+
///
|
|
1878
|
+
/// **WHAT THE CAPTURE SURVIVES AS, AND WHY IT IS NOT A FALLBACK.** `reversalWatch`'s per-tier capture is still
|
|
1879
|
+
/// taken, and it is the ONLY record of **what was owed** — it is the DEBT'S RECORD and the VERIFICATION
|
|
1880
|
+
/// BASELINE, not a write plan. Every address the reversal moved is read again after the store's act
|
|
1881
|
+
/// (`standingVerdict`), and the count and the failures below are read from THAT — so `UNDONE` is claimed only
|
|
1882
|
+
/// where each moved address demonstrably stands again with the values and the tiers it held, which is the
|
|
1883
|
+
/// honesty `D-41` item `2` measured at `200` of `200`. **NO WRITE AND NO DELETE IS ISSUED BY THIS FUNCTION ON
|
|
1884
|
+
/// ANY ARM**; the store's own verb is the whole act.
|
|
1299
1885
|
///
|
|
1300
1886
|
/// **AND WHY IT CANNOT RECURSE INTO THE MEMBER.** `judgeReversal` is reached from `index.mjs`'s `rollback`
|
|
1301
|
-
/// member; the restore never calls that member, the addon's `rollback`, or any package member — only the
|
|
1302
|
-
///
|
|
1303
|
-
/// is not re-walked.
|
|
1304
|
-
///
|
|
1305
|
-
///
|
|
1306
|
-
///
|
|
1307
|
-
///
|
|
1308
|
-
///
|
|
1309
|
-
///
|
|
1887
|
+
/// member; the restore never calls that member, the addon's `rollback`, or any package member — only the store's
|
|
1888
|
+
/// `restoreMark` at its entry — so the judgement's ONE pass over the pairs stays one pass and `D-40`'s floor law
|
|
1889
|
+
/// is not re-walked. **NO `K-2` OPENS, NO PASS RUNS, NO LISTENER IS DELIVERED AND NO PAIR BODY IS ASKED A SECOND
|
|
1890
|
+
/// TIME**: the store's primitive appends no entry, fires no trigger and reads no constraint.
|
|
1891
|
+
///
|
|
1892
|
+
/// **WHERE THE STORE ITSELF REFUSES, THIS SAYS SO AND WRITES NOTHING.** `restoreMark` refuses in the store's own
|
|
1893
|
+
/// declared form (`JournalOpUnknown`) for a mark its journal no longer holds, and the state it holds at that
|
|
1894
|
+
/// instant is the state it keeps. The refusal is carried into the message `undoSpelling` builds, so a consumer
|
|
1895
|
+
/// is told the store refused and is never told a restoration happened that did not.
|
|
1896
|
+
///
|
|
1897
|
+
/// **⟶ AND A FAILED SAVE IS A SECOND, DIFFERENT ANSWER — 2026-10-27, THE FILE-SAVE RULING.** `restoreMark` now
|
|
1898
|
+
/// answers `FileCommitFailed` when the restore's own save cannot land, **and that answer does not mean the mark
|
|
1899
|
+
/// was refused**: the store's replay already ran, so the in-memory state IS the restored state and only the
|
|
1900
|
+
/// bytes at the store's file path were not updated. **So the two are classified apart (`saveRefused`) and the
|
|
1901
|
+
/// save's arm does NOT narrow the address verification**: every address the restore moved is counted exactly as
|
|
1902
|
+
/// on the passing arm, **and the file's own half is counted beside them** (`unsaved`), which is the one datum
|
|
1903
|
+
/// `undoSpelling` needs to say *"the memory was restored and the bytes were not"*. **NO BYTE IS WRITTEN HERE AND
|
|
1904
|
+
/// NO SECOND SAVE IS ATTEMPTED** — the store's answer is the whole report.
|
|
1310
1905
|
function restoreReversal(instance, moved) {
|
|
1311
1906
|
const addon_ = withAddon();
|
|
1907
|
+
// **THE ONE ACT: THE STORE RETURNS ITS OWN STATE TO THE MARK ITS COMMIT CACHED AT ITS OPENING** (`windowMark`,
|
|
1908
|
+
// `state.mjs`) — NOT to the journal's head, which is the write's own landing on the restart arm. **THE CARRIER
|
|
1909
|
+
// IS THE STORE'S OWN ANSWER, HANDED BACK VERBATIM**: `{k:'s', v:<op id>}` names an entry and `{k:'F'}` names the
|
|
1910
|
+
// FLOOR (the state the store was born with, where the journal held no entry when the commit opened). **NOTHING
|
|
1911
|
+
// IS COMPOSED HERE**, so the mark has one spelling and it lives at the store's edge.
|
|
1912
|
+
let refused = null;
|
|
1913
|
+
let cacheless = false;
|
|
1914
|
+
const mark = windowMark(instance);
|
|
1915
|
+
if (mark === undefined) {
|
|
1916
|
+
// **A WINDOW WITH NO CACHE IS A WINDOW THAT NEVER OPENED, AND THIS REFUSES RATHER THAN FALLING BACK TO THE
|
|
1917
|
+
// HEAD.** No store verb is invoked, so the store holds the state it held — and the count below claims NO
|
|
1918
|
+
// address restored, so the sentence that reaches the consumer says the reversal was not undone.
|
|
1919
|
+
cacheless = true;
|
|
1920
|
+
} else {
|
|
1921
|
+
try {
|
|
1922
|
+
Reflect.apply(addon_.restoreMark, instance, [mark]);
|
|
1923
|
+
} catch (why) {
|
|
1924
|
+
refused = why;
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
// **THE STORE'S ANSWER IS CLASSIFIED BEFORE ANY ADDRESS IS COUNTED — 2026-10-27, THE FILE-SAVE RULING.** A
|
|
1928
|
+
// REFUSED MARK leaves the store as it was, so no address may be claimed restored. **A FAILED SAVE does not**:
|
|
1929
|
+
// the store's replay already ran and the restored state STANDS, so every address is verified and counted
|
|
1930
|
+
// exactly as it is on the passing arm, and the file's own half is recorded beside the count (`unsaved`) for
|
|
1931
|
+
// the ONE sentence that names it. **THIS IS THE VERIFICATION EXTENDED TO THE FILE**: the restore already
|
|
1932
|
+
// counts the addresses it put back; the count is not narrowed by a failure that did not affect them, and the
|
|
1933
|
+
// bytes are reported as the thing that did fail. **AND THE CACHELESS ARM IS A THIRD, WHICH NEVER RESTORES**:
|
|
1934
|
+
// no mark was supplied, so no address may be counted.
|
|
1935
|
+
const unsaved = saveRefused(refused);
|
|
1936
|
+
const stateRestored = cacheless === false && (refused === null || unsaved !== null);
|
|
1312
1937
|
let restored = 0;
|
|
1313
1938
|
const failed = [];
|
|
1939
|
+
// ONE VERIFICATION PER ADDRESS: two pairs over one address (or one pair naming it twice) must not be counted
|
|
1940
|
+
// twice, so the addresses already measured are remembered — by a local loop, never by `Array.prototype.includes`
|
|
1941
|
+
// on a refusal path (`contract.md §2.1`'s clause on `F8-2` and item `(2b)`'s row `54`).
|
|
1942
|
+
const measured = [];
|
|
1314
1943
|
for (let index = 0; index < moved.length; index += 1) {
|
|
1315
1944
|
const one = moved[index];
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
if (one.before !== undefined) {
|
|
1324
|
-
const fault = { found: null, value: undefined, path: [], subject: null, nodes: 0 };
|
|
1325
|
-
const carried = encodeValue(one.before, [], 0, [], fault);
|
|
1326
|
-
if (fault.found !== null) throw fault.found;
|
|
1327
|
-
Reflect.apply(addon_.write, instance, [
|
|
1328
|
-
encodeAddress(one.address, undefined, 'first argument'),
|
|
1329
|
-
encodeTier('mem', true, false, 'first argument'),
|
|
1330
|
-
carried,
|
|
1331
|
-
]);
|
|
1332
|
-
}
|
|
1945
|
+
const key = homeAddressKey(one.address);
|
|
1946
|
+
if (hasOwnSpelling(measured, key) === true) continue;
|
|
1947
|
+
appendOwn(measured, key);
|
|
1948
|
+
// **THE ADDRESS IS READ AGAIN, AGAINST THE CAPTURE** — the cross-tier standing and every tier with its own
|
|
1949
|
+
// value — and it counts as restored ONLY where both equal what the watch took before the reversal.
|
|
1950
|
+
const verdict = standingVerdict(instance, one);
|
|
1951
|
+
if (stateRestored && verdict.exact === true) {
|
|
1333
1952
|
restored += 1;
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1953
|
+
continue;
|
|
1954
|
+
}
|
|
1955
|
+
// AN ADDRESS THAT DOES NOT STAND AGAIN IS NAMED, WITH WHAT STANDS THERE INSTEAD AND WHAT IT WAS OWED, so the
|
|
1956
|
+
// consumer is never told the store was put back when it was not.
|
|
1957
|
+
appendOwn(failed, {
|
|
1958
|
+
address: one.address,
|
|
1959
|
+
before: one.before,
|
|
1960
|
+
beforeTier: one.beforeTier,
|
|
1961
|
+
beforeTiers: one.beforeTiers,
|
|
1962
|
+
standing: verdict.value,
|
|
1963
|
+
tiers: verdict.tiers,
|
|
1964
|
+
});
|
|
1965
|
+
}
|
|
1966
|
+
return { restored, total: measured.length, failed, refused, unsaved, cacheless };
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
/// **WHETHER A LOCAL LIST OF SPELLINGS ALREADY HOLDS ONE** — a local index loop and not `Array.prototype.includes`.
|
|
1970
|
+
function hasOwnSpelling(spellings, spelling) {
|
|
1971
|
+
for (let index = 0; index < spellings.length; index += 1) {
|
|
1972
|
+
if (spellings[index] === spelling) return true;
|
|
1973
|
+
}
|
|
1974
|
+
return false;
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
/// **THE ADDRESS AS IT STANDS NOW, MEASURED AGAINST WHAT THE WATCH CAPTURED** — the check that turns "the
|
|
1978
|
+
/// restore ran" into "the restore LOOKED": the cross-tier standing, every tier that stands with its value, and
|
|
1979
|
+
/// `exact` only where the standing equals the captured one AND the tier set with its per-tier values equals the
|
|
1980
|
+
/// captured set. **A capture of no tier requires ABSENCE** (`value === undefined`), which is the state an
|
|
1981
|
+
/// address that stood at no tier is owed.
|
|
1982
|
+
function standingVerdict(instance, one) {
|
|
1983
|
+
const value = standingAt(instance, one.address);
|
|
1984
|
+
const tiers = [];
|
|
1985
|
+
for (let index = 0; index < STANDING_TIERS.length; index += 1) {
|
|
1986
|
+
const tier = STANDING_TIERS[index];
|
|
1987
|
+
const stood = standingAtTier(instance, one.address, tier);
|
|
1988
|
+
if (stood.stood === true) appendOwn(tiers, { tier, value: stood.value });
|
|
1989
|
+
}
|
|
1990
|
+
if (one.beforeTiers.length === 0) {
|
|
1991
|
+
return { exact: value === undefined && tiers.length === 0, value, tiers };
|
|
1992
|
+
}
|
|
1993
|
+
if (sameStanding(value, one.before) === false) return { exact: false, value, tiers };
|
|
1994
|
+
if (tiers.length !== one.beforeTiers.length) return { exact: false, value, tiers };
|
|
1995
|
+
for (let index = 0; index < tiers.length; index += 1) {
|
|
1996
|
+
if (tiers[index].tier !== one.beforeTiers[index].tier) return { exact: false, value, tiers };
|
|
1997
|
+
if (sameStanding(tiers[index].value, one.beforeTiers[index].value) === false) {
|
|
1998
|
+
return { exact: false, value, tiers };
|
|
1338
1999
|
}
|
|
1339
2000
|
}
|
|
1340
|
-
return {
|
|
2001
|
+
return { exact: true, value, tiers };
|
|
1341
2002
|
}
|
|
1342
2003
|
|
|
1343
2004
|
/// **THE SENTENCE THE LOG CARRIES ABOUT THE UNDOING** — the refusal's own record of the compensating act, read
|
|
1344
|
-
/// at the ONE site that builds the log entry.
|
|
1345
|
-
///
|
|
2005
|
+
/// at the ONE site that builds the log entry. **IT MAY CLAIM *"THE REVERSAL WAS UNDONE"* ONLY WHERE EVERY ADDRESS
|
|
2006
|
+
/// IT MOVED STANDS AGAIN EXACTLY AS IT STOOD** (`restoreReversal`'s verdict); where it cannot, **it names each
|
|
2007
|
+
/// address that could not be restored and says what stands there INSTEAD and what it was owed** (`D-41` item `2`:
|
|
2008
|
+
/// *"a message must not claim a restoration that did not happen"*). `DEF-Q`: no column prints `undefined`.
|
|
2009
|
+
///
|
|
2010
|
+
/// **⟶ AND THE TWO ARMS THE STORE CAN ANSWER WITH ARE NAMED SEPARATELY, 2026-10-27 (THE FILE-SAVE RULING).**
|
|
2011
|
+
/// **A REFUSED MARK** means the store holds what it held, and the sentence says exactly that. **A FAILED SAVE
|
|
2012
|
+
/// does not mean that**: the store's replay ran, every address the restore moved IS restored in memory, and the
|
|
2013
|
+
/// one thing that failed is the write of the bytes at the store's file path. **So the sentence opens by saying
|
|
2014
|
+
/// BOTH — the in-memory state was restored and the bytes were not updated — carries the store's own
|
|
2015
|
+
/// `FileCommitFailed` and its generated message (`DD-52`: never a second source), and then makes the ordinary
|
|
2016
|
+
/// claim the verification supports.** A consumer that reads only the first clause of this sentence therefore
|
|
2017
|
+
/// learns the two facts the failure owes it, in the order that matters.
|
|
1346
2018
|
function undoSpelling(undo) {
|
|
2019
|
+
// **⟶ AND WHERE THE STORE ITSELF REFUSED THE MARK, THE SENTENCE OPENS WITH THAT** (2026-10-27): the act is the
|
|
2020
|
+
// store's own (`restoreReversal`), so a refusal it answered is the FIRST thing a consumer must hear — its
|
|
2021
|
+
// status and its own generated message (`DD-52`) — and it is never spoken for by a claim about the state.
|
|
2022
|
+
let refusal = '';
|
|
2023
|
+
if (undo.cacheless === true) {
|
|
2024
|
+
// **⟶ AND THE CACHELESS ARM OPENS THE SENTENCE, 2026-10-27** (`restoreReversal` above): **a window with no
|
|
2025
|
+
// cached journal mark is a window that never opened, and the act refused rather than falling back to the
|
|
2026
|
+
// head.** No status is named — no store verb was reached and none refused — and the one fact a consumer must
|
|
2027
|
+
// hear is that nothing was restored, which is what the count below then spells address by address.
|
|
2028
|
+
refusal = 'the commit window this reversal ran in carries NO CACHED JOURNAL MARK, so the store was NOT asked '
|
|
2029
|
+
+ 'to restore it and holds the state the reversal left; ';
|
|
2030
|
+
} else if (undo.unsaved !== null && undo.unsaved !== undefined) {
|
|
2031
|
+
// THE SAVE'S ARM: read as own data members and off no chain (`D-35`'s read half), exactly as the refused
|
|
2032
|
+
// mark's status and sentence are read below.
|
|
2033
|
+
const carried = typeof undo.unsaved === 'object';
|
|
2034
|
+
const status = carried === true ? ownDataMember(undo.unsaved, 'status') : undefined;
|
|
2035
|
+
const said = carried === true ? ownDataMember(undo.unsaved, 'message') : undefined;
|
|
2036
|
+
refusal = 'the store restored its own state to the journal mark IN MEMORY and its FILE WAS NOT UPDATED ('
|
|
2037
|
+
+ `${JSON.stringify(typeof status === 'string' ? status : 'a refusal')}: `
|
|
2038
|
+
+ `${typeof said === 'string' ? said : ''}) — the bytes at the store's file path still describe the state `
|
|
2039
|
+
+ 'that stood before the reversal; ';
|
|
2040
|
+
} else if (undo.refused !== null && undo.refused !== undefined) {
|
|
2041
|
+
// READ AS OWN DATA MEMBERS AND OFF NO CHAIN (`D-35`'s read half): the store's own plain refusal carries
|
|
2042
|
+
// `{status, message}` and nothing else, and a thrown value that is not an object is named as itself.
|
|
2043
|
+
const carried = typeof undo.refused === 'object';
|
|
2044
|
+
const status = carried === true ? ownDataMember(undo.refused, 'status') : undefined;
|
|
2045
|
+
const said = carried === true ? ownDataMember(undo.refused, 'message') : undefined;
|
|
2046
|
+
refusal = `the store REFUSED the journal mark (${JSON.stringify(typeof status === 'string' ? status : 'a refusal')}`
|
|
2047
|
+
+ `: ${typeof said === 'string' ? said : ''}) and holds the state it held; `;
|
|
2048
|
+
}
|
|
1347
2049
|
if (undo.failed.length === 0) {
|
|
1348
|
-
return
|
|
2050
|
+
return `${refusal}the reversal was UNDONE: every address it moved stands again exactly as it stood before `
|
|
2051
|
+
+ 'the reversal — the same value at the same tier, or absent where it was absent';
|
|
1349
2052
|
}
|
|
1350
2053
|
let named = '';
|
|
1351
2054
|
for (let index = 0; index < undo.failed.length; index += 1) {
|
|
1352
|
-
|
|
2055
|
+
const one = undo.failed[index];
|
|
2056
|
+
named += index === 0 ? '' : '; ';
|
|
2057
|
+
named += `${addressSpelling(one.address)} could not be restored and stands `
|
|
2058
|
+
+ `${standingDescription(one.standing, one.tiers)} where it stood `
|
|
2059
|
+
+ `${capturedDescription(one)} before the reversal`;
|
|
2060
|
+
}
|
|
2061
|
+
const moved = undo.total === 1 ? 'address' : 'addresses';
|
|
2062
|
+
const still = undo.restored === 1 ? 'stands' : 'stand';
|
|
2063
|
+
return `${refusal}the reversal was NOT undone at every address it moved (${undo.restored} of the `
|
|
2064
|
+
+ `${undo.total} ${moved} it moved ${still} again): ${named}`;
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
/// **A STANDING AS A SENTENCE — WHAT VALUE, AT WHICH TIER, OR ABSENCE** (`DEF-Q`: no column prints `undefined`).
|
|
2068
|
+
function standingDescription(value, tiers) {
|
|
2069
|
+
if (tiers.length === 0) {
|
|
2070
|
+
return value === undefined
|
|
2071
|
+
? 'at no value and no tier (absent)'
|
|
2072
|
+
: `at the value ${standingSpelling(value)} and at no tier this act can name`;
|
|
2073
|
+
}
|
|
2074
|
+
let spelled = 'at ';
|
|
2075
|
+
for (let index = 0; index < tiers.length; index += 1) {
|
|
2076
|
+
spelled += index === 0 ? '' : ' and ';
|
|
2077
|
+
spelled += `tier \`${tiers[index].tier}\` holding ${standingSpelling(tiers[index].value)}`;
|
|
2078
|
+
}
|
|
2079
|
+
return spelled;
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
/// **THE CAPTURED STANDING AS THE SAME SENTENCE — what the address was owed**, tier by tier with each tier's own
|
|
2083
|
+
/// value (so a shadow's two versions are both named and neither is spoken for the other). **AND WHERE IT STOOD
|
|
2084
|
+
/// AT MORE THAN ONE TIER, THE TIER THE CROSS-TIER READ DREW FROM IS NAMED BESIDE THEM** — the watch's
|
|
2085
|
+
/// `beforeTier`, which is what the consumer's own `read` would have answered at that instant.
|
|
2086
|
+
function capturedDescription(one) {
|
|
2087
|
+
const tiers = one.beforeTiers;
|
|
2088
|
+
if (tiers.length === 0) return 'at no value and no tier (absent)';
|
|
2089
|
+
let spelled = 'at ';
|
|
2090
|
+
for (let index = 0; index < tiers.length; index += 1) {
|
|
2091
|
+
spelled += index === 0 ? '' : ' and ';
|
|
2092
|
+
spelled += `tier \`${tiers[index].tier}\` holding ${standingSpelling(tiers[index].value)}`;
|
|
2093
|
+
}
|
|
2094
|
+
if (tiers.length > 1) {
|
|
2095
|
+
spelled += ` (the cross-tier read answered tier \`${one.beforeTier}\`)`;
|
|
1353
2096
|
}
|
|
1354
|
-
return
|
|
1355
|
-
+ 'judgement refused';
|
|
2097
|
+
return spelled;
|
|
1356
2098
|
}
|
|
1357
2099
|
|
|
1358
2100
|
|
|
@@ -1369,6 +2111,22 @@ function standingAt(instance, address) {
|
|
|
1369
2111
|
}
|
|
1370
2112
|
}
|
|
1371
2113
|
|
|
2114
|
+
/// **THE STORE'S STANDING AT ONE ADDRESS NARROWED TO ONE TIER — THE SAME ROUTE, ONE ARGUMENT FURTHER** (the
|
|
2115
|
+
/// `read` member's declared tier position, `a.read(address, tier?)`; `src/args.rs`'s `read_tier_sel` admits ONE
|
|
2116
|
+
/// token and answers that tier's version). **`stood: false` is the tier's own absence** — `TierNotFound` where
|
|
2117
|
+
/// the key holds no version at that tier, `AddressNotFound` where it holds none at all — and **`stood: true` with
|
|
2118
|
+
/// the value is what that tier answers**, which is the capture a tier-exact restore writes back.
|
|
2119
|
+
///
|
|
2120
|
+
/// **AND THE REFUSAL'S OWN CODE IS NOT READ HERE**: a tier probe asks one question — does this tier stand? — and
|
|
2121
|
+
/// every refusal to it answers the same thing, so no code is put in a value slot on this path (`DD-12`).
|
|
2122
|
+
function standingAtTier(instance, address, tier) {
|
|
2123
|
+
try {
|
|
2124
|
+
return { stood: true, value: instance.read(address, tier) };
|
|
2125
|
+
} catch (refused) {
|
|
2126
|
+
return { stood: false, value: undefined };
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
|
|
1372
2130
|
/// **WHETHER TWO STANDINGS ARE THE SAME STATE** — the comparison the word "touched" is decided by. **IT IS
|
|
1373
2131
|
/// STRUCTURAL AND IT IS TAKEN ON THE STORE'S OWN DECODED VALUES**, which the crossing admits as JSON values
|
|
1374
2132
|
/// (`docs/specs/storeroom-json-crossing/`): `Object.is` for the primitives, then `length` and index for the
|
|
@@ -1415,11 +2173,26 @@ function ownDataMember(value, name) {
|
|
|
1415
2173
|
/// **A BODY THAT THROWS IS THE SURFACE'S RANK-`18` `ConstraintBodyThrew`, NOT A RAW HOST ERROR** (`DEF-S`'s
|
|
1416
2174
|
/// ruling, `D-38`; `src/error.rs`'s `[&str; 20]` rank `18`): the mark the kernel sets at its own three frames
|
|
1417
2175
|
/// (`markBodyThrow`) is spelled on this side under the same `Symbol.for` key — so the value crosses through
|
|
1418
|
-
/// `bodyThrowRefusal` and this surface's ONE form
|
|
1419
|
-
///
|
|
1420
|
-
///
|
|
1421
|
-
///
|
|
1422
|
-
|
|
2176
|
+
/// `bodyThrowRefusal` and this surface's ONE form. **WHERE THE TREE CARRIES NO USABLE GENERATOR THE BODY'S OWN
|
|
2177
|
+
/// VALUE CROSSES AS ITSELF**, which is the safe direction `registrationCrossing` already takes and the one
|
|
2178
|
+
/// `fail-surface.md §1.1` item 5 declares for a body's throwable.
|
|
2179
|
+
///
|
|
2180
|
+
/// **⟶ AND THE THROWN VALUE NO LONGER ESCAPES THE JUDGEMENT UNCOMPENSATED, 2026-10-27 (`D-41` item `4`;
|
|
2181
|
+
/// ANNOTATE-BESIDE).** The clause above read *"with `log: []` (no attempt stands at a reversal's judgement)"*,
|
|
2182
|
+
/// and the throw then propagated out of `judgeReversal` **with the reversal's effect standing and `log` `[]`** —
|
|
2183
|
+
/// measured: the store held the state nobody could judge and the consumer was told nothing had been undone. **The
|
|
2184
|
+
/// conversion here is unchanged and is the CATCHER'S**: `judgeReversal` catches what this function throws (the
|
|
2185
|
+
/// converted rank-`18` form, or the body's own value where no generator stands), restores, and refuses with a log
|
|
2186
|
+
/// that names this pair — so the empty log this clause named as the arm's fact is superseded by the judgement's
|
|
2187
|
+
/// own arm, and no byte of the conversion moves.
|
|
2188
|
+
///
|
|
2189
|
+
/// **⟶ AND THE BODY IS INVOKED WITH NOTHING NAMED, 2026-10-27 (`D-45`, `D-46` item `1`).** A pair's constraint
|
|
2190
|
+
/// body is EXTERNALLY-SUPPLIED FUNCTION code entering the surface **and it has no commit to name** — its
|
|
2191
|
+
/// five-member context carries none (`kernel-surface.md §2.3` item 1) — so **a verb the body calls OPENS ITS OWN
|
|
2192
|
+
/// COMMIT** rather than joining the commit the reversal is being judged inside. **THE CONTEXT IS BUILT ABOVE THE
|
|
2193
|
+
/// INVOCATION**, so the store read the context owes is this frame's act and not the body's, and the conversion
|
|
2194
|
+
/// below is unchanged.
|
|
2195
|
+
function reversalOutcome(instance, entry, address, value) {
|
|
1423
2196
|
const context = {
|
|
1424
2197
|
address: address.slice(),
|
|
1425
2198
|
tier: null,
|
|
@@ -1428,7 +2201,7 @@ function reversalOutcome(entry, address, value) {
|
|
|
1428
2201
|
op: null,
|
|
1429
2202
|
};
|
|
1430
2203
|
try {
|
|
1431
|
-
return entry.fn(context);
|
|
2204
|
+
return externalCall(instance, () => entry.fn(context));
|
|
1432
2205
|
} catch (body) {
|
|
1433
2206
|
const carried = Object.create(null);
|
|
1434
2207
|
// THE TWO SLOTS THE KERNEL'S OWN MARK CARRIES (`kernel-foundations.mjs`'s `markBodyThrow`): the pair's
|
|
@@ -1456,50 +2229,109 @@ function reversalSaid(outcome) {
|
|
|
1456
2229
|
/// GENERATED SENTENCE** at the pair's own `<SEGMENT>` slot (`addon_.errorMessage` — `DD-52` forbids a second
|
|
1457
2230
|
/// source, so nothing is authored here; the fixed sentence below is reached only on a tree whose generator is
|
|
1458
2231
|
/// unusable, which is the same arm `constraintCrossing` answers with a fixed sentence), **and THE `log` IS ONE
|
|
1459
|
-
/// `constraint-check` ENTRY
|
|
2232
|
+
/// `constraint-check` ENTRY NAMING THE CONSTRAINT AND THE STATE IT REFUSED.**
|
|
1460
2233
|
///
|
|
1461
2234
|
/// **THE ENTRY IS BUILT HERE AND NOT BY THE KERNEL, AND THE ODD MEMBER IS SAID PLAINLY: no attempt stands at
|
|
1462
2235
|
/// a reversal's judgement**, so there is no attempt log to carry verbatim (`§2.5` item 3's `log` is *"the
|
|
1463
|
-
/// attempt's own message log"*).
|
|
1464
|
-
///
|
|
1465
|
-
///
|
|
1466
|
-
///
|
|
1467
|
-
|
|
2236
|
+
/// attempt's own message log"*).
|
|
2237
|
+
///
|
|
2238
|
+
/// **⟶ AND THE ENTRY CARRIES FIVE MEMBERS AND NOT SIX, 2026-10-27 — `D-41` ITEM `4`, ANNOTATE-BESIDE.** The
|
|
2239
|
+
/// clause above read *"The six members, their `constraint-check` kind and their `seq` ordinal are the kernel's
|
|
2240
|
+
/// own shape"* and the entry minted `seq: 1`; **THAT `1` WAS FABRICATED AND HAS NO RECORD BEHIND IT.** The
|
|
2241
|
+
/// kernel's `seq` is the ORDINAL WITHIN AN ATTEMPT'S OWN LOG (`kernel-foundations.mjs`'s `append`:
|
|
2242
|
+
/// `attempt.log.length + 1`, withdrawn entries renumbered) — **and no attempt stands at a reversal's judgement,
|
|
2243
|
+
/// so there is no log whose ordinal this is and no member of any record here that it could be read from.**
|
|
2244
|
+
/// `contract.md §2.6` item 4's clause of 2026-10-26 declared the `1`; **this pass does not mint it.** The entry
|
|
2245
|
+
/// therefore carries the other five members — `kind` · `id` · `message` · `opId` · `state` — and **no `seq` at
|
|
2246
|
+
/// all**: the honest form of a record whose ordinal is unknown is an absent member, never a number invented for
|
|
2247
|
+
/// it (`D-21`: a member that did not stand says so).
|
|
2248
|
+
///
|
|
2249
|
+
/// **AND IT HAS A SECOND ARM — THE JUDGEMENT THAT COULD NOT COMPLETE (`D-41` item `4`).** Where `thrown` is the
|
|
2250
|
+
/// value a pair's body threw at this judgement, the entry is the same five-member `constraint-check` naming the
|
|
2251
|
+
/// same pair, the state the reversal left and the undoing, **and the crossed `status` is the set's rank-`18`
|
|
2252
|
+
/// member `ConstraintBodyThrew` with the store's own sentence for it** — the code says what happened (a body
|
|
2253
|
+
/// threw), while the treatment is the violation arm's: the reversal was restored and the pair is named.
|
|
2254
|
+
/// **WHERE THE THROWN VALUE IS NOT THE KERNEL'S MARKED FORM** (a body's raw throwable on a tree with no usable
|
|
2255
|
+
/// generator), the same rank-`18` refusal is built here — the restoration and the pair's name cross regardless
|
|
2256
|
+
/// of the body's own value's class, which is the difference between a compensating act and a conversion.
|
|
2257
|
+
function reversalRefusal(one, after, said, reversalId, undo, thrown, unsettled = false) {
|
|
1468
2258
|
const addon_ = withAddon();
|
|
1469
2259
|
// **THE `<SEGMENT>` SLOT IS THE ADDRESS SPELLING THE KERNEL'S OWN REGISTRATION REFUSAL HANDS THE SAME
|
|
1470
2260
|
// GENERATOR** (`kernel-registration.mjs`'s `registrationRefusal`: the segments joined by `/`, BARE — the
|
|
1471
2261
|
// generator's own `build` is what prints a string segment single-quoted, so a pre-quoted spelling here
|
|
1472
2262
|
// would print `''a''`). One spelling, one home, and no second quoting rule.
|
|
1473
2263
|
const subject = addressSpelling(one.address);
|
|
2264
|
+
// **⟶ AND THE UNQUIET ARM KEEPS THE SAME CROSSED STATUS, `D-42` (2026-10-27).** A restart that spends its
|
|
2265
|
+
// budget has not been JUDGED — it could not settle — and **a check that will not settle is a check that does
|
|
2266
|
+
// not pass** (`D-41` item `4`'s own direction), so the status is the set's rank-`20` member for a refused
|
|
2267
|
+
// pass, exactly the one the at-rest control crosses with. **ONLY THE LOG ENTRY'S SENTENCE DIFFERS**, so that
|
|
2268
|
+
// no consumer is told a pair refused a state it never got to judge.
|
|
2269
|
+
const status = thrown === null ? CONSTRAINT_PASS_REFUSED : BODY_THREW_STATUS;
|
|
1474
2270
|
let message = '';
|
|
1475
2271
|
if (typeof addon_.errorMessage === 'function') {
|
|
1476
|
-
const generated = addon_.errorMessage(
|
|
1477
|
-
if (typeof generated === 'string') message = generated;
|
|
2272
|
+
const generated = addon_.errorMessage(status, subject, 'constraints');
|
|
2273
|
+
if (typeof generated === 'string' && generated.length > 0) message = generated;
|
|
1478
2274
|
}
|
|
1479
2275
|
if (message === '') {
|
|
1480
|
-
message =
|
|
1481
|
-
|
|
2276
|
+
message = thrown === null
|
|
2277
|
+
? 'the reversal was refused by a constraint pass, the state it would leave is not one the registered '
|
|
2278
|
+
+ 'constraints admit'
|
|
2279
|
+
: 'the reversal was refused by a constraint body that threw, the state it would leave could not be judged';
|
|
2280
|
+
}
|
|
2281
|
+
// **THE LOG ENTRY'S SENTENCE, AT ITS THREE ARMS** — a pair that refused the state the reversal (or the
|
|
2282
|
+
// in-commit action) left, a body that threw at the judgement of it, and — from `D-42` — **the restart's own
|
|
2283
|
+
// budget spent**. The third arm is the one the restart's exhaustion reaches and it names no refusing pair.
|
|
2284
|
+
let spelled;
|
|
2285
|
+
if (unsettled === true) {
|
|
2286
|
+
spelled = `the constraint ${one.entry.id} could not be asked a state that would settle at `
|
|
2287
|
+
+ `${addressSpelling(one.address)}: the value there is ${standingSpelling(after)} — the check was `
|
|
2288
|
+
+ `restarted ${RESTART_LIMIT} times and a pair body acted inside the check at every restart, so the `
|
|
2289
|
+
+ `restart budget is spent and the check does not pass — ${undoSpelling(undo)}`;
|
|
2290
|
+
} else if (thrown === null) {
|
|
2291
|
+
spelled = `the constraint ${one.entry.id} refused the state the reversal left at `
|
|
2292
|
+
+ `${addressSpelling(one.address)}: the value there is ${standingSpelling(after)}`
|
|
2293
|
+
+ (said === null ? '' : ` — ${said}`)
|
|
2294
|
+
+ ` — ${undoSpelling(undo)}`;
|
|
2295
|
+
} else {
|
|
2296
|
+
spelled = `the constraint ${one.entry.id} THREW at the judgement of the state the reversal left at `
|
|
2297
|
+
+ `${addressSpelling(one.address)}: the value there is ${standingSpelling(after)}`
|
|
2298
|
+
+ ` — ${undoSpelling(undo)}`;
|
|
1482
2299
|
}
|
|
1483
2300
|
const entry = {
|
|
1484
|
-
seq
|
|
2301
|
+
// **⟶ AND THE `seq` STANDS, 2026-10-28 — `DEF-AI`: THE ENTRY'S DECLARED SHAPE IS THE KERNEL'S CLOSED SIX
|
|
2302
|
+
// AND THIS ONE CARRIED FIVE.** The 2026-10-27 clause below withdrew the `1` as FABRICATED, on the reading
|
|
2303
|
+
// that `seq` is *"the ordinal within an ATTEMPT's own log"* and that no attempt stands at a reversal's
|
|
2304
|
+
// judgement. **THE READING IS RIGHT ABOUT THE ATTEMPT AND WRONG ABOUT THE MEMBER.** `seq`'s DECLARED
|
|
2305
|
+
// DOMAIN is *"the append ordinal, strictly increasing from `1` in array order"*
|
|
2306
|
+
// (`docs/specs/storeroom-constraints/kernel-surface.md §2.5` item 1), and the array this entry stands in is
|
|
2307
|
+
// THIS REFUSAL'S OWN ONE-ENTRY LIST: its first element's ordinal is `1` BY THAT RULE, not by invention —
|
|
2308
|
+
// the same arithmetic the kernel's own `append` performs (`log.length + 1`, read off the list the entry
|
|
2309
|
+
// stands in). **AND THE TWO COPIES OF THIS VERY ENTRY ALREADY DISAGREED**: `carryRestartRefusal` re-appends
|
|
2310
|
+
// it into the attempt's log through `append`, where it carries `seq` `1`, while the list that crosses to
|
|
2311
|
+
// the caller carried none — one entry, two shapes, which is this branch's `DEF-AI` class exactly. **`log`
|
|
2312
|
+
// IS DECLARED `LogEntry[]`** (`bindings/js/index.d.ts`), so a consumer typing it read `undefined` where
|
|
2313
|
+
// `number` is declared. **THE DECLARATION IS NOT WEAKENED TO MATCH THE ENTRY: THE ENTRY CARRIES THE
|
|
2314
|
+
// MEMBER.** No other member, no second entry and no sentence moves.
|
|
1485
2315
|
kind: 'constraint-check',
|
|
2316
|
+
seq: 1,
|
|
1486
2317
|
id: one.entry.id,
|
|
1487
|
-
// **⟶ AND THE ENTRY SAYS THE
|
|
1488
|
-
// record, beside the state it refused, so a consumer that catches it knows
|
|
1489
|
-
// reversal found it (and is told plainly
|
|
1490
|
-
// sentence is this entry's, and no second log entry and no
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
+ ` — ${undoSpelling(undo)}`,
|
|
1495
|
-
// **THE STORE'S OWN ECHO OF THE ID THE REVERSAL NAMED, OR `null`** — the entry's sixth member is always
|
|
2318
|
+
// **⟶ AND THE ENTRY SAYS WHAT THE ACT DID, 2026-10-26 (`DEF-W`'s `(a)`) and 2026-10-27 (`D-41` item `2`)** —
|
|
2319
|
+
// the refusal's own record, beside the state it refused, so a consumer that catches it knows whether the
|
|
2320
|
+
// store stands again where the reversal found it (and is told plainly, and by address, where it does not).
|
|
2321
|
+
// ONE ENTRY, FIVE MEMBERS: the sentence is this entry's, and no second log entry and no sixth member is
|
|
2322
|
+
// minted.
|
|
2323
|
+
message: spelled,
|
|
2324
|
+
// **THE STORE'S OWN ECHO OF THE ID THE REVERSAL NAMED, OR `null`** — the entry's fifth member is always
|
|
1496
2325
|
// present and of the kernel's own domain (`kernel-surface.md §2.5` item 1: a `string | null`), never absent.
|
|
1497
2326
|
opId: typeof reversalId === 'string' ? reversalId : null,
|
|
1498
2327
|
state: null,
|
|
1499
2328
|
};
|
|
1500
2329
|
const log = [];
|
|
1501
2330
|
appendOwn(log, entry);
|
|
1502
|
-
|
|
2331
|
+
// **THE CROSSED `status` IS THE ARM'S OWN AND IS NEVER MINTED** (`DD-40`): rank `20` where a pair refused the
|
|
2332
|
+
// state the reversal left, rank `18` where a pair's body threw at the judgement of it (`D-41` item `4`). The
|
|
2333
|
+
// sentence beside it was generated for that same code — one source for each (`DD-52`).
|
|
2334
|
+
return { status, message, log: refusalLog(log) };
|
|
1503
2335
|
}
|
|
1504
2336
|
|
|
1505
2337
|
/// **THE ADDRESS'S OWN `<SEGMENT>` SPELLING, JOINED BY `/` AND BARE** — the kernel's own
|