provident-storeroom 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.guide.md +212 -5
- package/README.md +36 -11
- package/RELEASE-NOTES.md +610 -0
- package/index.d.ts +77 -6
- package/index.mjs +120 -34
- package/package.json +7 -6
- package/src/entry/constraints.mjs +662 -73
- package/src/entry/delivery.mjs +19 -5
- package/src/entry/kernel-attempt.mjs +181 -23
- package/src/entry/kernel-commit.mjs +191 -2
- package/src/entry/kernel-foundations.mjs +266 -24
- package/src/entry/kernel-registration.mjs +81 -27
- package/src/entry/kernel-terminal.mjs +18 -5
- package/src/entry/state.mjs +47 -4
package/src/entry/delivery.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { arrayClass, classSpelling, hasLoneSurrogate, isPlainObjectValue, target
|
|
|
6
6
|
import { encodeAddress, encodeOpId, handleWire, inDomainHandle } from './carrier.mjs';
|
|
7
7
|
import { decodeSegments, spellConstraintAddress } from './frame.mjs';
|
|
8
8
|
import { addressSpelling } from './kernel-foundations.mjs';
|
|
9
|
-
import { entryOf, carryRefusal, commitFile, homeAddressKey, externalCall, SETTLED_ON_THE_PASSING_ARM, SAVE_FAILED_AT_THE_TERMINAL_ARM } from './state.mjs';
|
|
9
|
+
import { entryOf, carryRefusal, commitFile, homeAddressKey, externalCall, commitLogOf, SETTLED_ON_THE_PASSING_ARM, SAVE_FAILED_AT_THE_TERMINAL_ARM } from './state.mjs';
|
|
10
10
|
|
|
11
11
|
/// `PAR-JS-13`: the returned record is `{op, watched, triggered}` — fresh on every call, never a view.
|
|
12
12
|
///
|
|
@@ -555,7 +555,13 @@ export function terminalArm(state, record) {
|
|
|
555
555
|
// receiver … A listener that is itself a store member is NOT supported"* — the package's own internal
|
|
556
556
|
// paths (this one and `registerOn`'s re-install) address the store they hold, and only a CALLER's call
|
|
557
557
|
// takes its receiver from `this` (`§1`).
|
|
558
|
-
|
|
558
|
+
// **⟶ AND THE COMMIT'S OWN LIST GOES WITH THE CALL — `D-53`, 2026-10-28.** A save that fails is a constraint
|
|
559
|
+
// violated at the write's LAST position, so its refusal must cross carrying the COMMIT's entries (the pass's
|
|
560
|
+
// `constraint-check` entries and, by the time the caller reads it, the kernel's one `outcome` entry with the
|
|
561
|
+
// save arm's own `KC-9` in `state`). **THE LIST IS READ OFF THE RECORD THE KERNEL BUILT** (`commitLogOf(record)` — `record[COMMIT_LOG]`,
|
|
562
|
+
// a symbol key on `CommitRecord`'s own identity — no member is added, `A117` (D6)), and a record carrying none
|
|
563
|
+
// is a record this package did not build, whose failure keeps the declared `[]`.
|
|
564
|
+
carryRefusal(() => commitFile(state.receiver, answer.op.opId), [encodeOpId(answer.op.opId)], commitLogOf(record));
|
|
559
565
|
} catch (saveFailure) {
|
|
560
566
|
// **THE FAILURE CARRIES THE VERY THROWABLE AND ITS OWN MARK** (`docs/specs/storeroom-js/surface.md §2.11` clause 9): the kernel's catch
|
|
561
567
|
// reads `SAVE_FAILED_AT_THE_TERMINAL_ARM` to tell a failed save from a body of the delivered set that
|
|
@@ -594,9 +600,17 @@ export function terminalArm(state, record) {
|
|
|
594
600
|
const triggeringAddress = answer === null || answer === undefined || answer.op === null || answer.op === undefined
|
|
595
601
|
? undefined
|
|
596
602
|
: answer.op.address;
|
|
597
|
-
//
|
|
598
|
-
//
|
|
599
|
-
|
|
603
|
+
// **⟶ AND THE ARM PERFORMS THE DELIVERY FOR A KERNEL-DRIVEN WRITE AND FOR NO OTHER ACT — 2026-10-29.** A
|
|
604
|
+
// `delete`'s delivery is its OWN MEMBER's (`D-49` declares that window the one whose check never ran, and a
|
|
605
|
+
// request raised there is the witness's and not a pass's); the record is the delete's, so this arm is
|
|
606
|
+
// reached for it — the `file`-tier save above is the arm's act on BOTH — and the residue's delivery is the
|
|
607
|
+
// member's. **THE FACT IS THE PACKAGE'S OWN STATE AND NEVER A MEMBER OF ANY RECORD**, and it is `'arm'` on
|
|
608
|
+
// every path that does not name another, so a write's delivery is exactly where it was.
|
|
609
|
+
if (state.legDelivery !== 'member') {
|
|
610
|
+
// `deliver` is THE SAME loop the post-verb window uses (`docs/specs/storeroom-js/surface.md §2.4` rules 1–3 read once, at both instants): ONE
|
|
611
|
+
// invocation per DISTINCT handle, and a handle with no registered function fires nothing silently.
|
|
612
|
+
deliver(state, triggered, triggeringAddress);
|
|
613
|
+
}
|
|
600
614
|
return undefined;
|
|
601
615
|
}
|
|
602
616
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// `D-13` (`docs/L1/kernel-subdivision.md` §1 part `9d`) — the pass: bytes moved from `bindings/js/src/constraint-kernel.mjs`; no logic changed.
|
|
2
|
-
import { KC, KC_TOKENS, SETTLED_ON_THE_PASSING_ARM, SAVE_FAILED_AT_THE_TERMINAL_ARM, TERMINAL_ARM, markBodyThrow, refuse, isKernelRefusal, pairSpelling, addressSpelling, sameAddress, kernelFor, append, appendOwn, ownMember, withdraw, landedOp, landedOpDefect, pairsAtAddress,
|
|
2
|
+
import { KC, KC_TOKENS, SETTLED_ON_THE_PASSING_ARM, SAVE_FAILED_AT_THE_TERMINAL_ARM, TERMINAL_ARM, markBodyThrow, throwableForm, refuse, isKernelRefusal, pairSpelling, addressSpelling, sameAddress, kernelFor, append, appendOwn, ownMember, withdraw, landedOp, landedOpDefect, pairsAtAddress, enterCommitFrame, leaveCommitFrame, commitLogInFlight, sealHandoff } from './kernel-foundations.mjs';
|
|
3
3
|
import { commitAttemptIdOf, terminal, close } from './kernel-terminal.mjs';
|
|
4
4
|
// ---------------------------------------------------------------------------------------------
|
|
5
5
|
// `K-3` `runAttempt(store, commit) -> AttemptReport`
|
|
@@ -37,6 +37,35 @@ const COMMIT_SCOPE = Symbol.for('provident-storeroom.commit-scope');
|
|
|
37
37
|
/// (`§1` item 2: `K-1`–`K-5` and no sixth name).
|
|
38
38
|
const RESTART_DRAIN = Symbol.for('provident-storeroom.restart-drain');
|
|
39
39
|
|
|
40
|
+
/// **`D-54` (b)'s SECOND SPELLING OF THE SAME `Symbol.for` KEY** — the entry writes the restarted check's
|
|
41
|
+
/// refusal onto the report under it (`constraints.mjs`'s `carryRestartRefusal`) and this module reads it back
|
|
42
|
+
/// so the failing arm can answer with the very value the terminal judgement built, exactly as the passing arm
|
|
43
|
+
/// reaches it through `constraintWrite`. **NEITHER SIDE IMPORTS THE OTHER** (`kernel-surface.md §1` item 1's
|
|
44
|
+
/// empty import footprint), the key is invisible to `Object.keys` and to `Object.getOwnPropertyNames`
|
|
45
|
+
/// (`A117` (D6)), and no kernel item is minted (`§1` item 2: `K-1`–`K-6` and no seventh name).
|
|
46
|
+
const RESTART_REFUSAL = Symbol.for('provident-storeroom.restart-refusal');
|
|
47
|
+
|
|
48
|
+
/// **⟶ `D-54` (b)'s COMPENSATION FLAG — the same `Symbol.for` key `constraints.mjs` spells.** The kernel's
|
|
49
|
+
/// terminal act composes the attempt's rollback THROUGH THE APP'S PUBLISHED `rollback` MEMBER
|
|
50
|
+
/// (`kernel-terminal.mjs`'s `composeRollback`), so that call would otherwise take a restart watch and raise a
|
|
51
|
+
/// request — a phantom the failing pass's drain would then judge, asking pairs at the state the compensation
|
|
52
|
+
/// had just restored to. **`D-42` declares the rule the flag keeps: *"a restart is only ever raised by a
|
|
53
|
+
/// consumer's own `rollback` member call."*** The flag stands on the kernel record for the duration of the one
|
|
54
|
+
/// call, is a symbol key (invisible to `Object.keys`/`Object.getOwnPropertyNames`, `A117` (D6)), and mints no
|
|
55
|
+
/// kernel item (`kernel-surface.md §1` item 2).
|
|
56
|
+
const COMPENSATING = Symbol.for('provident-storeroom.compensating-rollback');
|
|
57
|
+
|
|
58
|
+
/// **THE KERNEL'S ONE TERMINAL ACT, TAKEN WITH ITS COMPENSATION FLAGGED** — the wrapper every terminal call in
|
|
59
|
+
/// this module uses so the composition inside `terminal` is never mistaken for an action of the caller's.
|
|
60
|
+
function terminalComposed(kernel, attempt, status, message) {
|
|
61
|
+
kernel[COMPENSATING] = true;
|
|
62
|
+
try {
|
|
63
|
+
terminal(kernel, attempt, status, message);
|
|
64
|
+
} finally {
|
|
65
|
+
kernel[COMPENSATING] = false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
40
69
|
/// **⟶ ADDED 2026-10-27 — `D-46`'s NAME ON AN INVOCATION'S OWN ENTRY, AND IT IS THIS PASS'S ONE USE OF THE
|
|
41
70
|
/// SEAM'S SIXTH CHANNEL.** **THE RULING, THE ARCHITECT, VERBATIM: *"A constraint's repair needs to stay as part
|
|
42
71
|
/// of the same commit so that it can be tracked as part of the commit process … The original way of maintaining
|
|
@@ -69,6 +98,28 @@ function repairInCommit(store, commit, run) {
|
|
|
69
98
|
return run();
|
|
70
99
|
}
|
|
71
100
|
|
|
101
|
+
/// **⟶ AND THE CONSTRAINT BODY'S INVOCATION NAMES THE ATTEMPT'S COMMIT TOO — `D-53`, 2026-10-28.**
|
|
102
|
+
///
|
|
103
|
+
/// **THE RULING, VERBATIM: *"Constraints/Repairs should always use the same commit"*** (`strata/decisions.md` ·
|
|
104
|
+
/// `D-53`). **THE INVARIANT THIS FRAME NOW KEEPS IS `D-45`'s *"it should be opening a new commit by default of
|
|
105
|
+
/// entering at the surface"* READ THROUGH `D-53`'s LATER AND NARROWER ONE: a call that NAMES a commit JOINS it,
|
|
106
|
+
/// and a call that names none opens one — and the kernel names the attempt's commit at EVERY invocation of
|
|
107
|
+
/// caller code that belongs to the attempt, a constraint body's as well as a repair body's** (`D-46`'s device,
|
|
108
|
+
/// applied to the second kind of body). **SO A CONSTRAINT NEVER OPENS A COMMIT: the check it is invoked for is
|
|
109
|
+
/// already inside one (`D-44`'s scope) and this name is what makes its verb JOIN that window instead of opening
|
|
110
|
+
/// a second.** **THE LOG IS THE SAME FACT SEEN FROM THE OTHER SIDE**: the entries such a verb mints are the
|
|
111
|
+
/// attempt's own commit's entries, which is what `DEF-AK` measures — *"one inner refusal, two hosts"* — and what
|
|
112
|
+
/// `D-53` dissolved `D-52`'s merge question with (*"the crossed report IS that list"*).
|
|
113
|
+
///
|
|
114
|
+
/// **A LISTENER BODY STILL NAMES NOTHING, AND THAT IS THE INVARIANT AND NOT AN OMISSION**: it is invoked by the
|
|
115
|
+
/// ENTRY at the terminal arm, after the triggering commit has passed its constraints, so *"what the listener
|
|
116
|
+
/// does is a NEW QUESTION and must not inherit the old verdict"* — its own commit, its own list.
|
|
117
|
+
function constraintInCommit(store, commit, run) {
|
|
118
|
+
const channel = store !== null && typeof store === 'object' ? store[EXTERNAL_CALL] : undefined;
|
|
119
|
+
if (typeof channel === 'function') return channel(run, commit);
|
|
120
|
+
return run();
|
|
121
|
+
}
|
|
122
|
+
|
|
72
123
|
export function runAttempt(store, commitRecord) {
|
|
73
124
|
// THE SEAM, READ BEFORE ANY STATE MOVES: **a store this package did not build carries no such channel, so it
|
|
74
125
|
// is not this package's store and no pass of this kernel may run against it.** The refusal is thrown BEFORE
|
|
@@ -91,12 +142,61 @@ export function runAttempt(store, commitRecord) {
|
|
|
91
142
|
// open — a direct `K-2`/`K-3` drive, `D-44`'s window. **NO COUNT IS MINTED EITHER WAY**: the channel is
|
|
92
143
|
// `openCommit`/`closeCommit` composed, and the count moves only where this call's own opening is the one that
|
|
93
144
|
// took it.
|
|
145
|
+
// **⟶ AND A FAILING PASS'S TERMINAL STATE IS STILL A JUDGEMENT — `D-54` (b), 2026-10-28, MEASURED.** The bytes
|
|
146
|
+
// above reached the drain only where the pass ANSWERED A REPORT, so a pass that ended by throwing — a repair
|
|
147
|
+
// body that reversed the store had then broken the attempt's own re-run, or a delete's pass whose pair
|
|
148
|
+
// refused after its delivery's reversal — left the request its bodies raised standing, unjudged, with its
|
|
149
|
+
// effect in the store. **THE REQUEST IS CARRIED TO THE PASS'S TERMINAL JUDGEMENT**: the terminal act has run
|
|
150
|
+
// and the attempt is closed, so the state the pass left is the state the restarted check is asked at, and the
|
|
151
|
+
// drain runs here, inside the same scope, exactly as it does on the passing arm. **THE FAILING PASS'S OWN
|
|
152
|
+
// ANSWER IS NOT RE-SHAPED**: where the restarted check passes, or where the throwable is not the kernel's own
|
|
153
|
+
// (a caller body's value, a store refusal — each of which must cross as itself), the pass's throwable crosses
|
|
154
|
+
// unchanged. Only a KERNEL refusal — the pass's own terminal arm — is superseded by the refusal the restarted
|
|
155
|
+
// check built at that same terminal state, because that check's verdict is the state the pass left.
|
|
94
156
|
return scope(() => {
|
|
95
|
-
|
|
96
|
-
|
|
157
|
+
let report;
|
|
158
|
+
try {
|
|
159
|
+
report = passInCommitScope(store, commitRecord);
|
|
160
|
+
} catch (thrown) {
|
|
161
|
+
return drainFailingPass(store, commitRecord, thrown);
|
|
162
|
+
}
|
|
163
|
+
// **⟶ AND THE RECORD IS SEALED AT THE HANDOFF — `D-55` item 6, `DEF-AO`, 2026-10-28.** The drain above is
|
|
164
|
+
// the LAST act of closing out (it amends the report's own `outcome` and appends the refusal's entry to the
|
|
165
|
+
// report's list BEFORE this line), so what the seal freezes is the record the driver receives and no record
|
|
166
|
+
// in flight: `report.log` and the report are `Object.freeze`d, and a later act can neither append to the
|
|
167
|
+
// commit's list nor re-member the report. **A PASSING ARM IS SEALED TOO** — its list is handed off once.
|
|
168
|
+
return sealHandoff(drainRestart(store, report), commitLogInFlight(kernelFor(store)) !== null);
|
|
97
169
|
}, commitRecord);
|
|
98
170
|
}
|
|
99
171
|
|
|
172
|
+
/// **THE FAILING PASS'S DRAIN — `D-54` (b)'s ONE NEW CALL SITE.**
|
|
173
|
+
///
|
|
174
|
+
/// **WHY THE REPORT IS READ AND NOT BUILT**: the pass's terminal act (`kernel-terminal.mjs`'s `terminal`) has
|
|
175
|
+
/// already answered the attempt's ONE five-member report and placed it in the kernel's closed map before it
|
|
176
|
+
/// throws, so the log the drain re-appends onto is the attempt's own list and no second report is minted
|
|
177
|
+
/// (`A117` (D6): no member is added to any record). **A THROWABLE THAT STOOD BEFORE ANY TERMINAL ACT — `KC-2`,
|
|
178
|
+
/// a re-entrant `KC-7`, a store refusal at `K-2` — has no closed report and no request of this pass's window
|
|
179
|
+
/// either**, so it crosses unchanged and the drain is not reached: no pass ran.
|
|
180
|
+
///
|
|
181
|
+
/// **THE ONE PRECEDENCE RULE, STATED ONCE**: a restarted check's refusal supersedes the pass's answer only
|
|
182
|
+
/// where that answer is the KERNEL's own (a `KC`-tokened refusal, `isKernelRefusal`). A constraint body's
|
|
183
|
+
/// throwable is the caller's and crosses as itself (`fail-surface.md §1.1` item `5`), a store verb's refusal
|
|
184
|
+
/// crosses verbatim (`§1.2` item `2`), and neither is re-shaped by a later check's verdict — the request is
|
|
185
|
+
/// still judged and the store still restored by that judgement's own compensating act.
|
|
186
|
+
function drainFailingPass(store, commitRecord, thrown) {
|
|
187
|
+
const closed = kernelFor(store).closed.get(commitAttemptIdOf(commitRecord));
|
|
188
|
+
if (closed === undefined) throw thrown;
|
|
189
|
+
const answered = drainRestart(store, closed);
|
|
190
|
+
// **⟶ THE FAILING ARM'S RECORD IS SEALED AT ITS OWN HANDOFF — `DEF-AO`.** The drain has already amended the
|
|
191
|
+
// closed report if the restarted check refused, so the seal stands before this arm picks which value crosses:
|
|
192
|
+
// the restarted refusal and the pass's own throwable both carry the SAME frozen list (`D-53`), and neither
|
|
193
|
+
// can be appended to after this line.
|
|
194
|
+
sealHandoff(answered, commitLogInFlight(kernelFor(store)) !== null);
|
|
195
|
+
const restarted = answered !== null && typeof answered === 'object' ? answered[RESTART_REFUSAL] : undefined;
|
|
196
|
+
if (restarted !== undefined && isKernelRefusal(thrown) === true) throw restarted;
|
|
197
|
+
throw thrown;
|
|
198
|
+
}
|
|
199
|
+
|
|
100
200
|
/// **THE DRAIN, TAKEN INSIDE THE SCOPE THE PASS JUST ENDED IN.** It hands the store **the report the pass
|
|
101
201
|
/// answered with** and answers the report the kernel returns: unchanged where no request stood or the
|
|
102
202
|
/// restarted check passed, and amended — `outcome` `'failed'` and the refusal's entry in the log — where the
|
|
@@ -152,7 +252,7 @@ function passInCommitScope(store, commitRecord) {
|
|
|
152
252
|
if (terminalArm !== null) {
|
|
153
253
|
// A FAILING LANDING: the arm's own terminal act, its per-op rollback composition, and the throw
|
|
154
254
|
// of `fail-surface.md §1.1`'s form carrying the log.
|
|
155
|
-
|
|
255
|
+
terminalComposed(kernel, attempt, terminalArm.status, terminalArm.message);
|
|
156
256
|
// **⟶ INSTANT (b) ON THE FAILING ARM, AND IT PRECEDES THE REFUSAL** (`docs/decisions.md` · `A116`
|
|
157
257
|
// (D1); `surface.md §2.4` item 9's table row (b): *"AT THE PASS'S TERMINAL ARM … after the last
|
|
158
258
|
// constraint of the attempt has been evaluated and before `runAttempt` returns to the calling
|
|
@@ -239,7 +339,16 @@ function passInCommitScope(store, commitRecord) {
|
|
|
239
339
|
// `'ok'`; where the failed save's own rollback took it the store answers `JournalOpUnknown` and the
|
|
240
340
|
// composition's floor reads `KC-8` in the ONE `outcome` entry (item 5 (b); item 6 (a)).
|
|
241
341
|
attempt.checkpoint = null;
|
|
242
|
-
|
|
342
|
+
// **⟶ AND THE ARM'S TOKEN IS THE SET'S NINTH MEMBER, `KC-9` — `D-53`'s THIRD RULING, 2026-10-28: *"Open the
|
|
343
|
+
// token set"*.** **`D-52` MEASURED THE CONTRADICTION THIS CLOSES**: *"a constraint refusal crosses
|
|
344
|
+
// `ConstraintPassRefused` with terminal `state: 'KC-3'`; and with an in-body reversal meeting the floor,
|
|
345
|
+
// `ConstraintPassRefused` with terminal `KC-8`; a save failure crosses `FileCommitFailed` with `log: []`, and
|
|
346
|
+
// the attempt's own log reads `KC-8` — the same token a passing-pair run carries. **SO `KC-8` CROSSES AS BOTH
|
|
347
|
+
// STATUSES.**"* **THE SAVE ARM THEREFORE GETS A TOKEN OF ITS OWN**, so that a save failure and a constraint
|
|
348
|
+
// refusal cross with different statuses AND each is derivable from the log's terminal state — **and
|
|
349
|
+
// `kernel-terminal.mjs`'s precedence clause is what keeps this token through the floor**, which is otherwise
|
|
350
|
+
// `KC-8` on both arms and would put the contradiction back.
|
|
351
|
+
terminalComposed(kernel, attempt, KC.saveFailed,
|
|
243
352
|
typeof saveFailure.message === 'string'
|
|
244
353
|
? saveFailure.message
|
|
245
354
|
: `the attempt's own save at ${addressSpelling(attempt.address)} failed`);
|
|
@@ -257,7 +366,10 @@ function passInCommitScope(store, commitRecord) {
|
|
|
257
366
|
// stand in one log). **AND NOTHING IS APPENDED TO THIS LOG AFTER IT**: the delivered set's bodies ran
|
|
258
367
|
// before this line and reach this attempt's log by no act (`§2.7` item 6), the record this attempt's
|
|
259
368
|
// report carries being the same list this line closes.
|
|
260
|
-
|
|
369
|
+
// **⟶ AND ITS ITERATION IS `{ pair: null, op }` — the `commit` entry names NO PAIR and the attempt's LAST OP**
|
|
370
|
+
// (`kernel-surface.md §2.1` item 3's `LogKind` table; `D-53`'s first ruling, which is what the iteration position
|
|
371
|
+
// carries).
|
|
372
|
+
append(attempt, 'commit', { pair: null, op: attempt.ops[attempt.ops.length - 1] },
|
|
261
373
|
`every constraint registered at ${addressSpelling(attempt.address)} passed; the commit stands`);
|
|
262
374
|
return closed;
|
|
263
375
|
}
|
|
@@ -343,14 +455,35 @@ function evaluate(kernel, attempt, landing) {
|
|
|
343
455
|
// alike — and NOT the union of the store's prefix-selected addresses"), WHILE THE OP EVERY EVALUATION
|
|
344
456
|
// CARRIES IS THE LANDING'S OWN — the repair's op where a repair's edit landed, and the attempt's first
|
|
345
457
|
// write where the pass is the commit's own landing.
|
|
346
|
-
//
|
|
458
|
+
// **⟶ AND THE SET THAT ADDRESS MATERIALISES IS NOW A PREFIX SET, 2026-10-29 (`D-56`).** `RCA-8(g)`
|
|
459
|
+
// ANNOTATE-BESIDE: **the quotation above stands BYTE-FOR-BYTE as `attempt-lifecycle.md §2.4` item 5 (iv)'s
|
|
460
|
+
// EXACT-ADDRESS rule — the clause `D-56` names by number and SUPERSEDES**; the architect's own sentence is
|
|
461
|
+
// *"A listener/constraint should fire when the descendants of its targeted address node change, because the
|
|
462
|
+
// descendants become part of the object that is read from that address"*, and what it changes here is the
|
|
463
|
+
// PREDICATE `pairsAtAddress` applies — **the pairs whose own address is a PREFIX of the attempt's, equality
|
|
464
|
+
// included.** **NO OTHER LINE OF THIS FRAME MOVES**: the address is still the attempt's, the landing's op is
|
|
465
|
+
// still what every evaluation carries, and the set is still ONE SNAPSHOT taken at this instant.
|
|
466
|
+
// THE PASS'S OWN EVALUATED SET IS FIXED WHEN THE PASS BEGINS — a SNAPSHOT of the registry's rows AT OR ABOVE
|
|
347
467
|
// the attempt's address AT THAT INSTANT, and never a live view of the registry this pass reads again:
|
|
348
468
|
// "a PASS's evaluated set is FIXED WHEN THE PASS BEGINS — it is every pair registered at the attempt's
|
|
349
469
|
// address AT THAT INSTANT, each evaluated once in clause (ii)'s order", so "A `K-1` THAT RETURNS
|
|
350
470
|
// DURING A PASS APPENDS A PAIR TO THE REGISTRY WITHOUT APPENDING ANY ENTRY TO THAT PASS AND WITHOUT
|
|
351
471
|
// BEING EVALUATED BY IT: the new pair enters the NEXT pass's set" (`attempt-lifecycle.md §2.4` item 5
|
|
352
|
-
// (iv); `CX-12
|
|
472
|
+
// (iv); `CX-12`, which `D-56` defers to and does NOT move). **THE SNAPSHOT IS MATERIALISED ONCE PER RUN AND
|
|
473
|
+
// READ BY THE WHOLE RUN** — the loop below, the repair arm's `list` and `releasePending`'s check-off all read
|
|
474
|
+
// THIS ONE array — **and it is ALSO the set the layer (a) delivery of this run is read over.**
|
|
353
475
|
const list = pairsAtAddress(kernel, attempt.address);
|
|
476
|
+
// **⟶ AND THE COMMIT THE INVOCATIONS OF THIS RUN NAME — `D-55` ITEM 3's DELETE-SHAPED ATTEMPT, 2026-10-29.**
|
|
477
|
+
// **A WRITE'S ATTEMPT NAMES ITS `CommitRecord`** (`attempt.record`, the object `K-2` built and adopted), and
|
|
478
|
+
// every verb a body calls under it JOINS that commit (`D-46`). **A DELETE'S ATTEMPT HAS NO `CommitRecord`** —
|
|
479
|
+
// it lands no write, so there is no adoption, no residue and no save — **and it still owes the same
|
|
480
|
+
// invariant**: `D-53`'s *"Constraints/Repairs should always use the same commit"* is not a rule about records
|
|
481
|
+
// but about the COMMIT, and a body's write under a delete's pass that named nothing would OPEN a second commit
|
|
482
|
+
// and start a second list. **SO THE ATTEMPT CARRIES ITS COMMIT'S NAME** (`kernel-commit.mjs`'s
|
|
483
|
+
// `commitRemoval` sets `attempt.name` to the one member `commitAttemptIdOf` reads) **and this frame hands THE
|
|
484
|
+
// NAME where a record exists and THE RECORD where it does** — one expression, and on the write path it is the
|
|
485
|
+
// very object it always was, so no byte of the write's own invocation moves.
|
|
486
|
+
const commitName = attempt.record === undefined ? attempt.name : attempt.record;
|
|
354
487
|
// THE ATOMIC LANDING EVALUATION'S OWN ARM-TAKING IS `attempt-lifecycle.md §2.4` item 4's arms, read
|
|
355
488
|
// over THE PAIR THAT FAILED AT THAT OP (`kernel-surface.md §2.3` item 1; `§2.4`: `KC-3` where that pair
|
|
356
489
|
// is NOT in `ran` before this run and no repair is registered for it; `KC-6` where it IS in `ran` and
|
|
@@ -383,24 +516,40 @@ function evaluate(kernel, attempt, landing) {
|
|
|
383
516
|
// THE ENTRY IS OPENED BEFORE THE BODY RUNS, so a body that reads the record's own log mid-flight
|
|
384
517
|
// reads its own evaluation's entry — and it is WITHDRAWN where the body returns nothing
|
|
385
518
|
// (`kernel-surface.md §2.5` item 1; `PAR-C-6`).
|
|
386
|
-
|
|
519
|
+
// **⟶ AND IT IS NAMED BY THE ITERATION — the pair AND the op, one identity — `D-53`'s FIRST RULING**
|
|
520
|
+
// (`kernel-foundations.mjs`'s `append`; `D-52`'s rule 1: *"an entry carries the PAIR identity and the OP
|
|
521
|
+
// identity together … they are one identity"*).
|
|
522
|
+
append(attempt, 'constraint-check', { pair, op }, `the evaluation of ${pair.id}`);
|
|
387
523
|
const check = attempt.log[attempt.log.length - 1];
|
|
388
524
|
let outcome;
|
|
525
|
+
// **⟶ AND THE FRAME: every list the body's own verbs append to between these two lines is THIS commit's
|
|
526
|
+
// list** (`D-53`'s first invariant). The frame is pushed for exactly the invocation and popped in a
|
|
527
|
+
// `finally`, so a throwable leaves no frame standing and no later write of this commit inherits a frame it
|
|
528
|
+
// does not own.
|
|
529
|
+
enterCommitFrame(kernel, attempt.log);
|
|
389
530
|
try {
|
|
390
|
-
// **⟶ AND THE BODY IS INVOKED WITH
|
|
391
|
-
//
|
|
392
|
-
//
|
|
393
|
-
//
|
|
394
|
-
//
|
|
395
|
-
//
|
|
396
|
-
|
|
397
|
-
// ordinary write still opens ONE commit and a callback's verb is still an act of its own.
|
|
398
|
-
outcome = externalCall(attempt.store, () => pair.constraint(context));
|
|
531
|
+
// **⟶ AND THE BODY IS INVOKED WITH THE ATTEMPT'S COMMIT NAMED, 2026-10-28 (`D-53`).** `D-45` invoked it
|
|
532
|
+
// with nothing named and `D-46` narrowed that for repairs alone; **`D-53` states the invariant both halves
|
|
533
|
+
// obey: a CONSTRAINT never opens a commit and a REPAIR never opens one, while a listener's write always
|
|
534
|
+
// does.** The name is an INVOCATION's and nothing else's: it is set before the call and restored after it,
|
|
535
|
+
// on the throwing arm too, so an ordinary write still opens ONE commit and a callback's verb is still an
|
|
536
|
+
// act of its own.
|
|
537
|
+
outcome = constraintInCommit(attempt.store, commitName, () => pair.constraint(context));
|
|
399
538
|
} catch (body) {
|
|
400
539
|
// A body that threw returned nothing, so no `constraint-check` entry stands and the attempt is
|
|
401
540
|
// closed (`PAR-C-6`; `NX-2`; `composition-and-states.md §2.7` item 13).
|
|
402
541
|
withdraw(attempt, check);
|
|
403
|
-
|
|
542
|
+
// **⟶ AND THE THROWABLE'S OWN FORM ENTERS THE COMMIT'S LOG — `D-55` ITEM 1, `DEF-AK`, 2026-10-28.**
|
|
543
|
+
// The architect, verbatim: *"Include a thrown message in the message log. Obviously."* **THE ENTRY IS
|
|
544
|
+
// THE ONE THE TERMINAL ACT ALREADY APPENDS**: this arm closes the attempt with its ONE `outcome` entry
|
|
545
|
+
// (`composition-and-states.md §2.7` item 13), and NO second entry and NO fifth `kind` is minted —
|
|
546
|
+
// `constraint-check` was WITHDRAWN above and must not come back (`fail-surface.md §1.1` item 1 (b),
|
|
547
|
+
// which the kernel-level cells assert as *"NO entry stands for the pair whose body returned nothing"*).
|
|
548
|
+
// **SO THE TERMINAL ENTRY'S SENTENCE CARRIES THE FORM** (`throwableForm`: the string's own text, the
|
|
549
|
+
// object's own `message` member, or the kind of value it was, read off own members only), and the
|
|
550
|
+
// closed report's list — the list the crossing hands the caller — holds it at that entry's `seq`.
|
|
551
|
+
terminalComposed(kernel, attempt, null, `the constraint ${pair.id} threw; the attempt is closed — the `
|
|
552
|
+
+ `value it threw was ${throwableForm(body)}`);
|
|
404
553
|
// **⟶ AND THE VALUE IS MARKED HERE, BY THE FRAME THAT CAUGHT IT FROM THE BODY — `DEF-S`, 2026-10-26,
|
|
405
554
|
// on the architect's ruling *"Expand the returned error set for both S/N"*.** The mark is what the
|
|
406
555
|
// entry's `constraintCrossing` converts on, and an UNMARKED value still crosses as itself
|
|
@@ -409,6 +558,10 @@ function evaluate(kernel, attempt, landing) {
|
|
|
409
558
|
// `kernel-foundations.mjs`). The throwable's own identity is unmoved at THIS layer: a kernel-level
|
|
410
559
|
// caller still meets the very value the body threw.
|
|
411
560
|
throw markBodyThrow(body, attempt.address, attempt.log);
|
|
561
|
+
} finally {
|
|
562
|
+
// THE FRAME GOES WITH THE INVOCATION, ON EVERY ARM (`D-53`): a frame left standing would make the NEXT
|
|
563
|
+
// write of this store join a commit it is not inside.
|
|
564
|
+
leaveCommitFrame(kernel);
|
|
412
565
|
}
|
|
413
566
|
|
|
414
567
|
// THE CONSTRAINT'S OWN OUTCOME — A CLOSED THREE-ARM SET (`PAR-C-5`). A value outside the three
|
|
@@ -487,7 +640,7 @@ function evaluate(kernel, attempt, landing) {
|
|
|
487
640
|
// INSTANT IT IS APPENDED — "THE OP THE REPAIR PRODUCED WHERE IT PRODUCED ONE, ELSE THE OP IT WAS
|
|
488
641
|
// INVOKED FOR" (`kernel-surface.md §2.5` item 1's `repair-run` row) — so on EVERY arm the entry
|
|
489
642
|
// names THE OP THIS EVALUATION CARRIED, and only the arm that produced an op rewrites it below.
|
|
490
|
-
append(attempt, 'repair-run', pair
|
|
643
|
+
append(attempt, 'repair-run', { pair, op }, 'the pair\'s repair was attempted');
|
|
491
644
|
const entry = attempt.log[attempt.log.length - 1];
|
|
492
645
|
let result;
|
|
493
646
|
const repairContext = {
|
|
@@ -529,7 +682,10 @@ function evaluate(kernel, attempt, landing) {
|
|
|
529
682
|
// so a repair that supplies it at `write`'s fourth position names the same commit by its own hand, and
|
|
530
683
|
// the two spellings cannot disagree: **the entry's position wins where it is supplied, and this name is
|
|
531
684
|
// the fallback where it is not** (`state.mjs`'s `openCommit`).
|
|
532
|
-
|
|
685
|
+
// **⟶ AND THE FRAME STANDS FOR THIS INVOCATION TOO (`D-53`'s first invariant): the repair's own verbs
|
|
686
|
+
// append to the attempt's list, and the frame is what makes `K-2` join rather than open.**
|
|
687
|
+
enterCommitFrame(kernel, attempt.log);
|
|
688
|
+
result = repairInCommit(attempt.store, commitName, () => repair(repairContext));
|
|
533
689
|
} catch (body) {
|
|
534
690
|
// THE REPAIR-RUN ENTRY IS APPENDED BEFORE THE THROW, and the attempt's outcome entry carries
|
|
535
691
|
// `KC-4` (`ck_states_a_repair_body_that_throws_reaches_the_caller_unconverted`).
|
|
@@ -575,7 +731,7 @@ function evaluate(kernel, attempt, landing) {
|
|
|
575
731
|
if (storeCode !== null) {
|
|
576
732
|
entry.message = `the repair ${pair.id} was attempted and the store refused its own edit — the `
|
|
577
733
|
+ `store's answer is ${storeCode}`;
|
|
578
|
-
|
|
734
|
+
terminalComposed(kernel, attempt, KC.repairFailed, entry.message);
|
|
579
735
|
// **⟶ AND THE FORM THAT CROSSES TO THE CALLER IS THE KERNEL'S OWN** (`kernel-surface.md §2.3`
|
|
580
736
|
// item 2 (iii): the attempt *"moves to `FAILING` with `KC-4`"*, and *"the thrown form's `status`
|
|
581
737
|
// is NEVER a store member"*) — **the very form the FAILING arm above throws**, carrying the
|
|
@@ -584,8 +740,10 @@ function evaluate(kernel, attempt, landing) {
|
|
|
584
740
|
// body's own arm and this conversion is the refused-verb's.
|
|
585
741
|
refuse(attempt.throwState, attempt.throwMessage, attempt.log);
|
|
586
742
|
}
|
|
587
|
-
|
|
743
|
+
terminalComposed(kernel, attempt, KC.repairFailed, `the repair ${pair.id} threw; the attempt is closed`);
|
|
588
744
|
throw body;
|
|
745
|
+
} finally {
|
|
746
|
+
leaveCommitFrame(kernel);
|
|
589
747
|
}
|
|
590
748
|
|
|
591
749
|
// THE REPAIR'S OWN RESULT — A CLOSED TWO-ARM SET (`PAR-C-8`), WHOSE SUCCESS ARM'S THIRD MEMBER
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// `D-13` (`docs/L1/kernel-subdivision.md` §1 part `9c`) — the commit act: bytes moved from `bindings/js/src/constraint-kernel.mjs`; no logic changed.
|
|
2
|
-
import { KC, refuse, inDomainAddress, kernelFor, attemptHeldAt, appendOwn, addressSpelling } from './kernel-foundations.mjs';
|
|
2
|
+
import { KC, refuse, inDomainAddress, kernelFor, attemptHeldAt, appendOwn, addressSpelling, commitLogInFlight, COMMIT_LOG } from './kernel-foundations.mjs';
|
|
3
3
|
// ---------------------------------------------------------------------------------------------
|
|
4
4
|
// `K-2` `commit(store, address, tier, value) -> CommitRecord`
|
|
5
5
|
// ---------------------------------------------------------------------------------------------
|
|
@@ -53,6 +53,17 @@ export function commit(store, address, tier, value) {
|
|
|
53
53
|
// `appendOwn`), and NO ANSWER MOVES: the same segments, the same order, a FRESH array as before.
|
|
54
54
|
const addressCopy = [];
|
|
55
55
|
for (let i = 0; i < address.length; i += 1) appendOwn(addressCopy, address[i]);
|
|
56
|
+
// **⟶ AND THE ATTEMPT'S LOG IS THE COMMIT'S LOG — `D-53`, 2026-10-28.** A write the kernel reaches from inside
|
|
57
|
+
// an invocation it made of caller code that BELONGS TO AN ATTEMPT (a constraint body's verb at a landing, a
|
|
58
|
+
// repair body's write, a registration's body) is part of that attempt's commit, so it JOINS that commit's one
|
|
59
|
+
// list; a write reached with no such frame standing — a caller's own write, and a LISTENER BODY's write, which
|
|
60
|
+
// the entry invokes at the terminal arm — OPENS a commit and starts a fresh list, because *"the triggering
|
|
61
|
+
// commit already passed constraints"* and what the listener does now is a new question (`D-53`).
|
|
62
|
+
// **ONE LIST PER COMMIT AND NO MERGE**: the entries a nested write mints are this list's entries, their `seq`
|
|
63
|
+
// is this list's ordinal, and the crossed report of the enclosing refusal IS this list (`D-52`'s rule 2 is
|
|
64
|
+
// dissolved rather than answered — there are not two lists to reconcile).
|
|
65
|
+
const joined = commitLogInFlight(kernel);
|
|
66
|
+
const commitLog = joined === null ? [] : joined;
|
|
56
67
|
const attempt = {
|
|
57
68
|
ref: { id: `attempt-${kernel.attempts}` },
|
|
58
69
|
store,
|
|
@@ -65,7 +76,8 @@ export function commit(store, address, tier, value) {
|
|
|
65
76
|
// reads `triggered` as the store's returned set VERBATIM).
|
|
66
77
|
write: null,
|
|
67
78
|
ops: [],
|
|
68
|
-
|
|
79
|
+
// THE COMMIT'S OWN LIST, BY REFERENCE (`D-53`): the attempt holds a reference to it and mints no second one.
|
|
80
|
+
log: commitLog,
|
|
69
81
|
ran: [],
|
|
70
82
|
appliedRepairs: [],
|
|
71
83
|
rollback: [],
|
|
@@ -111,6 +123,18 @@ export function commit(store, address, tier, value) {
|
|
|
111
123
|
pending: [],
|
|
112
124
|
};
|
|
113
125
|
attempt.record = record;
|
|
126
|
+
// **⟶ AND THE LOG TRAVELS ON THE COMMIT'S OWN RECORD, UNDER A SYMBOL KEY — `D-53`.** The record is the
|
|
127
|
+
// commit's JS identity: the fourth position names it, the entry adopts it, and the terminal arm holds it when
|
|
128
|
+
// it must tell a failed save's crossing WHICH LOG the commit's verdict stands in (`delivery.mjs`'s save arm
|
|
129
|
+
// reads it through `state.mjs`'s `commitLogOf`, which spells the same key). **NO MEMBER IS ADDED**: `Object.keys` and
|
|
130
|
+
// `Object.getOwnPropertyNames` read past a symbol (`A117` (D6)), so `CommitRecord` keeps its four members and
|
|
131
|
+
// every census of it moves by nothing.
|
|
132
|
+
Object.defineProperty(record, COMMIT_LOG, {
|
|
133
|
+
value: commitLog,
|
|
134
|
+
enumerable: false,
|
|
135
|
+
writable: false,
|
|
136
|
+
configurable: true,
|
|
137
|
+
});
|
|
114
138
|
// **⟶ INSTANT (a)'S SEAM CALL IS WITHDRAWN, 2026-10-18** (`docs/specs/storeroom-constraints/kernel-surface.md
|
|
115
139
|
// §2.1` item 2's clause of that date: *"the call of `settle(record)` THIS ITEM MAKES AT INSTANT (a) … IS
|
|
116
140
|
// WITHDRAWN"*). **WITH ONE ACTOR THERE IS NOTHING TO WITHHOLD**: the record is built and complete BEFORE the
|
|
@@ -164,3 +188,168 @@ export function commit(store, address, tier, value) {
|
|
|
164
188
|
return record;
|
|
165
189
|
}
|
|
166
190
|
|
|
191
|
+
// ---------------------------------------------------------------------------------------------
|
|
192
|
+
// **⟶ ADDED 2026-10-29 — `commitRemoval`: THE DELETE-SHAPED COMMIT ACT. `D-55` ITEM 3, `DEF-X`.**
|
|
193
|
+
//
|
|
194
|
+
// **THE RULING, THE ARCHITECT, VERBATIM: *"A delete is an editing verb and must pass constraints. This includes
|
|
195
|
+
// all of the relevant commit and message logic."*** (`strata/decisions.md` · `D-55` item `3`). **THE MEASURED
|
|
196
|
+
// OBSTACLE IT ANSWERS WAS PRINTED, NOT ASSUMED**: a `delete` opens its own commit window and reaches the
|
|
197
|
+
// addon's `delete` directly — **no `K-2`, no `K-3`, no log and no terminal entry** — and **the only pass shape
|
|
198
|
+
// the artefact had (`K-2` then `K-3`) LANDS A WRITE FIRST** (`storeAfter = {"c":2}`), so any pass driven
|
|
199
|
+
// through it judges a state the delete is not in. **SO THE DELETE GETS AN ATTEMPT OF ITS OWN KIND, AND THIS IS
|
|
200
|
+
// IT** — the commit act's remove-shaped sibling, and NOT a re-used `K-2`.
|
|
201
|
+
//
|
|
202
|
+
// **IT OPENS LIKE ANY OTHER, AND THE TWO THINGS IT SHARES WITH `K-2` ARE THE TWO THAT MATTER:**
|
|
203
|
+
// * **`D-44` IS KEPT BY THE CALLER AND RE-CHECKED HERE**: the attempt is opened inside the delete's own
|
|
204
|
+
// commit window (the member opens it before this act is reached, `index.mjs`'s `delete`), so no check this
|
|
205
|
+
// pass runs stands outside one — and a store this package did not build carries no commit scope at all, so
|
|
206
|
+
// `runAttempt` fails closed exactly as it does for a write.
|
|
207
|
+
// * **`D-53` IS KEPT BY THE SAME READ `K-2` TAKES**: `commitLogInFlight` answers the enclosing invocation's
|
|
208
|
+
// list where this delete was called from caller code that BELONGS TO an attempt (a constraint body's
|
|
209
|
+
// `delete`, a repair's), and `null` at a consumer's own call. **ONE LIST PER COMMIT, AND A DELETE'S ENTRIES
|
|
210
|
+
// JOIN IT** — there is no second list and no merge.
|
|
211
|
+
//
|
|
212
|
+
// **WHAT IT DOES NOT DO IS LAND A WRITE.** `K-2` calls the store's `write`. **This act mints an `AttemptRecord`
|
|
213
|
+
// of kind `delete` and calls THE STORE'S OWN LEG THE CALLER HANDS IT** — the addon's `delete`, already crossed
|
|
214
|
+
// by the entry — so **the state the attempt is judged at is the state the delete LEFT and never a state a probe
|
|
215
|
+
// wrote.** The act's own answer (`removal`) is the delete's declared receipt: its `op` is the DELETE's journal
|
|
216
|
+
// op and so THE ATTEMPT'S ONE LANDING (`attempt.ops`), which is what the pass's context carries and what the
|
|
217
|
+
// failing arm's composition rolls back; its `triggered` set is the store's own returned set, kept on
|
|
218
|
+
// `attempt.write` for the terminal act's discard rule exactly as a failed write's is.
|
|
219
|
+
//
|
|
220
|
+
// **⟶ AND IT MINTS THE `CommitRecord` TOO, 2026-10-29 — THE FOUR MEMBERS, THE SYMBOL-KEYED LOG, AND THE ONE
|
|
221
|
+
// IDENTITY THE WHOLE COMMIT'S MACHINERY IS KEYED BY.** The `DEF-X` build measured the four residuals this
|
|
222
|
+
// closes and printed them; each is a `K-2` behaviour that follows from the record and from nothing else:
|
|
223
|
+
// * **ADOPTION** — the record is what `K-2` hands the store's own verb at its fourth position, and what the
|
|
224
|
+
// entry holds so that the TERMINAL ARM performs the delivery and the save. A delete has no fourth position
|
|
225
|
+
// (its declared arity is `delete(address, tier)`), so the entry adopts the record it holds the same way it
|
|
226
|
+
// adopts a write's: it stands the delete's own returned receipt in the leg slot the terminal arm reads
|
|
227
|
+
// (`index.mjs`'s `delete`), and the RECORD is what `settleArm` hands that arm.
|
|
228
|
+
// * **THE `pending` RESIDUE** — written exactly as `K-2` writes it: the returned set WHOLE at this instant,
|
|
229
|
+
// and a handle leaves it only by its own pair's check-off (`releasePending`) or by the failing arm's
|
|
230
|
+
// discard (`terminal`). **NO SIFT**: the delete's own returned set is carried, member for member.
|
|
231
|
+
// * **THE `file`-TIER SAVE** — the terminal arm's save is gated on the record this act mints
|
|
232
|
+
// (`SETTLED_ON_THE_PASSING_ARM`, placed by the passing arm) and on the leg the entry adopted, so a
|
|
233
|
+
// `file`-tier delete SAVES its own op exactly as a `file`-tier write saves its own.
|
|
234
|
+
// * **`K-4`/`K-5` BY REF** — the record carries `attempt`, the `AttemptRef` those two items accept, so the
|
|
235
|
+
// delete's log and report are answerable after a PASSING delete and not only from a refusal's log.
|
|
236
|
+
// **THE RECORD'S FOUR MEMBERS AND ITS SYMBOL-KEYED LOG ARE `K-2`'S OWN, SPELLED THE SAME WAY**: the log is
|
|
237
|
+
// defined with `Object.defineProperty` under `COMMIT_LOG` and is not a fifth member (`A117` (D6)), so a census
|
|
238
|
+
// of any record moves by nothing.
|
|
239
|
+
//
|
|
240
|
+
// **THE `D-3` ARM IS KEPT AND A HELD ADDRESS IS JOINED RATHER THAN REFUSED** (the ground is printed at the act
|
|
241
|
+
// itself and it is a measurement, not a preference: a repair has no fourth position to name its commit at, so
|
|
242
|
+
// a `KC-7` here would make a lawful repair's `delete` unlawful):
|
|
243
|
+
// * **A REFUSED STORE VERB LEAVES NO ATTEMPT** (`D-3`'s neighbour): the addon's own refusal crosses back
|
|
244
|
+
// unchanged, and because the attempt is placed in `kernel.live` only AFTER the act answered an op, a
|
|
245
|
+
// refused delete holds nothing and closes nothing — `K-2`'s own rule, reached by the same structure.
|
|
246
|
+
// * **AND AN ACT THAT REMOVED NOTHING IS `D-3`'S SUCCESS WITH `tiers: []`**: no journal entry was appended,
|
|
247
|
+
// so there is no op, no landing to judge and no edit to undo — **this act answers `null`, the entry mints
|
|
248
|
+
// no pass, and nothing is added to any log.** A delete that changed nothing cannot be refused by a
|
|
249
|
+
// constraint, because it is not an edit. **NO `KC` TOKEN IS MINTED FOR IT AND NO TENTH TOKEN EXISTS.**
|
|
250
|
+
//
|
|
251
|
+
// **WHAT IT ANSWERS.** The attempt record, open and live — **carrying `attempt.record`, the `CommitRecord` this
|
|
252
|
+
// act minted** — for the pass the caller runs next (`entry`'s `constraintDelete`), or `null` on the `D-3` arm.
|
|
253
|
+
// **NO KERNEL ITEM IS MINTED**: `kernel-surface.md §1` item
|
|
254
|
+
// `2` closes the kernel's EXPORT SET at the five `K-1`–`K-5` items and that barrel
|
|
255
|
+
// (`src/constraint-kernel.mjs`) is untouched — this function is a part module's own act, reached by the entry
|
|
256
|
+
// the way every other kernel part is, and it is named by no `K-` number.
|
|
257
|
+
export function commitRemoval(store, address, tier, remove) {
|
|
258
|
+
const kernel = kernelFor(store);
|
|
259
|
+
// **NO `KC-7` REFUSAL IS TAKEN AT THIS OPENING, AND THE ASYMMETRY WITH `K-2` IS NAMED BECAUSE IT IS
|
|
260
|
+
// MEASURED.** `K-2` refuses a second attempt at a HELD address, and a REPAIR at that address is admitted only
|
|
261
|
+
// because it NAMES the enclosing commit at `write`'s fourth position (`D-46`). **A delete has no such
|
|
262
|
+
// position** — the member's arity is the declared `delete(address, tier)` and this pass changes no
|
|
263
|
+
// declaration — so a repair that edits by `delete` at the attempt's own address (the shape
|
|
264
|
+
// `tests/integration/js-constraints/constraint-kernel-negatives.test.mjs`'s `P-NEG-22` drives, and
|
|
265
|
+
// `parameter-semantics.md §2.7` blesses) would be refused by a hold it had no way to name its way out of,
|
|
266
|
+
// and a lawful repair would stop being lawful. **SO THIS ACT REFUSES NOTHING ON THAT GROUND**: it joins the
|
|
267
|
+
// address as a second attempt record and places itself in `kernel.live` below, which keeps the hold the
|
|
268
|
+
// enclosing attempt already has (`attemptHeldAt` stays true there for every nested `K-2`, unchanged) and
|
|
269
|
+
// takes the hold itself where the address was free. **THE COUNT `reversalAtRest` READS IS UNMOVED IN
|
|
270
|
+
// MEANING**: an open delete attempt IS an open attempt, so a reversal raised inside its pass is a step.
|
|
271
|
+
kernel.attempts += 1;
|
|
272
|
+
// THE ATTEMPT'S ADDRESS IS A LOCAL INDEX COPY of the caller's array, never `address.slice()` (`D-35`'s read
|
|
273
|
+
// half; the same form `commit` above takes and for the same measured reason).
|
|
274
|
+
const addressCopy = [];
|
|
275
|
+
for (let i = 0; i < address.length; i += 1) appendOwn(addressCopy, address[i]);
|
|
276
|
+
// THE COMMIT'S ONE LIST, BY REFERENCE, OR A FRESH ONE WHERE THIS DELETE OPENED THE COMMIT (`D-53`).
|
|
277
|
+
const joined = commitLogInFlight(kernel);
|
|
278
|
+
const ref = { id: `attempt-${kernel.attempts}` };
|
|
279
|
+
const attempt = {
|
|
280
|
+
// **THE KIND — the discriminator the write's attempt never needed**: an attempt that landed no write is
|
|
281
|
+
// judged against the DELETE's op, and it now owes the SAME `CommitRecord` a write's attempt does.
|
|
282
|
+
kind: 'delete',
|
|
283
|
+
ref,
|
|
284
|
+
// **THE NAME THE BODIES THIS PASS INVOKES JOIN** (`D-46`/`D-53`). The record below is that name from now
|
|
285
|
+
// on — `kernel-attempt.mjs`'s `evaluate` hands `attempt.record` to the invocation channel where one exists —
|
|
286
|
+
// and this one-member object STANDS AS THE RECORD'S ABSENT ARM, so a body's write joins the delete's commit
|
|
287
|
+
// instead of opening a second one on either arm.
|
|
288
|
+
name: { attempt: ref },
|
|
289
|
+
store,
|
|
290
|
+
address: addressCopy,
|
|
291
|
+
tier,
|
|
292
|
+
// THE SUBJECT IS WHAT THE DELETE REMOVES, NOT A VALUE: the after-state is absence, and the op carries what
|
|
293
|
+
// stood before it (its `before`) per tier (`D-55` item `3`'s *"the addresses and the tiers"*).
|
|
294
|
+
value: undefined,
|
|
295
|
+
commit: undefined,
|
|
296
|
+
// The store's own returned set, kept whole for the terminal act's discard rule (`terminal`).
|
|
297
|
+
write: null,
|
|
298
|
+
// THE DELETE'S JOURNAL OP IS THE ATTEMPT'S ONE LANDING — empty until the act answers one.
|
|
299
|
+
ops: [],
|
|
300
|
+
log: joined === null ? [] : joined,
|
|
301
|
+
ran: [],
|
|
302
|
+
appliedRepairs: [],
|
|
303
|
+
rollback: [],
|
|
304
|
+
checkpoint: null,
|
|
305
|
+
checkedOff: [],
|
|
306
|
+
status: 'open',
|
|
307
|
+
report: null,
|
|
308
|
+
};
|
|
309
|
+
// **THE RECORD, BUILT BEFORE THE STORE'S LEG IS CALLED — `K-2`'s OWN INSTANT AND `K-2`'s OWN FOUR MEMBERS**
|
|
310
|
+
// (`kernel-surface.md §2.1` item 2; `A112` re-spells the fourth: *"`pending` IS THE WHOLE RETURNED SET"*).
|
|
311
|
+
// Its members are FILLED from the receipt below; it is built here so the commit's identity exists before the
|
|
312
|
+
// act lands anything, exactly as it does for a write.
|
|
313
|
+
const record = {
|
|
314
|
+
attempt: attempt.ref,
|
|
315
|
+
op: null,
|
|
316
|
+
triggered: [],
|
|
317
|
+
pending: [],
|
|
318
|
+
};
|
|
319
|
+
attempt.record = record;
|
|
320
|
+
// AND THE COMMIT'S LIST TRAVELS ON IT UNDER THE SYMBOL KEY, VERBATIM AS `K-2` DEFINES IT (`D-53`): ONE LIST
|
|
321
|
+
// PER COMMIT, and the record is the identity it hangs from. **NO MEMBER IS ADDED** (`A117` (D6)).
|
|
322
|
+
Object.defineProperty(record, COMMIT_LOG, {
|
|
323
|
+
value: attempt.log,
|
|
324
|
+
enumerable: false,
|
|
325
|
+
writable: false,
|
|
326
|
+
configurable: true,
|
|
327
|
+
});
|
|
328
|
+
// **THE STORE'S OWN LEG, AND IT IS THE CALLER'S** (`kernel-surface.md §1` item 1's empty import footprint:
|
|
329
|
+
// this module reaches no entry and no addon of its own; the thunk is the entry's own addon call).
|
|
330
|
+
const removal = remove();
|
|
331
|
+
// `D-3`: nothing was removed — no entry was appended, so there is no op to name and no state to judge. **NO
|
|
332
|
+
// ATTEMPT IS OPENED AND NO RECORD CROSSES**: the receipt is the whole answer, its `tiers` and `triggered`
|
|
333
|
+
// empty, and the record built above dies with this attempt.
|
|
334
|
+
if (removal === null || typeof removal !== 'object' || removal.op === null || removal.op === undefined) {
|
|
335
|
+
attempt.status = 'closed';
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
attempt.write = removal;
|
|
339
|
+
attempt.ops = [removal.op];
|
|
340
|
+
// **THE RECEIPT'S OWN MEMBERS, READ OFF IT VERBATIM — `K-2`'s three assignments at its own record's name.**
|
|
341
|
+
// `triggered` is the store's returned set and `pending` is that set WHOLE (no sift; `A112`), so the residue
|
|
342
|
+
// the terminal arm delivers and the failing arm's discard reads are the delete's own, unfiltered.
|
|
343
|
+
record.op = removal.op;
|
|
344
|
+
record.triggered = removal.triggered;
|
|
345
|
+
record.pending = removal.triggered.slice();
|
|
346
|
+
// THE ATTEMPT IS PLACED LIVE HERE, BEFORE THE FIRST BODY OF THE PASS RUNS: the store's own `delete` invokes
|
|
347
|
+
// nothing, so there is no window between the act and this line in which a caller's code could interleave —
|
|
348
|
+
// and the address is held from this instant through the pass and its terminal act, exactly as `K-2` holds
|
|
349
|
+
// it. **THE MAP IS ALSO THE COUNT OF OPEN ATTEMPTS** the restart's at-rest discriminator reads
|
|
350
|
+
// (`constraints.mjs`'s `reversalAtRest`), so a reversal raised inside this pass is a step and not a
|
|
351
|
+
// judgement.
|
|
352
|
+
kernel.live.set(ref.id, attempt);
|
|
353
|
+
return attempt;
|
|
354
|
+
}
|
|
355
|
+
|