provident-storeroom 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +215 -76
- package/index.mjs +748 -292
- package/package.json +8 -7
- package/src/constraint-kernel.mjs +1330 -0
|
@@ -0,0 +1,1330 @@
|
|
|
1
|
+
// `U-STOREROOM-CONSTRAINTS` — THE CALLER-SIDE CONSTRAINT KERNEL. ZERO DEPENDENCIES.
|
|
2
|
+
//
|
|
3
|
+
// The kernel lives in the Node.js space and reaches the store through the store's own declared
|
|
4
|
+
// verbs (`kernel-surface.md §1` item 1). It holds no store of its own: every one of the five items
|
|
5
|
+
// takes THE CALLER'S OWN STORE INSTANCE first.
|
|
6
|
+
//
|
|
7
|
+
// THE FIVE ITEMS AND NOTHING ELSE (`kernel-surface.md §1` item 2):
|
|
8
|
+
// K-1 register(store, address, id, constraint) -> Handle
|
|
9
|
+
// K-2 commit(store, address, tier, value) -> CommitRecord
|
|
10
|
+
// K-3 runAttempt(store, commit) -> AttemptReport
|
|
11
|
+
// K-4 log(store, attempt) -> LogEntry[]
|
|
12
|
+
// K-5 report(store, attempt) -> AttemptReport
|
|
13
|
+
//
|
|
14
|
+
// EVERY ARGUMENT'S DOMAIN, EVERY RECORD'S MEMBER SET AND EVERY STATE TOKEN ARE READ FROM THE
|
|
15
|
+
// CONTRACT DIRECTORY: `parameter-semantics.md §2.1`–`§2.17`, `attempt-lifecycle.md §2.4`,
|
|
16
|
+
// `composition-and-states.md §2.6`, `fail-surface.md §1`–`§2`.
|
|
17
|
+
|
|
18
|
+
// THE MODULE'S WHOLE IMPORT FOOTPRINT, AND IT CARRIES NO SECOND LOAD PATH (`kernel-surface.md §1` item
|
|
19
|
+
// 1's fixture clause; `parameter-semantics.md §2.7`'s no-second-route clause; `A: docs/decisions.md` ·
|
|
20
|
+
// `A110`): **NOTHING** — no `createRequire`, no addon path, no native module and no dependency of the
|
|
21
|
+
// module's own. Every op this kernel credits is an op the caller's own instance's verb calls answered.
|
|
22
|
+
//
|
|
23
|
+
// **⟶ AND THE ENTRY IS NOT IMPORTED EITHER, FROM 2026-10-16 ON `A127` (`surface.md §2.9` item 1's and
|
|
24
|
+
// `§2.4` item 9 (f)'s `A127` clauses).** The import that stood here — `{ write, rollback, read }` from
|
|
25
|
+
// `'provident-storeroom'` — is REMOVED WITH THE TEN NAMES IT NAMED (`11 → 1` ✓): **the module namespace
|
|
26
|
+
// carries ONE name, `storeCreate`, and every store-reaching act is a METHOD of the object it returned**, so
|
|
27
|
+
// this module reaches the store through the caller's own instance's members and through nothing else (the
|
|
28
|
+
// fifth position's record included — `store.write(address, tier, value, record)`). **THE KERNEL'S OWN
|
|
29
|
+
// IMPORT FOOTPRINT IS THEREFORE EMPTY, WHICH IS WHAT THIS HEADER HAS DECLARED ALL ALONG** (`§1` item 1;
|
|
30
|
+
// the paragraph at `THE REPAIR'S OWN OP` below, whose *"the caller's own instance is the only way it ever
|
|
31
|
+
// reaches the store"* is now the code and no longer only the sentence).
|
|
32
|
+
|
|
33
|
+
// ---------------------------------------------------------------------------------------------
|
|
34
|
+
// `fail-surface.md §2` — THE KERNEL'S OWN CLOSED STATE SET, `8` MEMBERS AND NO NINTH.
|
|
35
|
+
// ---------------------------------------------------------------------------------------------
|
|
36
|
+
// `fail-surface.md §1.1` ITEM 1 (a) — THE ONE SPELLING, AND IT IS THE TOKEN: a refusal's `status` carries
|
|
37
|
+
// `KC-1`…`KC-8` and NOTHING ELSE. The full names (`ConstraintViolated` …) are LABELS: they keep exactly
|
|
38
|
+
// one declared use — the `name` column of `§2`'s table, and a citation beside a token — and NO clause
|
|
39
|
+
// spells a member's VALUE as a name. `status` and `LogEntry.state` therefore read THE SAME TOKEN STRING,
|
|
40
|
+
// related by IDENTITY (`§1.1` item 1 (c)). THE CENSUS DOES NOT MOVE: `8` members (`2 + 2 + 2 + 1 + 1`)
|
|
41
|
+
// on `13` sites (`1 + 4 + 4 + 3 + 1`).
|
|
42
|
+
const KC = {
|
|
43
|
+
address: 'KC-1', // ConstraintAddressRefused
|
|
44
|
+
arg: 'KC-2', // ConstraintArgRefused
|
|
45
|
+
violated: 'KC-3', // ConstraintViolated
|
|
46
|
+
repairFailed: 'KC-4', // ConstraintRepairFailed
|
|
47
|
+
repairRepeat: 'KC-5', // ConstraintRepairRepeat
|
|
48
|
+
repeat: 'KC-6', // ConstraintRepeat
|
|
49
|
+
attemptOpen: 'KC-7', // ConstraintAttemptOpen
|
|
50
|
+
rollbackFloor: 'KC-8', // ConstraintRollbackFloor
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** The eight tokens above, as the ONE list a member's own value is checked against — the kernel's own
|
|
54
|
+
* token is NEVER named as a store code (`fail-surface.md §1.1` item 1 (a); `§2`'s `KC-4` row). */
|
|
55
|
+
const KC_TOKENS = Object.values(KC);
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* `composition-and-states.md §2.6` item 5 (b) — THE COMPOSITION'S TWO FLOOR CODES, AND THE WHOLE OF THAT
|
|
59
|
+
* PART: "AN OP THE COMPOSITION STILL OWES WHOSE CALL FAILS EITHER FLOOR CODE — `RollbackCompacted` OR
|
|
60
|
+
* `JournalOpUnknown` — IS `KC-8`". The step's `answer` carries THE STORE'S OWN CODE on the throwing arm
|
|
61
|
+
* (item 3), so the floor is read off the step's own `answer` and off no other member.
|
|
62
|
+
*/
|
|
63
|
+
const STORE_FLOOR_CODES = ['RollbackCompacted', 'JournalOpUnknown'];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* **THE PASS'S OWN BOOKKEEPING OF WHAT ITS CHECK-OFFS CONSUMED, CARRIED TO THE TERMINAL ARM
|
|
67
|
+
* (`docs/specs/storeroom-js/surface.md §2.7` item 7's keying, read with `§2.4` item 8 (c) AS CORRECTED
|
|
68
|
+
* 2026-10-15 and `docs/decisions.md` · `A117` (D5)).**
|
|
69
|
+
*
|
|
70
|
+
* **THE CHECK-OFF KEEPS ITS ACT AND ITS LAW UNCHANGED**: it is still THE ONLY LAWFUL REMOVAL on a passing
|
|
71
|
+
* write (`kernel-surface.md §2.1` item 2), it still removes the evaluated identity's entry from the
|
|
72
|
+
* residue by identity (`releasePending` below), and every `pending`-based assertion about it stands — the
|
|
73
|
+
* residue is still the returned set MINUS the checked-off entries and MINUS nothing else, and a SIFT is
|
|
74
|
+
* still unlawful. **WHAT `A117` (D5) ADDS IS WHAT THE CHECK-OFF CONSUMED**: *"the check-off consumes the
|
|
75
|
+
* evaluated pair's own delivery of that identity, NOT that identity's whole owed delivery"* — the carrier
|
|
76
|
+
* has ONE entry per address, and the entry's own owed firings are not counted in `pending`; they are
|
|
77
|
+
* counted where the owed firings live, THE PACKAGE'S REGISTRY. So the identity a checked-off pair stood
|
|
78
|
+
* under is NOT an identity with no owed firing when a registration at that same address owes it one.
|
|
79
|
+
*
|
|
80
|
+
* **THIS MEMBER IS THAT FINDING, AND IT IS NOT A SECOND CHANNEL**: the entry already resolves a handle to
|
|
81
|
+
* its registered function for the residue, and this member names the identities whose pair the pass
|
|
82
|
+
* evaluated and checked off — the entry resolves THE SAME WAY over them at the terminal arm and delivers
|
|
83
|
+
* each ONCE (`§2.7` item 6: the other listeners are reached ONCE every constraint has passed). `A117`
|
|
84
|
+
* (D6): **NO MEMBER IS ADDED** — `CommitRecord` keeps its four members, the store keeps one home entry per
|
|
85
|
+
* address, and this finding is carried on the record under a SYMBOL key, which `Object.keys`,
|
|
86
|
+
* `Object.getOwnPropertyNames` and every declared census read past, so the named-shape set does not move.
|
|
87
|
+
*
|
|
88
|
+
* **AND IT IS PUBLISHED ONLY ON THE PASSING ARM** (`runAttempt`'s success arm, immediately before
|
|
89
|
+
* `settleArm`): on a FAILING write `A114` (D1)/(D2) discards the other listeners and NOTHING is delivered,
|
|
90
|
+
* so the arm's residue is empty AND the checked-off identity stands for no delivery — the marker is never
|
|
91
|
+
* placed on a closed attempt.
|
|
92
|
+
*/
|
|
93
|
+
const CHECKED_OFF = Symbol.for('provident-storeroom.checked-off-at-the-terminal-arm');
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* **⟶ ADDED 2026-10-15 (`surface.md §2.11` clauses 1–2; `contract.md §7.2` item 2 as amended) — THE PASSING
|
|
97
|
+
* ARM'S OWN MARK, PLACED BY THE KERNEL AND READ BY THE ENTRY'S SEAM.**
|
|
98
|
+
*
|
|
99
|
+
* **THE SEAM'S TERMINAL ARM PERFORMS THE STORE'S `file`-TIER COMMIT ON ITS PASSING ARM ALONE** (clause 1:
|
|
100
|
+
* *"the `file` tier, the TERMINAL ARM and the PASSING ARM alone"*), **and BOTH ARMS REACH THE SAME
|
|
101
|
+
* `settle` CALL** — `settleArm` is the one seam instant this kernel takes, and it is taken on the failing
|
|
102
|
+
* arm too, where clause 1 refuses the write a save and a store call of its own. **THE ARM IS THIS
|
|
103
|
+
* KERNEL'S OWN FACT AND NOBODY ELSE'S**, so it is told to the entry under a SYMBOL key, exactly as the
|
|
104
|
+
* check-off list is (`CHECKED_OFF` above): **NO MEMBER IS ADDED** to `CommitRecord` (`A117` (D6)), the
|
|
105
|
+
* record's four members and its `pending` member are untouched, and a census of either moves by nothing.
|
|
106
|
+
* **THE SYMBOL IS A WELL-KNOWN ONE DECLARED ON BOTH SIDES**, so the entry imports no kernel and the
|
|
107
|
+
* kernel imports no entry.
|
|
108
|
+
*/
|
|
109
|
+
const SETTLED_ON_THE_PASSING_ARM = Symbol.for('provident-storeroom.settled-on-the-passing-arm');
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* **⟶ ADDED 2026-10-15 (`surface.md §2.11` clause 5; `fail-surface.md §1.1` item 3; `kernel-surface.md §2.1`
|
|
113
|
+
* items 3–5) — THE FAILED SAVE'S OWN MARK, PLACED BY THE ENTRY'S SEAM ON THE RECORD IT WAS HANDED.**
|
|
114
|
+
*
|
|
115
|
+
* **THE SAVE IS A CONSTRAINT EVALUATED LAST, AND THE PASS REPORTS ITS FAILURE AS IT REPORTS ANY OTHER**
|
|
116
|
+
* (clause 5): the failed save's arm is the TERMINAL ACT — the per-op rollback composition FIRST, then the
|
|
117
|
+
* ONE `outcome` entry, then the refusal — so the closed attempt's FINAL log carries that entry, the
|
|
118
|
+
* terminal answer is that closed record's FINAL report (`K-4`/`K-5`), and the report's `rollback` member
|
|
119
|
+
* carries the rollback the composition PERFORMED. **THE ARM CANNOT BE READ OFF THE THROWN FORM**: the
|
|
120
|
+
* store's own verb produced this failure, so its code crosses on the STORE's channel and its two-member
|
|
121
|
+
* form reaches the caller unchanged (`§1.2` item 2) — the KERNEL's token stands in the `outcome` entry's
|
|
122
|
+
* `state` (`§1.2` item 3's repair-arm pattern, read at this arm).
|
|
123
|
+
*
|
|
124
|
+
* **SO THE ENTRY TELLS THE KERNEL WHICH ARM IT IS, ON THE IDENTITY THE KERNEL HOLDS**, exactly as
|
|
125
|
+
* `SETTLED_ON_THE_PASSING_ARM` tells the entry: it is set by `settleOn` at the ONE call the arm is made of
|
|
126
|
+
* — the store's `commit_file`, taken as the terminal arm's FIRST act — and it carries THE VERY THROWABLE
|
|
127
|
+
* the seam rethrew, so the kernel's own catch can tell the failed save from a BODY OF THE DELIVERED SET
|
|
128
|
+
* THAT THREW, which is NOT caught, not retried and not reported (`§2.7` item 4). **IT IS A SYMBOL KEY ON
|
|
129
|
+
* PURPOSE** (`A117` (D6)): `CommitRecord` keeps its four members and no census moves.
|
|
130
|
+
*/
|
|
131
|
+
const SAVE_FAILED_AT_THE_TERMINAL_ARM = Symbol.for('provident-storeroom.save-failed-at-the-terminal-arm');
|
|
132
|
+
|
|
133
|
+
/** `fail-surface.md §1.1` — ONE THROWN PLAIN OBJECT, EXACTLY THREE MEMBERS, NEVER AN `Error`. */
|
|
134
|
+
function refuse(status, message, log) {
|
|
135
|
+
throw { status, message, log: log === undefined ? [] : log };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ---------------------------------------------------------------------------------------------
|
|
139
|
+
// `PAR-C-1` — THE REGISTRATION KEY'S `address`: the store's own domain, unchanged and not
|
|
140
|
+
// re-declared here.
|
|
141
|
+
// ---------------------------------------------------------------------------------------------
|
|
142
|
+
function inDomainAddress(address) {
|
|
143
|
+
if (!Array.isArray(address)) return false;
|
|
144
|
+
for (const segment of address) {
|
|
145
|
+
if (typeof segment === 'string') continue;
|
|
146
|
+
if (typeof segment === 'number' && Number.isInteger(segment) && segment >= 0) continue;
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** `PAR-C-2` — the registration key's `id`: a non-empty `string` and nothing else. */
|
|
153
|
+
function inDomainId(id) {
|
|
154
|
+
return typeof id === 'string' && id.length > 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* `attempt-lifecycle.md §2.4` item 2 — THE ADDRESS HALF OF THE PAIR KEY, AND THE REGISTRY'S OWN KEY FOR
|
|
159
|
+
* ONE ADDRESS — WITH EACH SEGMENT'S OWN CLASS MARKER, WHICH IS THIS SPELLING'S WHOLE POINT: an INDEX
|
|
160
|
+
* (`i`) bears THE SEGMENT'S OWN SIGNLESS DECIMAL DIGITS immediately, a KEY (`k`) bears THE SEGMENT'S OWN
|
|
161
|
+
* CHARACTER COUNT, and each is then followed by `:`, by the segment VERBATIM and by `;`; the segments so
|
|
162
|
+
* spelled are joined with `/`. THE MARKER IS WHAT KEEPS THE TWO DECLARED SEGMENT CLASSES APART — the
|
|
163
|
+
* withdrawn UNMARKED spelling spelled an index `3` and the key `'3'` IDENTICALLY, so its "injective"
|
|
164
|
+
* claim was false over a domain closed at exactly two classes — and the `;` is a delimiter the field's
|
|
165
|
+
* own grammar cannot carry, so a `;`, a `:`, a `/`, a `#`, a NUL or the empty segment `0:` INSIDE a
|
|
166
|
+
* segment is that segment's own character and never a separator: `['a/b'],'c'` spells `k:3;a/b` against
|
|
167
|
+
* `['a','b'],'c'`'s `k:1;a/k:1;b`, `['v',3]`'s second segment spells `i:3;` and not a character count,
|
|
168
|
+
* `['a\0b']` and `['a','b']` are two addresses, and the empty address spells the empty string. NO
|
|
169
|
+
* READER MAY STRIP THE MARKER, and no clause of this module re-spells a key anywhere else.
|
|
170
|
+
*/
|
|
171
|
+
function addressToken(address) {
|
|
172
|
+
let token = '';
|
|
173
|
+
for (let i = 0; i < address.length; i += 1) {
|
|
174
|
+
if (i > 0) token += '/';
|
|
175
|
+
const segment = address[i];
|
|
176
|
+
if (typeof segment === 'number') token += `i:${segment};`;
|
|
177
|
+
else {
|
|
178
|
+
const text = String(segment);
|
|
179
|
+
token += `k:${text.length}:${text};`;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return token;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* `attempt-lifecycle.md §2.4` item 2 — THE PAIR TOKEN: THE ADDRESS HALF ABOVE, then ONE `#`, then the
|
|
187
|
+
* bare `id`. `(['a','b'],'x')` spells `k:1;a/k:1;b#x`, `(['a'],'b#x')` spells `k:1;a#b#x`, `(['a/b'],'c')`
|
|
188
|
+
* spells `k:3;a/b#c`, `(['v',3],'x')` spells `k:1;v/i:3;#x` and `([],'x')` spells `#x` — the `#` the
|
|
189
|
+
* address half cannot carry being the one separator between the two halves.
|
|
190
|
+
*/
|
|
191
|
+
function pairKey(address, id) {
|
|
192
|
+
return `${addressToken(address)}#${id}`;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// ---------------------------------------------------------------------------------------------
|
|
196
|
+
// THE KERNEL'S OWN CALLER-SIDE STATE. ONE `WeakMap` KEYED BY THE INSTANCE THE CALLER PASSED, so
|
|
197
|
+
// two stores never share a registry and this module retains no store of its own.
|
|
198
|
+
// ---------------------------------------------------------------------------------------------
|
|
199
|
+
const KERNELS = new WeakMap();
|
|
200
|
+
|
|
201
|
+
// THE ATTEMPT RECORDS ARE THE KERNEL'S OWN CALLER-SIDE SHAPE AND ARE KEYED BY THE `AttemptRef`, NOT BY
|
|
202
|
+
// THE INSTANCE: a reader answers "from the record and not from the store instance"
|
|
203
|
+
// (`ck_surface_K4_the_readers_answer_from_the_record_and_not_from_the_store_instance`; `§2.1` item 4).
|
|
204
|
+
const LIVE = new Map();
|
|
205
|
+
const CLOSED = new Map();
|
|
206
|
+
let ATTEMPTS = 0;
|
|
207
|
+
|
|
208
|
+
function kernelFor(store) {
|
|
209
|
+
let kernel = KERNELS.get(store);
|
|
210
|
+
if (kernel === undefined) {
|
|
211
|
+
kernel = {
|
|
212
|
+
// The registration registry, keyed by the pair token, in first-registration order per
|
|
213
|
+
// address (`kernel-surface.md §2.1` item 1, `CC-7`).
|
|
214
|
+
pairs: new Map(),
|
|
215
|
+
byAddress: new Map(),
|
|
216
|
+
// address token -> the store's own adopted home handle for that address.
|
|
217
|
+
homes: new Map(),
|
|
218
|
+
// pair token -> THE STORE'S OWN ADOPTED HANDLE the pair's registration answered. The kernel
|
|
219
|
+
// "mints no token for a store-minted handle" (`§2.2` item 1) and "THE ONE THING THE KERNEL DOES
|
|
220
|
+
// WITH THE HANDLE IS RECORD IT" (`§2.2` item 3) — so the handle the delivery is keyed by is
|
|
221
|
+
// recorded here and nowhere else.
|
|
222
|
+
handles: new Map(),
|
|
223
|
+
// address token -> the AttemptRef.id holding it.
|
|
224
|
+
held: new Map(),
|
|
225
|
+
};
|
|
226
|
+
KERNELS.set(store, kernel);
|
|
227
|
+
}
|
|
228
|
+
return kernel;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ---------------------------------------------------------------------------------------------
|
|
232
|
+
// THE MESSAGE LOG (`kernel-surface.md §2.5` item 1; `PAR-C-4`). SIX MEMBERS, `seq` ASCENDING FROM
|
|
233
|
+
// `1`, ONE KIND PER ENTRY: `constraint-check` | `repair-run` | `commit` | `outcome`.
|
|
234
|
+
// ---------------------------------------------------------------------------------------------
|
|
235
|
+
function append(attempt, kind, id, opId, message, state) {
|
|
236
|
+
attempt.log.push({
|
|
237
|
+
seq: attempt.log.length + 1,
|
|
238
|
+
kind,
|
|
239
|
+
id: id === undefined ? null : id,
|
|
240
|
+
opId: opId === undefined ? null : opId,
|
|
241
|
+
message,
|
|
242
|
+
state: state === undefined ? null : state,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** A withdrawn entry takes its `seq` with it: the log's ordinals stay `1..n` (`§2.5` item 1). */
|
|
247
|
+
function withdraw(attempt, entry) {
|
|
248
|
+
const at = attempt.log.indexOf(entry);
|
|
249
|
+
if (at === -1) return;
|
|
250
|
+
attempt.log.splice(at, 1);
|
|
251
|
+
for (let i = 0; i < attempt.log.length; i += 1) attempt.log[i].seq = i + 1;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ---------------------------------------------------------------------------------------------
|
|
255
|
+
// THE REPAIR'S OWN OP (`PAR-C-7`; `parameter-semantics.md §2.7`'s `observable` cell — the seam's ONE
|
|
256
|
+
// home; `A: docs/decisions.md` · `A110`).
|
|
257
|
+
//
|
|
258
|
+
// THE REPAIR'S OWN RETURN CARRIES IT, AND THAT RETURN IS ITS ONE CARRIER: *"THE KERNEL READS THE OP
|
|
259
|
+
// THE REPAIR LANDED OFF THE REPAIR'S OWN RETURN AND NOWHERE ELSE — the op it APPENDS to the
|
|
260
|
+
// attempt's `ops` IS `returnValue.op`."* THE ROUTE `A110` DELETES IS **DELETED AND NOT WIDENED**: no
|
|
261
|
+
// `createRequire`, no addon load path, no addon-verb interception window, no monkey-patch and no
|
|
262
|
+
// second dependency stands in this module, so the import footprint above is the whole of what the
|
|
263
|
+
// kernel loads and the caller's own instance is the only way it ever reaches the store.
|
|
264
|
+
//
|
|
265
|
+
// AND `returnValue.op`'s ONE DECLARED VALUE IS THE STORE'S OWN OP VALUE, THE ONE ITS OWN `write`
|
|
266
|
+
// ANSWERED WITH — *"so a return carrying any other identity has carried no op at all."* A repair's
|
|
267
|
+
// edit that lands mints a FRESH op: the journal is append-only and `AttemptRecord.ops` holds the ops
|
|
268
|
+
// THIS attempt created, so an identity the attempt ALREADY HOLDS is provably not this repair's own
|
|
269
|
+
// landing. The member is therefore decided CALLER-SIDE, off the return and off the attempt's own
|
|
270
|
+
// record and off nothing else, and every value outside it is THE APP'S OWN DEFECT — *"the kernel
|
|
271
|
+
// credits NO op, the attempt takes arm `(d)` and fails `KC-4`, its `repair-run` entry is appended,
|
|
272
|
+
// and the kernel's own generated sentence names the unrecognized or unlanded `op`."*
|
|
273
|
+
// ---------------------------------------------------------------------------------------------
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* THE OP THE REPAIR'S OWN RETURN CARRIES, OR `null` WHERE IT CARRIES NONE.
|
|
277
|
+
*
|
|
278
|
+
* `null` answers BOTH halves of `§2.7`'s clause at once: an `ok === true` return whose `op` is
|
|
279
|
+
* ABSENT or `undefined`, and one whose `op` is NOT the op the repair actually landed — a value that
|
|
280
|
+
* is no op at all (an op is an object carrying a non-empty string `opId`), an op this attempt
|
|
281
|
+
* ALREADY HOLDS, or an op that PROVABLY LANDED BEFORE THIS REPAIR'S OWN EDIT. Each is read as a
|
|
282
|
+
* repair that produced NO OP (`parameter-semantics.md §2.7` — *"a return carrying any other identity
|
|
283
|
+
* has carried no op at all"*; `attempt-lifecycle.md §2.4` item 4's arm `(d)`).
|
|
284
|
+
*
|
|
285
|
+
* `invokedFor` IS THE OP THIS EVALUATION CARRIED — the op the repair was invoked for — and it is
|
|
286
|
+
* the second ground's whole term: the repair's own edit lands INSIDE this invocation, and the
|
|
287
|
+
* store's own `seq` is "the entry's append ordinal, strictly increasing from 1"
|
|
288
|
+
* (`A: docs/specs/storeroom-native/write-and-read.md §6.2`), so an op whose own ordinal does not
|
|
289
|
+
* stand ABOVE the ordinal of the op this repair was invoked for CANNOT be an op this repair
|
|
290
|
+
* landed — it landed at or before it. The member is read CALLER-SIDE, off the return's own value and
|
|
291
|
+
* off the attempt's own record and off nothing else: the kernel reaches no journal and loads no
|
|
292
|
+
* second route. Where either ordinal is not a number the ground is not applied, and the membership
|
|
293
|
+
* ground above stands alone.
|
|
294
|
+
*/
|
|
295
|
+
function landedOp(attempt, returned, invokedFor) {
|
|
296
|
+
if (!('op' in returned)) return null;
|
|
297
|
+
const candidate = returned.op;
|
|
298
|
+
if (candidate === null || typeof candidate !== 'object') return null;
|
|
299
|
+
if (typeof candidate.opId !== 'string' || candidate.opId.length === 0) return null;
|
|
300
|
+
for (const held of attempt.ops) {
|
|
301
|
+
if (held !== null && typeof held === 'object' && held.opId === candidate.opId) return null;
|
|
302
|
+
}
|
|
303
|
+
const floor = invokedFor !== null && invokedFor !== undefined && typeof invokedFor.seq === 'number'
|
|
304
|
+
? invokedFor.seq
|
|
305
|
+
: null;
|
|
306
|
+
if (floor !== null && typeof candidate.seq === 'number' && candidate.seq <= floor) return null;
|
|
307
|
+
return candidate;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* THE KERNEL'S OWN GENERATED SENTENCE FOR THAT ARM: *"the kernel's own generated sentence names the
|
|
312
|
+
* unrecognized or unlanded `op`"* (`§2.7`'s home, verbatim). It names the identity the malformed
|
|
313
|
+
* return carried — the `opId` where the member carried one, the member's own value where it did not
|
|
314
|
+
* — and never the attempt's address alone.
|
|
315
|
+
*/
|
|
316
|
+
function landedOpDefect(attempt, pair, returned) {
|
|
317
|
+
const where = JSON.stringify(attempt.address);
|
|
318
|
+
if (!('op' in returned) || returned.op === undefined) {
|
|
319
|
+
return `the repair ${pair.id} returned \`ok: true\` and carried no op at ${where}`;
|
|
320
|
+
}
|
|
321
|
+
return `the repair ${pair.id} returned \`ok: true\` and named the unrecognized or unlanded op `
|
|
322
|
+
+ `${opSpelling(returned.op)} at ${where}`;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** One returned `op` member's identity, spelled for the kernel's own sentence: an `opId` where the
|
|
326
|
+
* member carried one, and the member's own class where it carried no op at all. */
|
|
327
|
+
function opSpelling(value) {
|
|
328
|
+
if (value !== null && typeof value === 'object' && typeof value.opId === 'string') {
|
|
329
|
+
return JSON.stringify(value.opId);
|
|
330
|
+
}
|
|
331
|
+
if (typeof value === 'string') return JSON.stringify(value);
|
|
332
|
+
if (value === null) return 'null';
|
|
333
|
+
return `a ${typeof value} (which is no op)`;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ---------------------------------------------------------------------------------------------
|
|
337
|
+
// `K-1` `register(store, address, id, constraint) -> Handle`
|
|
338
|
+
// ---------------------------------------------------------------------------------------------
|
|
339
|
+
export function register(store, address, id, constraint) {
|
|
340
|
+
const kernel = kernelFor(store);
|
|
341
|
+
|
|
342
|
+
// CHANNEL (i) — THE KERNEL'S OWN, REFUSED BEFORE THE STORE'S `listen` IS CALLED.
|
|
343
|
+
if (!inDomainAddress(address)) {
|
|
344
|
+
refuse(KC.address,
|
|
345
|
+
'the registration address is outside the store\'s own address domain: an address is an array of '
|
|
346
|
+
+ 'string keys or non-negative integer indices, the empty array included',
|
|
347
|
+
[]);
|
|
348
|
+
}
|
|
349
|
+
if (!inDomainId(id) || typeof constraint !== 'function') {
|
|
350
|
+
refuse(KC.arg,
|
|
351
|
+
'a registration\'s key is an address and a NON-EMPTY STRING id, and its third argument is a '
|
|
352
|
+
+ 'function',
|
|
353
|
+
[]);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// CHANNEL (ii) — THE STORE'S OWN. An in-domain address the store's own listener machinery refuses
|
|
357
|
+
// throws THE STORE'S OWN CODE, in the store's own form, at this call and unconverted.
|
|
358
|
+
//
|
|
359
|
+
// **⟶ AND THE ACT IS THE PRODUCT'S TWO DECLARED HALVES, FROM 2026-10-16 ON `A127`** (`surface.md §2.4`
|
|
360
|
+
// item 9 (f)'s `A127` clause): the combined `on(address, listener)` is MERGED AWAY, so the home entry is
|
|
361
|
+
// minted by `listen` and its function placed by `register` — ONE act, the two members the product
|
|
362
|
+
// declares, and no second spelling of either. `listen` keeps the address-level idempotence the removed
|
|
363
|
+
// route read (`write-and-read.md §6.5` item 12 (c)): a repeat at an address the home already holds mints
|
|
364
|
+
// nothing and answers the entry's own handle.
|
|
365
|
+
const home = store.listen(address);
|
|
366
|
+
store.register(home, noopListener);
|
|
367
|
+
|
|
368
|
+
const key = pairKey(address, id);
|
|
369
|
+
const standing = kernel.pairs.get(key);
|
|
370
|
+
// THE PAIR'S OWN IDEMPOTENCE: a second registration under the SAME pair key keeps the replaced
|
|
371
|
+
// registration's POSITION and replaces only its function (`§2.1` item 1; `CC-7`).
|
|
372
|
+
if (standing === undefined) {
|
|
373
|
+
kernel.pairs.set(key, { address, id, constraint });
|
|
374
|
+
kernel.handles.set(key, home);
|
|
375
|
+
const token = addressToken(address);
|
|
376
|
+
const list = kernel.byAddress.get(token);
|
|
377
|
+
if (list === undefined) kernel.byAddress.set(token, [key]);
|
|
378
|
+
else list.push(key);
|
|
379
|
+
if (!kernel.homes.has(token)) kernel.homes.set(token, home);
|
|
380
|
+
} else {
|
|
381
|
+
standing.constraint = constraint;
|
|
382
|
+
}
|
|
383
|
+
return home;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** The store holds ONE registration per address, and its `listen` takes a function. */
|
|
387
|
+
function noopListener() {}
|
|
388
|
+
|
|
389
|
+
// ---------------------------------------------------------------------------------------------
|
|
390
|
+
// `K-2` `commit(store, address, tier, value) -> CommitRecord`
|
|
391
|
+
// ---------------------------------------------------------------------------------------------
|
|
392
|
+
export function commit(store, address, tier, value) {
|
|
393
|
+
const kernel = kernelFor(store);
|
|
394
|
+
const token = inDomainAddress(address) ? addressToken(address) : null;
|
|
395
|
+
|
|
396
|
+
// THE ADDRESS THE ATTEMPT HOLDS REFUSES A SECOND ATTEMPT BEFORE THE WRITE VERB IS REACHED, and
|
|
397
|
+
// the refused call opens no attempt and leaves no entry (`KC-7`; `kernel-surface.md §2.1` item 2).
|
|
398
|
+
if (token !== null && kernel.held.has(token)) {
|
|
399
|
+
refuse(KC.attemptOpen,
|
|
400
|
+
`a constraint attempt is already open at ${JSON.stringify(address)}; it is disposed of by its own `
|
|
401
|
+
+ 'K-3 and by no other act',
|
|
402
|
+
[]);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// THE HOLD IS TAKEN AT `K-2`'S OWN ACT AND BEFORE THE STORE'S WRITE VERB IS REACHED
|
|
406
|
+
// (`attempt-lifecycle.md §2.4` item 8 (ii) (g) term (1); `A: docs/decisions.md` · `A112`): the store
|
|
407
|
+
// invokes nothing, so the only invocation window that can stand inside `K-2` is the SURFACE's, and a
|
|
408
|
+
// listener body's own nested `K-2` while `K-2` stands is inside `K-2`'s own window — so the address
|
|
409
|
+
// this call commits at is HELD from this instant, its token already in hand. The set below is what the
|
|
410
|
+
// head's `kernel.held.has(token)` refusal reads, and the map's values are only ever `has`ed and
|
|
411
|
+
// `delete`d (`release`). `KC-7`'s `K-2` half is refused ONLY at the address that already holds the
|
|
412
|
+
// live attempt: a nested `K-2` at a DESCENDANT address meets no hold of its own and is ADMITTED.
|
|
413
|
+
if (token !== null) kernel.held.set(token, token);
|
|
414
|
+
|
|
415
|
+
// THE STORE'S OWN VERB CHOOSES WHICH REFUSAL ANSWERS. An out-of-domain `tier` and an absent
|
|
416
|
+
// `value` are THE STORE'S own code on THE STORE'S own channel, and the kernel mints no `KC-2` for
|
|
417
|
+
// either (`kernel-surface.md §2.1` item 2; `parameter-semantics.md §2.14`). WHERE THE VERB REFUSES, NO
|
|
418
|
+
// ATTEMPT WAS OPENED, SO THE ADDRESS IS LEFT UNHELD: the hold taken above is released and the store's
|
|
419
|
+
// own throwable reaches the caller UNCHANGED AND UNCONVERTED (`fail-surface.md §1.2` item 2) — a
|
|
420
|
+
// refused write leaves no hold behind (`ck_surface_K2_an_out_of_domain_tier_is_the_store_s_own_code_on_the_store_s_own_channel`).
|
|
421
|
+
ATTEMPTS += 1;
|
|
422
|
+
const attempt = {
|
|
423
|
+
ref: { id: `attempt-${ATTEMPTS}` },
|
|
424
|
+
store,
|
|
425
|
+
address: address.slice(),
|
|
426
|
+
tier,
|
|
427
|
+
value,
|
|
428
|
+
commit,
|
|
429
|
+
// THE WRITE'S OWN RETURNED SET, HELD ON THE ATTEMPT ITSELF: the failing arm's discard reads it and
|
|
430
|
+
// never a derivation from the attempt's address (`attempt-lifecycle.md §3` item 8: the failing arm
|
|
431
|
+
// reads `triggered` as the store's returned set VERBATIM).
|
|
432
|
+
write: null,
|
|
433
|
+
ops: [],
|
|
434
|
+
log: [],
|
|
435
|
+
ran: [],
|
|
436
|
+
appliedRepairs: [],
|
|
437
|
+
rollback: [],
|
|
438
|
+
checkpoint: null,
|
|
439
|
+
// `A117` (D5): THE IDENTITIES THIS ATTEMPT'S PASSES CHECKED OFF, in the order the check-offs were
|
|
440
|
+
// taken — the finding the passing arm publishes onto the record (`publishCheckedOff`) so that the
|
|
441
|
+
// terminal arm resolves each the way the residue is resolved and delivers the firing a registration
|
|
442
|
+
// at that identity's address still owes (`CHECKED_OFF` above). It is the ATTEMPT'S OWN and never the
|
|
443
|
+
// record's: no `CommitRecord` member is added (`A117` (D6)).
|
|
444
|
+
checkedOff: [],
|
|
445
|
+
status: 'open',
|
|
446
|
+
report: null,
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// **⟶ ADDED 2026-10-15 — THE `A116` ORDERING-SEAM PASS: INSTANT (a), TAKEN HERE SO IT STANDS BEFORE THE
|
|
450
|
+
// STORE'S WRITE VERB IS CALLED.** `docs/decisions.md` · `A116` (D1)/(D2) declares the seam — a member
|
|
451
|
+
// of the object `storeCreate` returned, which THE KERNEL CALLS and THE ENTRY IMPLEMENTS — and
|
|
452
|
+
// `surface.md §2.4` item 9's table fixes this instant: *"BEFORE THE STORE'S WRITE VERB IS CALLED …
|
|
453
|
+
// inside `commit`, for a write the kernel has issued, before the store's own `write` verb is reached"*.
|
|
454
|
+
// The identity the seam receives IS THE RECORD IDENTITY `commit` returns — the same object, not a copy
|
|
455
|
+
// of it (`PAR-JS-19`'s argument cell) — so the record the seam adopts below is built FIRST, and this
|
|
456
|
+
// call is the adoption that makes the write in flight one whose in-window delivery is WITHHELD.
|
|
457
|
+
//
|
|
458
|
+
// THE MEMBER IS REACHED THE ONE WAY THIS SURFACE REACHES THE INSTANCE'S OWN MEMBERS, WITH NO ADDON CALL
|
|
459
|
+
// AND NO STORE VERB: the caller's own instance object carries it. **AND A `write` VERB THE INSTANCE DID
|
|
460
|
+
// NOT ADOPT A RECORD FOR — a bare caller-made write made through this same `store` — reaches no such
|
|
461
|
+
// member and is answered by the package's own post-verb instant, `§2.7` item 8's, unmoved** (`§2.4`
|
|
462
|
+
// item 9 (e): *"a caller's addressable sub-surface on that handle is the three members `§2.4` item 5 and
|
|
463
|
+
// item 7 declare"* — this arm is the kernel's own and never a caller's).
|
|
464
|
+
const record = {
|
|
465
|
+
attempt: attempt.ref,
|
|
466
|
+
op: null,
|
|
467
|
+
triggered: [],
|
|
468
|
+
// `kernel-surface.md §2.1` item 2 — THE FOURTH MEMBER, AS `A: docs/decisions.md` · `A112` RE-SPELLS
|
|
469
|
+
// IT: "`pending` IS THE WHOLE RETURNED SET ... THE KERNEL WRITES THE ENTIRE RETURNED SET OF
|
|
470
|
+
// TRIGGERED CONSTRAINTS AS `pending` AND CHECKS EACH OFF AS IT PASSES", and sifting a subset out of
|
|
471
|
+
// the returned set is UNNECESSARY AND UNLAWFUL. `K-2` is the caller's own verb call and the kernel
|
|
472
|
+
// invokes no pair in its window here, so EVERY handle this write returned stands in the member at
|
|
473
|
+
// this instant; a handle whose pair a LATER pass evaluates leaves it only by being checked off as it
|
|
474
|
+
// passes (`releasePending`), and where the write failed the registered constraints at its landing
|
|
475
|
+
// "its set is DISCARDED rather than carried, so its handles appear in `triggered` and in `pending`
|
|
476
|
+
// NEVER" (`attempt-lifecycle.md §2.4` item 8 (i) (5), the discard rule's one home).
|
|
477
|
+
pending: [],
|
|
478
|
+
};
|
|
479
|
+
attempt.record = record;
|
|
480
|
+
if (typeof store.settle === 'function') store.settle(record);
|
|
481
|
+
|
|
482
|
+
let written;
|
|
483
|
+
try {
|
|
484
|
+
// **THE FIFTH POSITION** (`kernel-surface.md §1` item 5's dated spelling; `surface.md §2.12` item 1
|
|
485
|
+
// stage 2): the kernel drives the Rust store with the record identity `K-2` opened or joined, so the
|
|
486
|
+
// kernel's own store leg IS the entry's own write and its delivery is withheld for the terminal arm.
|
|
487
|
+
written = store.write(address, tier, value, record);
|
|
488
|
+
} catch (refusal) {
|
|
489
|
+
if (token !== null) kernel.held.delete(token);
|
|
490
|
+
throw refusal;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
attempt.write = written;
|
|
494
|
+
attempt.ops = [written.op];
|
|
495
|
+
LIVE.set(attempt.ref.id, attempt);
|
|
496
|
+
|
|
497
|
+
// **THE MEMBERS THE WRITE'S OWN RETURN CARRIES, READ OFF IT VERBATIM** (`A112`; `§2.2` item 2): the
|
|
498
|
+
// record above was built with the four members the seam's own adoption is keyed by — the identity alone
|
|
499
|
+
// is what adoption reads — and the write's returned set is then written into `triggered` and into
|
|
500
|
+
// `pending` AS ONE LIST, member for member and by the SAME handle identities, which is the state `K-2`
|
|
501
|
+
// answers its caller with.
|
|
502
|
+
record.op = written.op;
|
|
503
|
+
record.triggered = written.triggered;
|
|
504
|
+
record.pending = written.triggered.slice();
|
|
505
|
+
|
|
506
|
+
// ── THE ORIGINAL BODY OF THIS ITEM, KEPT BESIDE THE INSERTION ABOVE ────────────────────────────────
|
|
507
|
+
//
|
|
508
|
+
// ATTEMPTS += 1;
|
|
509
|
+
// const attempt = { … write: written, ops: [written.op], … };
|
|
510
|
+
// const record = { attempt: attempt.ref, op: written.op, triggered: written.triggered,
|
|
511
|
+
// pending: written.triggered.slice() };
|
|
512
|
+
// attempt.record = record;
|
|
513
|
+
// LIVE.set(attempt.ref.id, attempt);
|
|
514
|
+
//
|
|
515
|
+
// THE MOVE IS THE SEAM'S OWN CONSEQUENCE AND MOVES NO RULE: the attempt's five members, the record's
|
|
516
|
+
// four members and the instant the record is placed in `LIVE` all stand as they stood, and the ONE
|
|
517
|
+
// difference is that the record stands before the write verb is reached, which is the instant `A116`
|
|
518
|
+
// (D1) fixes.
|
|
519
|
+
|
|
520
|
+
// THE SET THE WRITE RETURNED IS CARRIED WHOLE (`A112`): the handle the kernel's own adopted home entry
|
|
521
|
+
// stands for is NOT subtracted here — that subtraction is the sift `A112` withdraws by name. It leaves
|
|
522
|
+
// the member when its own pair's pass checks it off (`releasePending`), and the rolled-back arm's
|
|
523
|
+
// discard is the throw path's own rule (`terminal`/`close`).
|
|
524
|
+
return record;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// ---------------------------------------------------------------------------------------------
|
|
528
|
+
// `K-3` `runAttempt(store, commit) -> AttemptReport`
|
|
529
|
+
// ---------------------------------------------------------------------------------------------
|
|
530
|
+
export function runAttempt(store, commitRecord) {
|
|
531
|
+
const kernel = kernelFor(store);
|
|
532
|
+
const id = commitAttemptIdOf(commitRecord);
|
|
533
|
+
const attempt = LIVE.get(id);
|
|
534
|
+
if (attempt === undefined) {
|
|
535
|
+
// A CLOSED or UNKNOWN attempt is KC-2 — and NEVER KC-7, whose `K-3` site is the RE-ENTRANT call
|
|
536
|
+
// for a LIVE attempt (`fail-surface.md §2`'s KC-2 row; `kernel-surface.md §2.3` item 3).
|
|
537
|
+
refuse(KC.arg, `no open constraint attempt answers to ${id}`, []);
|
|
538
|
+
}
|
|
539
|
+
// `kernel-surface.md §2.1` item 3's `RD-9` CLAUSE, READ WITH `attempt-lifecycle.md §2.4` item 1: the
|
|
540
|
+
// `AttemptRef` is MINTED BY THE KERNEL INSTANCE (its `id` "unique within the kernel instance"), so a
|
|
541
|
+
// `CommitRecord` whose attempt was opened by ANOTHER instance names an attempt THE KERNEL INSTANCE
|
|
542
|
+
// HANDED THE RECORD HOLDS NONE FOR. That call is THIS refusal — `KC-2`, NO STATE MOVED AND NO ENTRY
|
|
543
|
+
// APPENDED — and NEVER a run of another instance's attempt: the attempt's own `store` is the instance
|
|
544
|
+
// its `K-2` reached, and what is refused here is refused BEFORE `status` moves, so the caller's own
|
|
545
|
+
// attempt stands OPEN, its pair unevaluated, and its address held by ITS OWN run alone (item 4's
|
|
546
|
+
// unconstrained-argument clause is declared for `K-4`/`K-5` and is not widened to `K-3`).
|
|
547
|
+
if (attempt.store !== store) {
|
|
548
|
+
refuse(KC.arg,
|
|
549
|
+
`no open constraint attempt answers to ${id}: it was opened through another store instance`,
|
|
550
|
+
[]);
|
|
551
|
+
}
|
|
552
|
+
if (attempt.status === 'running') {
|
|
553
|
+
// THE RE-ENTRANT `K-3`, refused by the SAME `KC-7` member a live address answers with.
|
|
554
|
+
refuse(KC.attemptOpen,
|
|
555
|
+
`the constraint attempt at ${JSON.stringify(attempt.address)} is already running`, []);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
attempt.status = 'running';
|
|
559
|
+
const terminalArm = runToCompletion(kernel, attempt);
|
|
560
|
+
if (terminalArm !== null) {
|
|
561
|
+
// A FAILING LANDING: the arm's own terminal act, its per-op rollback composition, and the throw
|
|
562
|
+
// of `fail-surface.md §1.1`'s form carrying the log.
|
|
563
|
+
terminal(kernel, attempt, terminalArm.status, terminalArm.message);
|
|
564
|
+
// **⟶ INSTANT (b) ON THE FAILING ARM, AND IT PRECEDES THE REFUSAL** (`docs/decisions.md` · `A116`
|
|
565
|
+
// (D1); `surface.md §2.4` item 9's table row (b): *"AT THE PASS'S TERMINAL ARM … after the last
|
|
566
|
+
// constraint of the attempt has been evaluated and before `runAttempt` returns to the calling
|
|
567
|
+
// process"*). The attempt is already CLOSED and the DISCARD has already emptied the member
|
|
568
|
+
// (`attempt-lifecycle.md §2.4` item 8 (i) (5); `terminal` above), so the residue this seam reads
|
|
569
|
+
// stands EMPTY and the arm delivers ZERO — *"on a write that fails on constraints THE OTHER LISTENERS
|
|
570
|
+
// ARE DISCARDED"* (`§2.7` item 6, read at item 7 (d)) — while the delivery itself is still owed at
|
|
571
|
+
// this instant and is taken HERE rather than skipped, because the residue and not the arm decides
|
|
572
|
+
// what it reaches (`§2.7` item 7 (c): *"the empty delivery is a NO-OP AND NOT A FAILURE"*).
|
|
573
|
+
settleArm(store, attempt);
|
|
574
|
+
// THE ARM IS READ OFF THE CLOSED ATTEMPT WHERE THE COMPOSITION'S OWN FLOOR OVERRODE IT: a still-owed
|
|
575
|
+
// op's call meeting `RollbackCompacted`/`JournalOpUnknown` is `KC-8` and not the pass's own arm
|
|
576
|
+
// (`composition-and-states.md §2.6` item 5 (b); `KC-8`'s own row).
|
|
577
|
+
refuse(attempt.throwState, attempt.throwMessage, attempt.log);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// THE SUCCESS ARM: the registry entry removed and the five-member report — **AND THE `commit` ENTRY IS
|
|
581
|
+
// NOT APPENDED HERE** (`DEF-2026-10-16-B`; `kernel-surface.md §2.1` item 3's `LogKind` table: `commit`
|
|
582
|
+
// = "the attempt's SUCCESS arm, appended once"; `composition-and-states.md §2.7` items 5 and 7 put it on
|
|
583
|
+
// the PASSED arm's own sequence). The save is A CONSTRAINT EVALUATED LAST (`surface.md §2.11` clause 5),
|
|
584
|
+
// so an arm that appends this entry BEFORE the save's own instant appends it on an arm whose save may
|
|
585
|
+
// not stand — and the entry's own declared text then LIES beside the `outcome` entry the failure arm
|
|
586
|
+
// appends (`§2.1` item 4 (ii)). **THE APPEND THEREFORE FOLLOWS THE SAVE'S OWN SUCCESS**, below: it stands
|
|
587
|
+
// on the passing arm alone, appended once, and it closes that arm's log.
|
|
588
|
+
const closed = close(kernel, attempt, 'passed');
|
|
589
|
+
// **⟶ INSTANT (b) ON THE PASSING ARM — THE ORDERING LAW'S WHOLE POINT** (`docs/decisions.md` · `A116`
|
|
590
|
+
// (D1); `surface.md §2.7` item 6): *"for a write, the surface runs the write's TRIGGERED CONSTRAINTS
|
|
591
|
+
// FIRST, and THE OTHER LISTENERS ARE REACHED ONLY ONCE EVERY CONSTRAINT HAS PASSED"*. Every constraint
|
|
592
|
+
// of this attempt has now been evaluated — the pass reached its terminal arm — and the delivery follows
|
|
593
|
+
// it, at THIS instant, before this item returns to the calling process. The attempt is closed FIRST so
|
|
594
|
+
// that a listener body's own kernel act meets a disposed attempt rather than a live one.
|
|
595
|
+
//
|
|
596
|
+
// AND THE PASS'S OWN CHECK-OFFS ARE PUBLISHED HERE, BEFORE THE SEAM IS REACHED (`A117` (D5)): the
|
|
597
|
+
// identities this attempt's pass evaluated and checked off are what the terminal arm resolves beside
|
|
598
|
+
// the residue, so that a registration standing at one of those identities' addresses — the firing the
|
|
599
|
+
// check-off did NOT consume — is delivered ONCE at this instant (`§2.7` item 6). It is placed on the
|
|
600
|
+
// PASSING arm ALONE: the failing arm above delivered nothing and published nothing.
|
|
601
|
+
publishCheckedOff(attempt);
|
|
602
|
+
// **⟶ AND THE PASSING ARM'S OWN MARK IS TAKEN WITH THEM** (`SETTLED_ON_THE_PASSING_ARM` above;
|
|
603
|
+
// `surface.md §2.11` clause 2): the seam's terminal arm performs the store's `file`-tier commit on THIS
|
|
604
|
+
// arm alone — *"the `file` tier, the TERMINAL ARM and the PASSING ARM alone"* (clause 1) — and the
|
|
605
|
+
// failing arm above reaches the same `settle` call with the same record in hand and owes no save.
|
|
606
|
+
if (attempt.record !== undefined) {
|
|
607
|
+
attempt.record[SETTLED_ON_THE_PASSING_ARM] = true;
|
|
608
|
+
}
|
|
609
|
+
// **⟶ AND THE SAVE IS A CONSTRAINT EVALUATED LAST, SO THE PASS THAT FAILED REPORTS IT** (`surface.md
|
|
610
|
+
// §2.11` clause 5; `kernel-surface.md §2.1` items 3–5; `fail-surface.md §1.1` items 1 and 3;
|
|
611
|
+
// `composition-and-states.md §2.6` item 3). **THIS IS THE ONE ARM ON WHICH THE PASSING ARM'S OWN FIRST
|
|
612
|
+
// ACT FAILS**, and the clause reads it exactly as it reads every other failing landing: *"a save that
|
|
613
|
+
// fails IS A CONSTRAINT VIOLATION"*, `ok === false`, the log gains the ONE `outcome` entry, and the
|
|
614
|
+
// report is the run's answer and never the passing arm's.
|
|
615
|
+
//
|
|
616
|
+
// **THE ARM IS READ OFF THE IDENTITY THE SEAM MARKS AND OFF NOTHING ELSE** (`SAVE_FAILED_AT_THE_TERMINAL_
|
|
617
|
+
// ARM` above): a BODY OF THE DELIVERED SET that throws is NOT this arm — `§2.7` item 4 leaves it NOT
|
|
618
|
+
// caught, not retried and not reported — so it is rethrown with the attempt standing just as it stood.
|
|
619
|
+
//
|
|
620
|
+
// **THE TERMINAL ACT IS THIS MODULE'S ONE TERMINAL ACT, TAKEN VERBATIM** (`terminal` below): the per-op
|
|
621
|
+
// rollback composition FIRST — ROLLBACK FIRST, MESSAGE SECOND — then the attempt's ONE `outcome` entry,
|
|
622
|
+
// whose `state` is the token the composition's own floor decides (`KC-8` where the still-owed op's call
|
|
623
|
+
// meets the store's own `JournalOpUnknown`, the failed save's arm being the store's own `§7.2` item 3
|
|
624
|
+
// rollback and the entry it rolled back being gone) and the pass's own token `KC-3` where no floor is met.
|
|
625
|
+
// **THE CALLER MEETS NEITHER FORM**: the store's verb produced this failure, so its code crosses on the
|
|
626
|
+
// STORE's channel, in the store's own two-member form, VERBATIM AND UNCONVERTED (`§1.2` item 2) — the
|
|
627
|
+
// kernel's token standing in the `outcome` entry's `state` — and THE VERY THROWABLE THE SEAM REWROTE is
|
|
628
|
+
// what leaves this call.
|
|
629
|
+
try {
|
|
630
|
+
settleArm(store, attempt);
|
|
631
|
+
} catch (saveFailure) {
|
|
632
|
+
if (attempt.record === undefined
|
|
633
|
+
|| attempt.record[SAVE_FAILED_AT_THE_TERMINAL_ARM] !== saveFailure) {
|
|
634
|
+
throw saveFailure;
|
|
635
|
+
}
|
|
636
|
+
// **AND THE PIN THE PASSING ARM TOOK IS RELEASED WITH IT** (`composition-and-states.md §2.6` item 3's
|
|
637
|
+
// `checkpoint` member's own domain, read at item 8 (iii); item 1's filter; item 2's *"WHERE THE ATTEMPT
|
|
638
|
+
// PASSED NO CHECKPOINT, THE CALL LIST IS ITEM 2'S OWN — THE WHOLE LIST"*). **THE MEMBER IS *"the opId of
|
|
639
|
+
// the op whose LANDING left the attempt's LAST VALID STATE, or null where no such landing exists FOR
|
|
640
|
+
// THAT ADDRESS"*** — and on THIS arm no landing of this attempt left one: the store's own failure arm
|
|
641
|
+
// has ALREADY restored the pre-state and popped the entry (`src/store.rs`'s `commit_file`; `§8.1` #15;
|
|
642
|
+
// clause 5's ROLLBACK FIRST), so the pass's own pin stood on a landing the save unsaid. **THE PIN IS
|
|
643
|
+
// THEREFORE `null` AND THE COMPOSITION'S CALL LIST IS THE WHOLE OF `ops`** — item 1's filter excludes
|
|
644
|
+
// the op a `null` member names from nothing — so the per-op call THIS ARM OWES IS ISSUED and its step
|
|
645
|
+
// stands in the report's `rollback`: *"the report carries the rollback that actually happened"*
|
|
646
|
+
// (`§2.6` item 3). Where the pinned op still stands in the store the call returns and the step records
|
|
647
|
+
// `'ok'`; where the failed save's own rollback took it the store answers `JournalOpUnknown` and the
|
|
648
|
+
// composition's floor reads `KC-8` in the ONE `outcome` entry (item 5 (b); item 6 (a)).
|
|
649
|
+
attempt.checkpoint = null;
|
|
650
|
+
terminal(kernel, attempt, KC.violated,
|
|
651
|
+
typeof saveFailure.message === 'string'
|
|
652
|
+
? saveFailure.message
|
|
653
|
+
: `the attempt's own save at ${JSON.stringify(attempt.address)} failed`);
|
|
654
|
+
throw saveFailure;
|
|
655
|
+
}
|
|
656
|
+
// **THE `commit` ENTRY: THE ATTEMPT'S SUCCESS ARM, APPENDED ONCE, ON THIS ARM ALONE**
|
|
657
|
+
// (`DEF-2026-10-16-B`; `kernel-surface.md §2.1` item 3's `LogKind` table — *"`commit` = the attempt's
|
|
658
|
+
// success arm, appended once"*, its `id` `null`, its `opId` the attempt's last op, its `state` `null`;
|
|
659
|
+
// `composition-and-states.md §2.7` items 5 and 7: *"one `constraint-check` entry per registered pair is
|
|
660
|
+
// appended, THEN the `commit` entry"*). **THE SAVE HAS STOOD** — the call above returned and this arm was
|
|
661
|
+
// not reached by the failed-save path — **SO IT IS APPENDED HERE AND ONLY HERE, AFTER every
|
|
662
|
+
// `constraint-check` entry of the pass, AND IT CLOSES THE LOG**: it is the PASSED arm's LAST entry, and
|
|
663
|
+
// the failing arm above appended its own ONE `outcome` entry and NO `commit` entry at all
|
|
664
|
+
// (`kernel-surface.md §2.1` item 4 (ii); item 3's two rows read together — the two one-shot arms never
|
|
665
|
+
// stand in one log). **AND NOTHING IS APPENDED TO THIS LOG AFTER IT**: the delivered set's bodies ran
|
|
666
|
+
// before this line and reach this attempt's log by no act (`§2.7` item 6), the record this attempt's
|
|
667
|
+
// report carries being the same list this line closes.
|
|
668
|
+
append(attempt, 'commit', null, attempt.ops[attempt.ops.length - 1].opId,
|
|
669
|
+
`every constraint registered at ${JSON.stringify(attempt.address)} passed; the commit stands`);
|
|
670
|
+
return closed;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* **THE SEAM'S TERMINAL INSTANT, TAKEN AT THE ONE PLACE BOTH ARMS REACH** (`surface.md §2.4` item 9 (b);
|
|
675
|
+
* `PAR-JS-19`; `A116` (D1)–(D2)): the record identity `K-2` answered, handed once more to THE INSTANCE'S
|
|
676
|
+
* OWN `settle` member — the member the kernel CALLS and the entry IMPLEMENTS — so that the entry delivers
|
|
677
|
+
* the residue standing in that record's `pending` at this instant through ITS OWN registry
|
|
678
|
+
* (`§2.7` item 7 (a)–(b)). **A SECOND CALL FOR THE SAME IDENTITY IS THE DELIVERY** (`PAR-JS-19`'s
|
|
679
|
+
* domain cell: *"the first call on this instance for a given identity IS the adoption, and the SECOND
|
|
680
|
+
* call for that identity is the delivery"*), so the record this reads is the very record instant (a)
|
|
681
|
+
* adopted and never a copy of it.
|
|
682
|
+
*
|
|
683
|
+
* **THE MEMBER IS REACHED WITH NO ADDON CALL AND NO STORE VERB**, on the caller's own instance object —
|
|
684
|
+
* the same object every item of this surface takes first.
|
|
685
|
+
*/
|
|
686
|
+
function settleArm(store, attempt) {
|
|
687
|
+
const record = attempt.record;
|
|
688
|
+
if (record === undefined) return;
|
|
689
|
+
if (typeof store.settle === 'function') store.settle(record);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* THE PASS LOOP OF ONE ATTEMPT — the first pass and, for EVERY repair the pass lands, the op's own
|
|
694
|
+
* ATOMIC LANDING EVALUATION followed by THE RE-RUN.
|
|
695
|
+
*
|
|
696
|
+
* `attempt-lifecycle.md §2.4` item 5 (iv): a pass's evaluated set is EVERY PAIR STANDING AT THE
|
|
697
|
+
* ATTEMPT'S OWN `address` WHEN THAT PASS BEGINS — the first pass and every re-run alike, the pairs that
|
|
698
|
+
* had already run INCLUDED, the pair whose repair just ran INCLUDED and a pair whose repair is
|
|
699
|
+
* registered but has not run INCLUDED — each evaluated ONCE in clause (ii)'s first-registration order,
|
|
700
|
+
* with NO EXCLUSION AND NO SKIP.
|
|
701
|
+
*
|
|
702
|
+
* `kernel-surface.md §2.3` item 1 — the OTHER rule: "EVERY WRITE THAT LANDS AT AN ADDRESS THE KERNEL
|
|
703
|
+
* REGISTERS PAIRS AT RUNS, AFTER THE WRITE VERB RETURNED AND BEFORE ANY OTHER KERNEL ACT, ONE PASS OVER
|
|
704
|
+
* EVERY PAIR REGISTERED AT THAT ADDRESS against THAT ONE OP's value and tier, its `AttemptContext.op`
|
|
705
|
+
* naming that op". A repair's own op is such a landing, and THIS is the arm "a repair's edit lands, the
|
|
706
|
+
* re-run evaluates EVERY pair at the attempt's address against THAT op, and where one of those
|
|
707
|
+
* evaluations does not return the pass arm THE ATTEMPT MOVES THROUGH THE RE-RUN'S OWN FOUR
|
|
708
|
+
* COMBINATIONS" names — so the repair's op is evaluated BEFORE the re-run, and the checkpoint therefore
|
|
709
|
+
* moves to THE REPAIR'S OWN OP.
|
|
710
|
+
*
|
|
711
|
+
* Returns `null` on the success arm, and the attempt's terminal arm otherwise.
|
|
712
|
+
*/
|
|
713
|
+
function runToCompletion(kernel, attempt) {
|
|
714
|
+
for (;;) {
|
|
715
|
+
// EVERY RUN READS THE ATTEMPT'S OWN SET, IN CLAUSE (ii)'s ORDER, AGAINST THE LANDING'S OWN OP:
|
|
716
|
+
// `attempt-lifecycle.md §2.4` item 5 (iv) fixes ONE scope for the first pass and every re-run alike,
|
|
717
|
+
// and `kernel-surface.md §2.3` item 1's atomic landing evaluation — whose own one home is that item —
|
|
718
|
+
// is the arm a repair's op landing owes: "a repair's edit lands, the re-run evaluates EVERY pair at
|
|
719
|
+
// the attempt's address against THAT op, and where one of those evaluations does not return the pass
|
|
720
|
+
// arm THE ATTEMPT MOVES THROUGH THE RE-RUN'S OWN FOUR COMBINATIONS". So the op a repair landed becomes
|
|
721
|
+
// THE NEXT RUN'S `op`, and every pair at the attempt's address — the pairs that had already run
|
|
722
|
+
// included — is evaluated against it, with no exclusion and no skip. THE RUN'S LANDING IS THE
|
|
723
|
+
// ATTEMPT'S LAST OP, AND THE RUN'S ADDRESS IS THAT OP'S OWN ADDRESS.
|
|
724
|
+
const landing = attempt.ops[attempt.ops.length - 1];
|
|
725
|
+
const run = evaluate(kernel, attempt, landing);
|
|
726
|
+
if (run.terminal !== null) return run.terminal;
|
|
727
|
+
if (!run.rerun) return null;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* ONE EVALUATION RUN — a LANDING'S OWN PASS. `attempt-lifecycle.md §2.4` item 5 (iv): "a pass's evaluated
|
|
733
|
+
* set is THE PAIRS STANDING AT THE ATTEMPT'S OWN `address` WHEN THAT PASS BEGINS … the first pass and
|
|
734
|
+
* every re-run alike … the pairs that had already run INCLUDED, the pair whose repair just ran INCLUDED
|
|
735
|
+
* and a pair whose repair is registered but has not run INCLUDED … each evaluated ONCE in clause (ii)'s
|
|
736
|
+
* first-registration order, WITH NO EXCLUSION AND NO SKIP." Every run — the commit's own landing, the
|
|
737
|
+
* repair's own landing and the re-run alike — therefore evaluates THAT ONE SET, against the op whose
|
|
738
|
+
* landing it reads. Answers:
|
|
739
|
+
* `{ terminal }` — the attempt's terminal arm, an EXISTING `KC` member, where one was reached;
|
|
740
|
+
* `{ terminal: null, rerun: true }` — a repair landed and its op was added to the attempt;
|
|
741
|
+
* `{ terminal: null, rerun: false }` — the pass arm, the `checkpoint` member pinned at that op.
|
|
742
|
+
*/
|
|
743
|
+
function evaluate(kernel, attempt, landing) {
|
|
744
|
+
// THE PASS'S OWN ADDRESS IS THE ATTEMPT'S (`attempt-lifecycle.md §2.4` item 5 (iv): "THE KERNEL
|
|
745
|
+
// EVALUATES THE PAIRS IT REGISTERED AT THE ATTEMPT'S OWN ADDRESS — the first pass and every re-run
|
|
746
|
+
// alike — and NOT the union of the store's prefix-selected addresses"), WHILE THE OP EVERY EVALUATION
|
|
747
|
+
// CARRIES IS THE LANDING'S OWN — the repair's op where a repair's edit landed, and the attempt's first
|
|
748
|
+
// write where the pass is the commit's own landing.
|
|
749
|
+
// THE PASS'S OWN EVALUATED SET IS FIXED WHEN THE PASS BEGINS — a SNAPSHOT of the registry's rows for
|
|
750
|
+
// the attempt's address AT THAT INSTANT, and never a live view of the registry this pass reads again:
|
|
751
|
+
// "a PASS's evaluated set is FIXED WHEN THE PASS BEGINS — it is every pair registered at the attempt's
|
|
752
|
+
// address AT THAT INSTANT, each evaluated once in clause (ii)'s order", so "A `K-1` THAT RETURNS
|
|
753
|
+
// DURING A PASS APPENDS A PAIR TO THE REGISTRY WITHOUT APPENDING ANY ENTRY TO THAT PASS AND WITHOUT
|
|
754
|
+
// BEING EVALUATED BY IT: the new pair enters the NEXT pass's set" (`attempt-lifecycle.md §2.4` item 5
|
|
755
|
+
// (iv); `CX-12`). The snapshot is ALSO the set the layer (a) delivery of this run is read over.
|
|
756
|
+
const standing = kernel.byAddress.get(addressToken(attempt.address));
|
|
757
|
+
const list = standing === undefined ? undefined : standing.slice();
|
|
758
|
+
// THE ATOMIC LANDING EVALUATION'S OWN ARM-TAKING IS `attempt-lifecycle.md §2.4` item 4's arms, read
|
|
759
|
+
// over THE PAIR THAT FAILED AT THAT OP (`kernel-surface.md §2.3` item 1; `§2.4`: `KC-3` where that pair
|
|
760
|
+
// is NOT in `ran` before this run and no repair is registered for it; `KC-6` where it IS in `ran` and
|
|
761
|
+
// is NOT in `appliedRepairs`; `KC-5` where it IS in `ran` and IS in `appliedRepairs`; and arm (b)
|
|
762
|
+
// where its repair is registered and has not run).
|
|
763
|
+
//
|
|
764
|
+
// `§2.4` ITEM 5 (ii)–(iii): "THE ATTEMPT TRANSITIONS AT THE FIRST EVALUATING PAIR WHOSE OUTCOME IS A
|
|
765
|
+
// VIOLATION: THAT PAIR'S OWN ARM DECIDES WHAT HAPPENS NEXT", and "where two pairs of one pass would
|
|
766
|
+
// violate, the FIRST in clause (ii)'s order decides and THE SECOND IS NOT EVALUATED". THE DECISION IS
|
|
767
|
+
// THEREFORE TAKEN INSIDE THE LOOP AT THE FIRST VIOLATING PAIR WHATEVER ITS FORM: a return standing
|
|
768
|
+
// OUTSIDE the three declared arms is READ AS the `{message}` arm (`PAR-C-5`; item 4's arm (c)
|
|
769
|
+
// predicate), so it is a violation of exactly the same standing as the caller's own `{message}` arm
|
|
770
|
+
// and is disposed of by the SAME predicates — NEVER carried to the end of the pass, where a later
|
|
771
|
+
// pair's landed repair would supersede the arm the attempt took first.
|
|
772
|
+
if (list !== undefined) {
|
|
773
|
+
for (const key of list) {
|
|
774
|
+
const pair = kernel.pairs.get(key);
|
|
775
|
+
if (pair === undefined) continue;
|
|
776
|
+
// `kernel-surface.md §2.3` item 1 — THE OP WHOSE LANDING LEFT THE STATE THIS EVALUATION RUNS AT,
|
|
777
|
+
// VERBATIM, and the value that write returned, VERBATIM: "the data the constraint confirms".
|
|
778
|
+
const op = landing;
|
|
779
|
+
const context = {
|
|
780
|
+
address: attempt.address.slice(),
|
|
781
|
+
attempt: attempt.ref,
|
|
782
|
+
op,
|
|
783
|
+
tier: op.tier === undefined ? null : op.tier,
|
|
784
|
+
value: op.after === undefined ? undefined : op.after.value,
|
|
785
|
+
};
|
|
786
|
+
|
|
787
|
+
// THE ENTRY IS OPENED BEFORE THE BODY RUNS, so a body that reads the record's own log mid-flight
|
|
788
|
+
// reads its own evaluation's entry — and it is WITHDRAWN where the body returns nothing
|
|
789
|
+
// (`kernel-surface.md §2.5` item 1; `PAR-C-6`).
|
|
790
|
+
append(attempt, 'constraint-check', pair.id, op.opId, `the evaluation of ${pair.id}`);
|
|
791
|
+
const check = attempt.log[attempt.log.length - 1];
|
|
792
|
+
let outcome;
|
|
793
|
+
try {
|
|
794
|
+
outcome = pair.constraint(context);
|
|
795
|
+
} catch (body) {
|
|
796
|
+
// A body that threw returned nothing, so no `constraint-check` entry stands; the attempt is
|
|
797
|
+
// closed and the BODY'S OWN THROWABLE reaches the caller unchanged and unconverted, carrying
|
|
798
|
+
// no kernel state token at all (`PAR-C-6`; `NX-2`; `composition-and-states.md §2.7` item 13).
|
|
799
|
+
withdraw(attempt, check);
|
|
800
|
+
terminal(kernel, attempt, null, `the constraint ${pair.id} threw; the attempt is closed`);
|
|
801
|
+
throw body;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// THE CONSTRAINT'S OWN OUTCOME — A CLOSED THREE-ARM SET (`PAR-C-5`). A value outside the three
|
|
805
|
+
// arms is read as the `{message}` arm and never as an arm of its own.
|
|
806
|
+
let text;
|
|
807
|
+
let repair = null;
|
|
808
|
+
if (outcome === true) {
|
|
809
|
+
text = `the constraint ${pair.id} passed at ${JSON.stringify(attempt.address)}`;
|
|
810
|
+
} else if (outcome !== null && typeof outcome === 'object' && 'message' in outcome) {
|
|
811
|
+
text = typeof outcome.message === 'string' && outcome.message.length > 0
|
|
812
|
+
? outcome.message
|
|
813
|
+
: unrecognized(pair);
|
|
814
|
+
if ('repair' in outcome && typeof outcome.repair === 'function') repair = outcome.repair;
|
|
815
|
+
} else {
|
|
816
|
+
text = unrecognized(pair);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
check.message = text;
|
|
820
|
+
|
|
821
|
+
// THE VIOLATION ARMS (`attempt-lifecycle.md §2.4` item 4 (b)–(f)), read off THE PAIR THAT FAILED
|
|
822
|
+
// and off nothing else. THE ONE DISCRIMINATOR IS THE PAIR'S OWN REGISTRY MEMBERSHIP READ AT THE
|
|
823
|
+
// INSTANT BEFORE THIS EVALUATION, TOGETHER WITH `ran` (`kernel-surface.md §2.5` item 3;
|
|
824
|
+
// `fail-surface.md §2`'s `KC-5`/`KC-6` rows): `KC-5` iff in `ran` AND in `appliedRepairs`;
|
|
825
|
+
// `KC-6` iff in `ran` AND OUT of `appliedRepairs` — whether or not a repair is registered for the
|
|
826
|
+
// pair, and NEVER off a repair-run COUNT.
|
|
827
|
+
const ran = attempt.ran.includes(key);
|
|
828
|
+
if (!ran) attempt.ran.push(key);
|
|
829
|
+
if (outcome === true) continue;
|
|
830
|
+
if (repair === null) {
|
|
831
|
+
// ARMS (c), (e) AND (f) — THE PAIR'S FIRST-EVALUATION ARM AND ITS TWO REPEAT ARMS, taken
|
|
832
|
+
// AT ONCE at the first violating pair whatever the form its return carried
|
|
833
|
+
// (`attempt-lifecycle.md §2.4` item 4's disjointness rule and item 5 (ii)–(iii)). Arm (c)'s
|
|
834
|
+
// predicate is "NOT in `ran` before this evaluation and no repair registered for it"; a pair
|
|
835
|
+
// IN `ran` is a repeat and never this arm, so its own token is read first.
|
|
836
|
+
if (ran) {
|
|
837
|
+
return { terminal: attempt.appliedRepairs.includes(key)
|
|
838
|
+
? { status: KC.repairRepeat,
|
|
839
|
+
message: `the pair ${pairKey(pair.address, pair.id)} violated a re-run and its repair had `
|
|
840
|
+
+ 'already been applied' }
|
|
841
|
+
: { status: KC.repeat,
|
|
842
|
+
message: `the pair ${pairKey(pair.address, pair.id)} violated a re-run and no repair had `
|
|
843
|
+
+ 'been applied to it' },
|
|
844
|
+
rerun: false };
|
|
845
|
+
}
|
|
846
|
+
return { terminal: { status: KC.violated, message: text }, rerun: false };
|
|
847
|
+
}
|
|
848
|
+
// LIMB (f) — A REPEAT BY A PAIR WHOSE REGISTERED REPAIR HAS NOT RUN IS TAKEN HERE AND NOT BELOW:
|
|
849
|
+
// "NO repair function is invoked a second time" (`P-SM-6`; `kernel-surface.md §2.5` item 3), the
|
|
850
|
+
// pair's own registry membership and never a repair-run count being the discriminator.
|
|
851
|
+
if (ran && !attempt.appliedRepairs.includes(key)) {
|
|
852
|
+
return { terminal: { status: KC.repeat,
|
|
853
|
+
message: `the pair ${pairKey(pair.address, pair.id)} violated a re-run and no repair had `
|
|
854
|
+
+ 'been applied to it' },
|
|
855
|
+
rerun: false };
|
|
856
|
+
}
|
|
857
|
+
// LIMB (e) — THE PAIR'S REPAIR HAS ALREADY RUN AND IS RECORDED AS APPLIED, so the second repair is
|
|
858
|
+
// never invoked and the repeat is `KC-5`.
|
|
859
|
+
if (ran) {
|
|
860
|
+
return { terminal: { status: KC.repairRepeat,
|
|
861
|
+
message: `the pair ${pairKey(pair.address, pair.id)} violated a re-run and its repair had `
|
|
862
|
+
+ 'already been applied' },
|
|
863
|
+
rerun: false };
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// ARM (b) — THE PAIR'S REPAIR RUNS THROUGH THE CALLER'S OWN VERB, AND THE OP IT LANDED IS READ
|
|
867
|
+
// OFF ITS OWN RETURN AND NOWHERE ELSE (`§2.7`). THE ENTRY'S `opId` IS THE ROW'S OWN VALUE FROM THE
|
|
868
|
+
// INSTANT IT IS APPENDED — "THE OP THE REPAIR PRODUCED WHERE IT PRODUCED ONE, ELSE THE OP IT WAS
|
|
869
|
+
// INVOKED FOR" (`kernel-surface.md §2.5` item 1's `repair-run` row) — so on EVERY arm the entry
|
|
870
|
+
// names THE OP THIS EVALUATION CARRIED, and only the arm that produced an op rewrites it below.
|
|
871
|
+
append(attempt, 'repair-run', pair.id, op.opId, 'the pair\'s repair was attempted');
|
|
872
|
+
const entry = attempt.log[attempt.log.length - 1];
|
|
873
|
+
let result;
|
|
874
|
+
try {
|
|
875
|
+
result = repair({
|
|
876
|
+
address: attempt.address.slice(),
|
|
877
|
+
id: pair.id,
|
|
878
|
+
op,
|
|
879
|
+
tier: context.tier,
|
|
880
|
+
value: context.value,
|
|
881
|
+
// **⟶ ADDED 2026-10-15 (`surface.md §2.11` clause 6; the architect's ruling of 2026-10-15;
|
|
882
|
+
// `kernel-surface.md §2.3` item 2).** **THE REPAIR IS PASSED THE COMMIT IT IS PART OF**, and it is
|
|
883
|
+
// passed THE ONE OBJECT THIS CALL HANDS IT — the context itself — *"so that they can make their
|
|
884
|
+
// own write call use that commit"*: *"Repair functions are returned by the constraint that they
|
|
885
|
+
// are triggered by. As externally-provided code, they should be using the package surface
|
|
886
|
+
// functions, which means they will need to be passed the commit they are part of so that they can
|
|
887
|
+
// make their own write call use that commit."* **THE FORM IS THE ONE `write`'s FIFTH POSITION
|
|
888
|
+
// ADMITS**: its class test is *"an object position is a record position only where it CARRIES A
|
|
889
|
+
// `pending` MEMBER whose value is present and not `undefined`"* (`§2.4` item 9 (g) item 1), and the
|
|
890
|
+
// member this context carries is THE COMMIT'S OWN `pending`, VERBATIM — the record `K-2` returned,
|
|
891
|
+
// the one `attempt.record` names, so the repair's write passes THE CONTEXT and the position reads
|
|
892
|
+
// the commit it stands for. **IT IS A CLASS TEST AND NEVER AN IDENTITY TEST** (the position's own
|
|
893
|
+
// clause), so a fresh list is handed and the record's own member is not aliased. **NO MEMBER OF
|
|
894
|
+
// THE DECLARED FIVE IS MOVED**: `address` · `id` · `op` · `tier` · `value` stand as `§2.3` item 2
|
|
895
|
+
// prints them, and the commit is carried beside them.
|
|
896
|
+
pending: attempt.record === undefined ? [] : attempt.record.pending.slice(),
|
|
897
|
+
});
|
|
898
|
+
} catch (body) {
|
|
899
|
+
// THE REPAIR-RUN ENTRY IS APPENDED BEFORE THE THROW, and the attempt's outcome entry carries
|
|
900
|
+
// `KC-4` (`ck_states_a_repair_body_that_throws_reaches_the_caller_unconverted`).
|
|
901
|
+
//
|
|
902
|
+
// AND WHERE THE STORE'S OWN VERB REFUSED THE REPAIR'S EDIT, THE ENTRY'S `message` NAMES THE
|
|
903
|
+
// STORE'S OWN CODE — `fail-surface.md §2`'s `KC-4` row's `observable` cell, read with `§1.2`
|
|
904
|
+
// item 3: "THE KERNEL'S GENERIC DESCRIPTION OF THE ATTEMPTED REPAIR ALONE DOES NOT SATISFY IT,
|
|
905
|
+
// AND THE CODE IS THE STORE'S OWN TOKEN — `WriteParentNotLink` in this unit's own repair window
|
|
906
|
+
// — and never a kernel string and never a `KC` token." The body threw the store's own form up
|
|
907
|
+
// through the kernel, so the code is read off that throwable's `status` and it is a STORE code
|
|
908
|
+
// (the store's form is `{status, message}`, carrying no `log` member — `§1.2` item 2; the
|
|
909
|
+
// kernel's own form carries three members, and a `KC` token is never named as a store code).
|
|
910
|
+
// The entry's `state` stays `null`; the thrown form's `status` is `KC-4`.
|
|
911
|
+
const storeCode = body !== null && typeof body === 'object'
|
|
912
|
+
&& typeof body.status === 'string'
|
|
913
|
+
&& body.status.length > 0
|
|
914
|
+
&& !('log' in body)
|
|
915
|
+
&& !KC_TOKENS.includes(body.status)
|
|
916
|
+
? body.status
|
|
917
|
+
: null;
|
|
918
|
+
if (storeCode !== null) {
|
|
919
|
+
entry.message = `the repair ${pair.id} was attempted and the store refused its own edit — the `
|
|
920
|
+
+ `store's answer is ${storeCode}`;
|
|
921
|
+
terminal(kernel, attempt, KC.repairFailed, entry.message);
|
|
922
|
+
// **⟶ AND THE FORM THAT CROSSES TO THE CALLER IS THE KERNEL'S OWN** (`kernel-surface.md §2.3`
|
|
923
|
+
// item 2 (iii): the attempt *"moves to `FAILING` with `KC-4`"*, and *"the thrown form's `status`
|
|
924
|
+
// is NEVER a store member"*) — **the very form the FAILING arm above throws**, carrying the
|
|
925
|
+
// store's own token in its MESSAGE and not in its `status` (§1.2 item 3). **A BODY WHOSE THROW
|
|
926
|
+
// CARRIES NO STORE CODE REACHES THE CALLER UNCONVERTED**, below: the unconverted throw is that
|
|
927
|
+
// body's own arm and this conversion is the refused-verb's.
|
|
928
|
+
refuse(attempt.throwState, attempt.throwMessage, attempt.log);
|
|
929
|
+
}
|
|
930
|
+
terminal(kernel, attempt, KC.repairFailed, `the repair ${pair.id} threw; the attempt is closed`);
|
|
931
|
+
throw body;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// THE REPAIR'S OWN RESULT — A CLOSED TWO-ARM SET (`PAR-C-8`), WHOSE SUCCESS ARM'S THIRD MEMBER
|
|
935
|
+
// IS THE OP THE REPAIR LANDED. AN `ok === true` RETURN WHOSE `op` IS ABSENT, `undefined` OR NOT
|
|
936
|
+
// THE OP THE REPAIR ACTUALLY LANDED HAS CARRIED NO OP AND IS THE APP'S OWN DEFECT: it is read as
|
|
937
|
+
// a repair that produced no op, so it fails `KC-4` whether or not the pair's repair had been
|
|
938
|
+
// recorded as applied (`§2.7`'s home; `§2.8`'s outside values; `A: docs/decisions.md` · `A110`).
|
|
939
|
+
const ok = result !== null && typeof result === 'object' && result.ok === true;
|
|
940
|
+
const produced = ok ? landedOp(attempt, result, op) : null;
|
|
941
|
+
if (produced === null) {
|
|
942
|
+
const carried = ok
|
|
943
|
+
? landedOpDefect(attempt, pair, result)
|
|
944
|
+
: result !== null && typeof result === 'object' && result.ok === false
|
|
945
|
+
&& typeof result.message === 'string' && result.message.length > 0
|
|
946
|
+
? result.message
|
|
947
|
+
: `the repair ${pair.id} produced no op at ${JSON.stringify(attempt.address)}`;
|
|
948
|
+
entry.message = carried;
|
|
949
|
+
return { terminal: { status: KC.repairFailed, message: carried }, rerun: false };
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// THE OP THE REPAIR PRODUCED IS ADDED and the pair enters `appliedRepairs`. The attempt then
|
|
953
|
+
// returns to the evaluation through THAT OP's OWN ATOMIC LANDING EVALUATION and the re-run.
|
|
954
|
+
entry.opId = produced.opId;
|
|
955
|
+
entry.message = `the repair ${pair.id} landed ${produced.opId}`;
|
|
956
|
+
attempt.ops.push(produced);
|
|
957
|
+
attempt.appliedRepairs.push(key);
|
|
958
|
+
// THE LAYER (a) DELIVERY OF THIS RUN'S OWN HANDLES, ONE PER EVALUATED PAIR (`kernel-surface.md
|
|
959
|
+
// §2.1` item 2; `§2.2` item 2): every handle this attempt's write returned that stands for a pair
|
|
960
|
+
// THIS RUN evaluated has now been checked off as it passed — it was invoked in the kernel's own
|
|
961
|
+
// window — so it leaves `CommitRecord.pending`, the member the caller's own loop reads its work
|
|
962
|
+
// off, THAT LOOP BEING ONE INVOKER AMONG THE JS SURFACE'S ORDERED LAYERS AND NEVER THE ONLY ONE
|
|
963
|
+
// (`A: docs/decisions.md` · `A112`). A handle whose pair this run did NOT evaluate STANDS IN THE
|
|
964
|
+
// MEMBER for that caller's own loop, and is never delivered twice.
|
|
965
|
+
releasePending(kernel, attempt, list);
|
|
966
|
+
return { terminal: null, rerun: true };
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
// A RUN THAT REACHES THIS LINE REACHED NO ARM INSIDE ITS LOOP: EVERY PAIR OF ITS OWN SNAPSHOT
|
|
970
|
+
// RETURNED THE PASS ARM OR LANDED A REPAIR, and a landed repair returned `rerun: true` above, its op's
|
|
971
|
+
// own landing evaluation following (`attempt-lifecycle.md §2.4` item 5 (i), (iv)).
|
|
972
|
+
releasePending(kernel, attempt, list);
|
|
973
|
+
// THE PASS ARM — EVERY PAIR OF THIS RUN'S OWN SET RETURNED THE PASS ARM, SO THE LANDING LEFT A VALID
|
|
974
|
+
// STATE AND THE EVALUATION'S RESULT IS PINNED HERE, AT THE ATTEMPT'S OWN `checkpoint` MEMBER, AND AT
|
|
975
|
+
// THAT LANDING'S OP (`composition-and-states.md §2.6` item 8 (i)–(ii), (iii); `kernel-surface.md §2.3`
|
|
976
|
+
// item 1). A run whose pair set is EMPTY is still a pair set: it returns the pass arm vacuously and
|
|
977
|
+
// PINS THE MEMBER AT THAT LANDING'S OP, so the `null` arm of item 8 (iii) is never that arm.
|
|
978
|
+
//
|
|
979
|
+
// AND THE VALUE IS ADDRESS-WIDE: THE CHECKPOINT IS "THE `opId` OF THE LAST LANDING THAT LEFT EVERY
|
|
980
|
+
// REGISTERED PAIR AT THE ATTEMPT'S OWN ADDRESS PASSING", so the pin belongs to the attempt's ADDRESS —
|
|
981
|
+
// a landing BESIDE it (a repair's op at a descendant address, whose pair set this attempt's scope does
|
|
982
|
+
// not reach) pins no member of this attempt and moves nothing (`§2.6` item 8 (i)'s foreign-landing
|
|
983
|
+
// clause; `VD-3`; `VD-6`). A violation arm returned above and therefore LEAVES THE MEMBER UNMOVED, so
|
|
984
|
+
// an earlier pin survives a later landing that failed.
|
|
985
|
+
if (addressToken(landing.address) === addressToken(attempt.address)) attempt.checkpoint = landing.opId;
|
|
986
|
+
return { terminal: null, rerun: false };
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* A RUN'S OWN LAYER (a) DELIVERY — one per evaluated pair, each carrying that pair's own function
|
|
991
|
+
* (`kernel-surface.md §2.1` item 2; `§2.2` item 2). The handle each evaluated pair's registration stands
|
|
992
|
+
* behind has now been invoked in the kernel's own window — THE PAIR'S PASS HAS CHECKED IT OFF AS IT
|
|
993
|
+
* PASSED — so it has left the member BY ITS OWN PASS and it STILL STANDS in `triggered`, the store's own
|
|
994
|
+
* returned set, which no removal ever reaches (`A: docs/decisions.md` · `A112`).
|
|
995
|
+
*
|
|
996
|
+
* **AND THE CHECK-OFF REMOVES EVERY OCCURRENCE OF THE IDENTITY IT EVALUATED — the entry's OWN pass is
|
|
997
|
+
* the removal's warrant** (`surface.md §2.7` item 7 (a): the member is the returned set *"MINUS the
|
|
998
|
+
* entries the pass checked off as they passed … AND MINUS NOTHING ELSE"*; `§2.4` item 8 (c): a body of
|
|
999
|
+
* a checked-off identity run at the delivery instant is a FAILURE of that item). **THE SINGLE-OCCURRENCE
|
|
1000
|
+
* REMOVAL THIS SITE ONCE SHIPPED — `indexOf` + `splice`, one entry per evaluated pair — LEFT ONE
|
|
1001
|
+
* OCCURRENCE STANDING WHERE THE STORE'S OWN LIST CARRIED THAT IDENTITY TWICE** (the lawful
|
|
1002
|
+
* caller-spelled duplicate: two construction entries at one address carrying the caller's same token
|
|
1003
|
+
* resolve to ONE home entry and ONE handle, which the store returns TWICE — `DD-42` clause 3; `DD-39`;
|
|
1004
|
+
* `surface.md §2.4`'s dated clause (ii); `PAR-JS-15`), **so the residue delivered that identity's
|
|
1005
|
+
* function a second time AT THE DELIVERY INSTANT — an entry the pass checked off, delivered.** **THE
|
|
1006
|
+
* DISCARD BESIDE THIS SITE ALREADY REMOVES BY THE SET (`terminal`'s `filter` against the failed write's
|
|
1007
|
+
* own returned set, `:892`), and the check-off now removes by the identity it evaluated** — ONE warrant,
|
|
1008
|
+
* every occurrence of it, and NO occurrence counts as a second entry for a set the pass has passed.
|
|
1009
|
+
*
|
|
1010
|
+
* **⟶ AND WHAT THE CHECK-OFF CONSUMED IS RECORDED AS IT IS TAKEN** (`docs/decisions.md` · `A117` (D5)):
|
|
1011
|
+
* the removal below is `A117`'s *"check-off consumes the evaluated pair's own delivery of that identity"*
|
|
1012
|
+
* and it is NOT *"that identity's whole owed delivery"* — so the identity it took is pushed onto the
|
|
1013
|
+
* attempt's own `checkedOff` list, which the PASSING arm publishes onto the record (`publishCheckedOff`)
|
|
1014
|
+
* for the terminal arm's delivery to resolve exactly as it resolves the residue. **THE REMOVAL ITSELF IS
|
|
1015
|
+
* UNTOUCHED BY THE RECORDING** — same warrant, same by-identity extent, same member, `pending`-based
|
|
1016
|
+
* assertions intact.
|
|
1017
|
+
*/
|
|
1018
|
+
function releasePending(kernel, attempt, keys) {
|
|
1019
|
+
const record = attempt.record;
|
|
1020
|
+
if (record === undefined || keys === undefined) return;
|
|
1021
|
+
for (const key of keys) {
|
|
1022
|
+
const handle = kernel.handles.get(key);
|
|
1023
|
+
if (handle === undefined) continue;
|
|
1024
|
+
record.pending = record.pending.filter((h) => h !== handle);
|
|
1025
|
+
if (!attempt.checkedOff.includes(handle)) attempt.checkedOff.push(handle);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* **THE PASSING ARM'S OWN PUBLICATION — `A117` (D5)'s finding PLACED ON THE RECORD THE TERMINAL ARM
|
|
1031
|
+
* HANDS TO THE INSTANCE'S SEAM.**
|
|
1032
|
+
*
|
|
1033
|
+
* It is called at `runAttempt`'s success arm, AFTER the attempt is CLOSED and BEFORE `settleArm`, and it
|
|
1034
|
+
* is called THERE and on NO FAILING ARM (`terminal`'s arm reaches none of this): on a write that fails on
|
|
1035
|
+
* constraints the other listeners are DISCARDED (`§2.7` item 6 read at item 7 (d); `A114` (D1)/(D2)), so
|
|
1036
|
+
* the arm's residue is empty AND a checked-off identity stands for NO delivery, its body never run — the
|
|
1037
|
+
* failing arm stays `0` of the failed write's own set and `0` for the identity too.
|
|
1038
|
+
*
|
|
1039
|
+
* **THE KEY IS A SYMBOL** (`CHECKED_OFF` above): `CommitRecord` keeps its four members (`A117` (D6)), the
|
|
1040
|
+
* record's enumerable shape does not move, and every census that reads a record's members reads them
|
|
1041
|
+
* through the same four.
|
|
1042
|
+
*/
|
|
1043
|
+
function publishCheckedOff(attempt) {
|
|
1044
|
+
const record = attempt.record;
|
|
1045
|
+
if (record === undefined || attempt.checkedOff.length === 0) return;
|
|
1046
|
+
Object.defineProperty(record, CHECKED_OFF, {
|
|
1047
|
+
value: attempt.checkedOff.slice(),
|
|
1048
|
+
enumerable: false,
|
|
1049
|
+
configurable: true,
|
|
1050
|
+
writable: true,
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
/** `PAR-C-5`'s outside value, read as the `{message}` arm with the KERNEL's own generated sentence. */
|
|
1055
|
+
function unrecognized(pair) {
|
|
1056
|
+
return `the constraint ${pair.id} returned a value outside the three declared outcome arms at `
|
|
1057
|
+
+ `${JSON.stringify(pair.address)}`;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* The attempt reference a READER was handed — THE `AttemptRef` RECORD OR ITS `id` STRING AND NOTHING
|
|
1062
|
+
* ELSE (`attempt-lifecycle.md §2.4` item 1: "`K-4`/`K-5` accept either the `AttemptRef` record or its
|
|
1063
|
+
* `id` string and NOTHING ELSE"; `parameter-semantics.md §2.15`). A `CommitRecord` is NOT an
|
|
1064
|
+
* `AttemptRef` — it carries four members, its `attempt` among them — so a reference that is neither of
|
|
1065
|
+
* the two declared forms is `null` here and is refused `KC-2` by the caller, never answered out of the
|
|
1066
|
+
* live map and never reaching `KC-7`'s subject.
|
|
1067
|
+
*/
|
|
1068
|
+
function attemptIdOf(reference) {
|
|
1069
|
+
if (typeof reference === 'string') return reference;
|
|
1070
|
+
if (reference !== null && typeof reference === 'object' && typeof reference.id === 'string') {
|
|
1071
|
+
return reference.id;
|
|
1072
|
+
}
|
|
1073
|
+
return null;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
/** `K-3`'S OWN ARGUMENT IS THE `CommitRecord` `K-2` RETURNED (`kernel-surface.md §2.1` item 2), and the
|
|
1077
|
+
* attempt it names is the `AttemptRef` that record carries. */
|
|
1078
|
+
function commitAttemptIdOf(commitRecord) {
|
|
1079
|
+
if (commitRecord !== null && typeof commitRecord === 'object'
|
|
1080
|
+
&& commitRecord.attempt !== null && typeof commitRecord.attempt === 'object'
|
|
1081
|
+
&& typeof commitRecord.attempt.id === 'string') {
|
|
1082
|
+
return commitRecord.attempt.id;
|
|
1083
|
+
}
|
|
1084
|
+
return attemptIdOf(commitRecord);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
/**
|
|
1088
|
+
* THE TERMINAL ACT (`attempt-lifecycle.md §2.4` item 3's terminal-arm clause; item 7;
|
|
1089
|
+
* `composition-and-states.md §2.7` item 13): the per-op rollback composition runs FIRST, then the
|
|
1090
|
+
* attempt's final record is placed in the closed store.
|
|
1091
|
+
*
|
|
1092
|
+
* THE THROWN FORM'S `status` AND THE `outcome` ENTRY'S `state` ARE ONE TOKEN, and where a still-owed
|
|
1093
|
+
* op's own call meets a compacted base the composition's own answer is `KC-8` — that token being both
|
|
1094
|
+
* the arm's and the entry's (`composition-and-states.md §2.6` items 5 (b) and 6 (a), (iv);
|
|
1095
|
+
* `fail-surface.md §2`'s `KC-8` row). The CONSTRAINT-body path passes `null` and its entry's `state` is
|
|
1096
|
+
* `null`; the repair-body path passes `KC-4`'s token.
|
|
1097
|
+
*
|
|
1098
|
+
* AND THE ATTEMPT-RECORD ENTRY THE ADDRESS WAS HELD BY IS REMOVED ON EVERY TERMINAL ARM, the standing
|
|
1099
|
+
* remainder being THE COMMIT REGISTRY'S OWN ENTRY and never that open `AttemptRecord` entry
|
|
1100
|
+
* (`§2.4` item 3's terminal-arm clause; item 8 (i) (3); `contract.md §5.2`'s retain row) — so a fresh
|
|
1101
|
+
* `K-2` at that address RETURNS a `CommitRecord` and is never refused `KC-7`, whose own subject is the
|
|
1102
|
+
* attempt that IS live.
|
|
1103
|
+
*/
|
|
1104
|
+
function terminal(kernel, attempt, status, message) {
|
|
1105
|
+
const floor = composeRollback(kernel, attempt);
|
|
1106
|
+
// THE COMPOSITION'S OWN FLOOR, TAKEN OFF THE MEMBER IT WAS DECIDED ON (`composition-and-states.md
|
|
1107
|
+
// §2.6` item 5 (b)): a still-owed op's call meeting either floor code makes the arm `KC-8` WHATEVER
|
|
1108
|
+
// the pass's own arm was, and nothing is restored (item 6 (a), (c)).
|
|
1109
|
+
const finalStatus = floor === null ? status : KC.rollbackFloor;
|
|
1110
|
+
const finalMessage = floor === null
|
|
1111
|
+
? message
|
|
1112
|
+
: `the per-op rollback met the store's own ${floor.code} at ${floor.opId}`;
|
|
1113
|
+
// THE `outcome` ENTRY — appended ONCE, and `state` is THE ARM'S ONE TOKEN: the floor is answered IN THIS
|
|
1114
|
+
// SAME ENTRY where the attempt would also have had a failure arm, and NO SECOND ENTRY IS APPENDED
|
|
1115
|
+
// (`kernel-surface.md §2.5` item 1's kind table; `§2.6` item 6 (a), (b)).
|
|
1116
|
+
append(attempt, 'outcome', null, attempt.ops[attempt.ops.length - 1].opId, finalMessage, finalStatus);
|
|
1117
|
+
// THE DISCARD RULE, AT ITS ONE OBSERVABLE (`attempt-lifecycle.md §2.4` item 8 (i) (5), read with
|
|
1118
|
+
// `kernel-surface.md §2.1` item 2's discarded-set clause; `A: docs/decisions.md` · `A112`): where the
|
|
1119
|
+
// attempt's own write FAILED the registered constraints at its landing and could not be repaired, its
|
|
1120
|
+
// composition is ROLLED BACK and THE DISCARD ACTS ON THAT WRITE'S OWN RETURNED SET AND REACHES EVERY
|
|
1121
|
+
// HANDLE OF IT — no handle of that write being delivered by either layer — WHILE AN ENTRY FOR A HANDLE
|
|
1122
|
+
// OF ANY OTHER WRITE STANDS, the whole-member clear being WITHDRAWN BY NAME AS THE SECOND, UNLAWFUL
|
|
1123
|
+
// REMOVAL. THE FAILED WRITE'S OWN RETURNED SET IS READ OFF THE WRITE ITSELF (`attempt.write`'s own
|
|
1124
|
+
// `triggered`, the record's `triggered` member VERBATIM) AND NEVER DERIVED FROM THE ATTEMPT'S ADDRESS OR FROM THE
|
|
1125
|
+
// AUTHOR OF ANY REGISTRATION: the store's own trigger selection is prefix-inclusive, so a handle it
|
|
1126
|
+
// returned for a registration at a PREFIX address IS a member of THIS write's returned set and LEAVES
|
|
1127
|
+
// with every other handle of it, its pair being one NO pass of this attempt evaluates and no check-off
|
|
1128
|
+
// therefore reaching it. An entry for a handle THIS WRITE DID NOT RETURN — which is what "an entry for
|
|
1129
|
+
// a handle of any other write" means — STANDS. So this is the ONE
|
|
1130
|
+
// REMOVAL PER ARM beside a check-off, and a body already run is never un-run; a PASSING attempt
|
|
1131
|
+
// discards nothing (its own removals are the check-offs `releasePending` performs), and the member is
|
|
1132
|
+
// NEVER cleared as a whole.
|
|
1133
|
+
if (attempt.record !== undefined) {
|
|
1134
|
+
const returnedSet = attempt.write.triggered;
|
|
1135
|
+
attempt.record.pending = attempt.record.pending.filter((h) => !returnedSet.includes(h));
|
|
1136
|
+
}
|
|
1137
|
+
attempt.status = 'closed';
|
|
1138
|
+
attempt.throwState = finalStatus;
|
|
1139
|
+
attempt.throwMessage = finalMessage;
|
|
1140
|
+
attempt.report = {
|
|
1141
|
+
attempt: attempt.ref,
|
|
1142
|
+
// THE `outcome` MEMBER IS THE ATTEMPT'S OWN TWO-ARM ANSWER — `'passed'` or `'failed'` — and NEVER
|
|
1143
|
+
// the arm's `KC` token, which belongs to the thrown form's `status` and to the `outcome` ENTRY's
|
|
1144
|
+
// `state` (`PAR-C-5`'s observable: "its terminal record placed with `outcome: 'failed'`"; the two
|
|
1145
|
+
// members read the same token string only in `status`/`state`, `fail-surface.md §1.1` item 1 (c)).
|
|
1146
|
+
outcome: 'failed',
|
|
1147
|
+
ops: attempt.ops.slice(),
|
|
1148
|
+
log: attempt.log,
|
|
1149
|
+
rollback: attempt.rollback.slice(),
|
|
1150
|
+
};
|
|
1151
|
+
CLOSED.set(attempt.ref.id, attempt.report);
|
|
1152
|
+
release(kernel, attempt);
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
/**
|
|
1156
|
+
* THE ONE REMOVAL EVERY TERMINAL ARM OWES (`attempt-lifecycle.md §2.4` item 3; `composition-and-states.md
|
|
1157
|
+
* §2.7` item 13): the attempt's OPEN-RECORD entry — the entry the address was HELD by — is removed, so
|
|
1158
|
+
* the address is left FREE and a fresh `K-2` there RETURNS rather than being refused `KC-7`. What is
|
|
1159
|
+
* retained is the CLOSED record (`K-4`/`K-5`'s arm) and, behind it, the commit registry's own entry —
|
|
1160
|
+
* and NOT this map's.
|
|
1161
|
+
*/
|
|
1162
|
+
function release(kernel, attempt) {
|
|
1163
|
+
LIVE.delete(attempt.ref.id);
|
|
1164
|
+
kernel.held.delete(addressToken(attempt.address));
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/** The success arm's own bookkeeping, shared with `terminal`'s removal rule. */
|
|
1168
|
+
function close(kernel, attempt, outcome) {
|
|
1169
|
+
attempt.status = 'closed';
|
|
1170
|
+
const report = {
|
|
1171
|
+
attempt: attempt.ref,
|
|
1172
|
+
outcome,
|
|
1173
|
+
ops: attempt.ops.slice(),
|
|
1174
|
+
log: attempt.log,
|
|
1175
|
+
rollback: [],
|
|
1176
|
+
};
|
|
1177
|
+
attempt.report = report;
|
|
1178
|
+
CLOSED.set(attempt.ref.id, report);
|
|
1179
|
+
release(kernel, attempt);
|
|
1180
|
+
return report;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
/**
|
|
1184
|
+
* `composition-and-states.md §2.6` ITEM 2, ITEM 5 (a) AND ITEM 8 (iii) — THE PER-OP ROLLBACK COMPOSITION.
|
|
1185
|
+
*
|
|
1186
|
+
* THE CALL LIST IS ITEM 2'S OWN ON BOTH ARMS — `A111`'s RE-SPELLING, WHICH SUPERSEDES BY NAME THE
|
|
1187
|
+
* SINGLE-OP READING OF ITEM 8 (iii)'S *"THE ATTEMPT'S FIRST OP ALONE"* SENTENCE — AND THE KERNEL ISSUES
|
|
1188
|
+
* ONE CALL PER STILL-OWED OP: THE NUMBER OF CALLS ISSUED IS THE NUMBER OF STEPS RECORDED (item 5 (a)
|
|
1189
|
+
* (i), item 3).
|
|
1190
|
+
*
|
|
1191
|
+
* (1) THE ORDER (item 2, declared by the kernel and by nothing store-side): **the repaired ops
|
|
1192
|
+
* first, in REVERSE of the order they were created, and the attempt's first write's op LAST** —
|
|
1193
|
+
* "so the composition is `ops` minus its first entry, reversed, then that first entry last, and the
|
|
1194
|
+
* order is TOTAL over `ops`". SO THE CALL LIST'S FIRST CALL IS THE LIST'S LAST ENTRY — THE ATTEMPT'S
|
|
1195
|
+
* OWN FIRST OP. AND WHERE THE `checkpoint` MEMBER NAMES AN OP THE LIST IS FIXED AT COMPOSITION TIME
|
|
1196
|
+
* AS `ops` UP TO AND EXCLUDING THAT OP, REVERSED; THE STOP OP IS NEVER PASSED, because no call is
|
|
1197
|
+
* issued over the `checkpoint` op or over anything at or before it (item 4's reach/stop clause,
|
|
1198
|
+
* item 5 (b)) — and the `checkpoint` op is not a member of the list, not an op the walk re-shapes it
|
|
1199
|
+
* against.
|
|
1200
|
+
*
|
|
1201
|
+
* (2) AN OP AN EARLIER RETURNED CALL'S OWN `undoneOps` MEMBER ALREADY REPORTS UNDONE IS NOT A STILL-OWED
|
|
1202
|
+
* OP: the kernel ISSUES NO CALL over it and records NO step for it (item 5 (a)'s skip clause and its
|
|
1203
|
+
* `VF-10` bullet, whose worked case is the live run's own `E2E-C-2.7`, where the second call over an
|
|
1204
|
+
* op the first call had already reversed was answered `RollbackCompacted` and left the address's
|
|
1205
|
+
* entry standing). THE PREDICATE IS THE STORE'S OWN MEMBER AND NEVER AN INFERENCE ABOUT WHAT A LATER
|
|
1206
|
+
* CALL WOULD DO, and `performed` holds it: the `opId`s EARLIER RETURNED CALLS REPEATED — a THROWING
|
|
1207
|
+
* call undoes nothing (`undoneOps: []`), so it can never put an op on that list. THE STEP COUNT IS
|
|
1208
|
+
* THEREFORE THE CALLS ISSUED AND MAY RUN BELOW THE LIST'S SIZE.
|
|
1209
|
+
*
|
|
1210
|
+
* SO THE WALK NEVER STOPS SHORT OF AN OP IT STILL OWES: `failed` is THAT CALL'S OWN ANSWER (`true` iff
|
|
1211
|
+
* it threw), a `true` step carries no claim that the walk stopped, and an op the walk never reached
|
|
1212
|
+
* carries no step at all because no call was issued over it.
|
|
1213
|
+
*
|
|
1214
|
+
* THE ONE MEMBER THE STORE'S OWN REPORT IS READ FOR BESIDE THE SKIP IS THE FLOOR (`item 5 (b)`): an op
|
|
1215
|
+
* the composition STILL OWES — one whose `opId` stands in NO earlier step's `undoneOps` member — whose
|
|
1216
|
+
* call fails either floor code is `KC-8`. `KC-8` is answered in the attempt's ONE `outcome` entry,
|
|
1217
|
+
* naming the store's own code, and the composition STOPS at that failing call: no call is issued over an
|
|
1218
|
+
* op after it (item 6 (a); `fail-surface.md §2`'s `KC-8` row).
|
|
1219
|
+
*
|
|
1220
|
+
* EACH STEP'S MEMBERS ARE THE STORE'S OWN (`§2.6` item 3): `answer` is THE LITERAL `'ok'` where the call
|
|
1221
|
+
* RETURNED and THE STORE'S OWN CODE where it THREW; `undoneOps` is the store's own report of the
|
|
1222
|
+
* reversals it performed, and `[]` on the throwing arm, where nothing was undone; `restoredTo` is the
|
|
1223
|
+
* store's `RollbackResult.restoredTo` on the returning arm and, on the throwing arm, THE STATE THE NAMED
|
|
1224
|
+
* OP'S OWN SUBTREE STOOD AT read through the store's own `read` verb — a TWO-MEMBER `BaseState` on BOTH
|
|
1225
|
+
* arms; and `checkpoint` is the attempt's ONE value, on every step of the attempt.
|
|
1226
|
+
*/
|
|
1227
|
+
function composeRollback(kernel, attempt) {
|
|
1228
|
+
// (1) THE CALL LIST, FIXED WHEN THE COMPOSITION BEGINS AND IN ITEM 2'S OWN ORDER ON BOTH ARMS: `ops`
|
|
1229
|
+
// up to and excluding the `checkpoint` op where the member NAMES one (so the stop op is no member of
|
|
1230
|
+
// the list at all), REVERSED — the repaired ops in reverse of their creation and THE FIRST WRITE'S OP
|
|
1231
|
+
// LAST. Where the member is `null` the list is the whole of `ops` under that same order.
|
|
1232
|
+
const callList = [];
|
|
1233
|
+
for (const op of attempt.ops) {
|
|
1234
|
+
if (attempt.checkpoint !== null && op.opId === attempt.checkpoint) break;
|
|
1235
|
+
callList.push(op);
|
|
1236
|
+
}
|
|
1237
|
+
callList.reverse();
|
|
1238
|
+
// THE REVERSALS EARLIER RETURNED CALLS PERFORMED — the store's own reports, the only member item 5's
|
|
1239
|
+
// "still owes" predicate (and item 5 (a)'s skip) is decided by.
|
|
1240
|
+
const performed = [];
|
|
1241
|
+
let floor = null;
|
|
1242
|
+
for (const op of callList) {
|
|
1243
|
+
const owed = !performed.includes(op.opId);
|
|
1244
|
+
// (2) THE SKIP: an op an earlier returned call's own `undoneOps` already reports undone is not still
|
|
1245
|
+
// owed, so NO call is issued over it and no step stands for it (item 5 (a)).
|
|
1246
|
+
if (!owed) continue;
|
|
1247
|
+
let answer = 'ok';
|
|
1248
|
+
let failed = false;
|
|
1249
|
+
let record = null;
|
|
1250
|
+
try {
|
|
1251
|
+
record = attempt.store.rollback(op.opId);
|
|
1252
|
+
} catch (thrown) {
|
|
1253
|
+
failed = true;
|
|
1254
|
+
answer = thrown !== null && typeof thrown === 'object' && typeof thrown.status === 'string'
|
|
1255
|
+
? thrown.status
|
|
1256
|
+
: 'the call threw';
|
|
1257
|
+
}
|
|
1258
|
+
if (failed && floor === null && STORE_FLOOR_CODES.includes(answer)) {
|
|
1259
|
+
floor = { opId: op.opId, code: answer };
|
|
1260
|
+
}
|
|
1261
|
+
const undoneOps = record !== null && Array.isArray(record.undoneOps) ? record.undoneOps : [];
|
|
1262
|
+
attempt.rollback.push({
|
|
1263
|
+
opId: op.opId,
|
|
1264
|
+
answer,
|
|
1265
|
+
failed,
|
|
1266
|
+
undoneOps,
|
|
1267
|
+
// THE THROWING ARM CANNOT READ A RETURNED `RollbackResult`: the state stands at the NAMED OP's own
|
|
1268
|
+
// subtree, read at the store's own verb (item 3).
|
|
1269
|
+
restoredTo: record !== null && record.restoredTo !== undefined && record.restoredTo !== null
|
|
1270
|
+
? record.restoredTo
|
|
1271
|
+
: baseState(attempt.store, op.address),
|
|
1272
|
+
checkpoint: attempt.checkpoint,
|
|
1273
|
+
});
|
|
1274
|
+
for (const undone of undoneOps) {
|
|
1275
|
+
if (!performed.includes(undone)) performed.push(undone);
|
|
1276
|
+
}
|
|
1277
|
+
// AND THE WALK STOPS AT THE FAILING CALL: a call that met either floor code is the composition's
|
|
1278
|
+
// LAST — "the walk STOPS at the failing call" (`§2.6` item 6 (a); `fail-surface.md §2`'s `KC-8`
|
|
1279
|
+
// row), so no call is issued over an op after it and none of those ops carries a step.
|
|
1280
|
+
if (floor !== null) break;
|
|
1281
|
+
}
|
|
1282
|
+
return floor;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
/**
|
|
1286
|
+
* THE STORE'S OWN BASE STATE AT ONE ADDRESS, READ THROUGH THE STORE'S OWN VERB (`composition-and-states.md
|
|
1287
|
+
* §2.6` item 3: the state that address stands at once the call has returned, read through the store's own
|
|
1288
|
+
* `read`). BOTH members are always carried: a state that is not present carries `value` as `undefined`,
|
|
1289
|
+
* so the two-member shape never depends on the arm the call took.
|
|
1290
|
+
*/
|
|
1291
|
+
function baseState(store, address) {
|
|
1292
|
+
try {
|
|
1293
|
+
return { present: true, value: store.read(address) };
|
|
1294
|
+
} catch (refused) {
|
|
1295
|
+
// `AddressNotFound` is the store's own arm for an address that stands nowhere: ABSENT, and still
|
|
1296
|
+
// the declared two-member `BaseState`.
|
|
1297
|
+
return { present: false, value: undefined };
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// ---------------------------------------------------------------------------------------------
|
|
1302
|
+
// `K-4` `log(store, attempt) -> LogEntry[]` — the attempt's own log, OPEN or CLOSED alike.
|
|
1303
|
+
// ---------------------------------------------------------------------------------------------
|
|
1304
|
+
export function log(store, reference) {
|
|
1305
|
+
const id = attemptIdOf(reference);
|
|
1306
|
+
const live = LIVE.get(id);
|
|
1307
|
+
if (live !== undefined) return live.log;
|
|
1308
|
+
const closed = CLOSED.get(id);
|
|
1309
|
+
if (closed !== undefined) return closed.log;
|
|
1310
|
+
refuse(KC.arg, `no constraint attempt answers to ${id}`, []);
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
// ---------------------------------------------------------------------------------------------
|
|
1314
|
+
// `K-5` `report(store, attempt) -> AttemptReport`
|
|
1315
|
+
// ---------------------------------------------------------------------------------------------
|
|
1316
|
+
export function report(store, reference) {
|
|
1317
|
+
const id = attemptIdOf(reference);
|
|
1318
|
+
const live = LIVE.get(id);
|
|
1319
|
+
if (live !== undefined) {
|
|
1320
|
+
// `K-5` OVER AN ATTEMPT THAT IS STILL OPEN IS `KC-7` — "which is how a drive reads that the attempt
|
|
1321
|
+
// IS live" (`kernel-surface.md §2.1` item 5; `fail-surface.md §2`'s `KC-7` row). THIS IS THE MEMBER
|
|
1322
|
+
// THE OPEN ATTEMPT ANSWERS WITH AND NOT `KC-2`: a live record carries no final report at all, so an
|
|
1323
|
+
// open record is refused whether the attempt is mid-run or has not yet begun.
|
|
1324
|
+
refuse(KC.attemptOpen, `the constraint attempt ${id} is still open`, []);
|
|
1325
|
+
}
|
|
1326
|
+
const closed = CLOSED.get(id);
|
|
1327
|
+
if (closed !== undefined) return closed;
|
|
1328
|
+
// AN UNKNOWN REFERENCE IS KC-2 AND NEVER KC-7 (`kernel-surface.md §2.1` item 5).
|
|
1329
|
+
refuse(KC.arg, `no constraint attempt answers to ${id}`, []);
|
|
1330
|
+
}
|