@rulvar/plan 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +119 -116
- package/dist/index.js +120 -127
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5,8 +5,8 @@ import { CURRENT_HASH_VERSION, ConfigError, DedupIndex, InMemoryStore, LEGACY_LT
|
|
|
5
5
|
* closed PlanNodeStatus machine, and the pure derivations the plan fold
|
|
6
6
|
* consumes (readiness, cycle checks).
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* (TaskPlan data model
|
|
8
|
+
* Contract: https://docs.rulvar.com/guide/adaptive-orchestration
|
|
9
|
+
* (TaskPlan data model; single applier and total order) (DEF-8).
|
|
10
10
|
* Nodes carry NodeId ULIDs minted by the engine inside the plan.revision
|
|
11
11
|
* entry that adds them, never by the model; dependencies form a DAG; the
|
|
12
12
|
* status machine is closed and `done` is immutable. State is ALWAYS a pure
|
|
@@ -15,9 +15,9 @@ import { CURRENT_HASH_VERSION, ConfigError, DedupIndex, InMemoryStore, LEGACY_LT
|
|
|
15
15
|
*/
|
|
16
16
|
/**
|
|
17
17
|
* The single sequential scope holding every plan-mutating entry, inside
|
|
18
|
-
* the orchestrator's run scope
|
|
18
|
+
* the orchestrator's run scope: total order = ordinal
|
|
19
19
|
* order = durable append order. Child node scopes are `plan/NodeId`
|
|
20
|
-
* (core `planNodeScope
|
|
20
|
+
* (core `planNodeScope`).
|
|
21
21
|
*/
|
|
22
22
|
const PLAN_SCOPE = "plan";
|
|
23
23
|
/** The empty plan every fold starts from. */
|
|
@@ -30,7 +30,7 @@ function emptyPlan() {
|
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Terminal statuses: no transition ever leaves them. `done` is immutable
|
|
33
|
-
* because its result is paid for (
|
|
33
|
+
* because its result is paid for (cancel_task on done drops
|
|
34
34
|
* with node_already_done); failed, cancelled, and skipped are equally
|
|
35
35
|
* final per the conflict table's terminal_status rows.
|
|
36
36
|
*/
|
|
@@ -46,18 +46,18 @@ function isTerminalPlanStatus(status) {
|
|
|
46
46
|
/**
|
|
47
47
|
* Asserts one status transition against the closed machine. Op-level
|
|
48
48
|
* legality (which ops may request which transitions in which state) is
|
|
49
|
-
* the rebase conflict table's job (
|
|
49
|
+
* the rebase conflict table's job (M7-T04); the machine
|
|
50
50
|
* itself enforces exactly the structural rules:
|
|
51
51
|
*
|
|
52
52
|
* - nothing leaves a terminal status (`done` is immutable; failed,
|
|
53
53
|
* cancelled, skipped are final),
|
|
54
54
|
* - `running` is entered only from `ready` (the engine schedules ready
|
|
55
|
-
* nodes
|
|
55
|
+
* nodes),
|
|
56
56
|
* - a transition never restates the current status (the engine writes no
|
|
57
57
|
* no-op set_node_status).
|
|
58
58
|
*
|
|
59
59
|
* A violation is an engine bug and raises the typed PlanInvariantError
|
|
60
|
-
* (
|
|
60
|
+
* (never a silent brick).
|
|
61
61
|
*/
|
|
62
62
|
function assertPlanTransition(node, to) {
|
|
63
63
|
if (isTerminalPlanStatus(node.status)) throw new PlanInvariantError(`plan node ${node.nodeId} is terminal '${node.status}' and cannot become '${to}' (docs/07, 3.1: the status machine is closed and 'done' is immutable)`, { data: {
|
|
@@ -77,8 +77,8 @@ function assertPlanTransition(node, to) {
|
|
|
77
77
|
} });
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
80
|
-
* Dependency satisfaction, derived purely in the fold and NEVER a record
|
|
81
|
-
*
|
|
80
|
+
* Dependency satisfaction, derived purely in the fold and NEVER a record:
|
|
81
|
+
* a dep is satisfied when waived or when its upstream
|
|
82
82
|
* node is `done`. Terminally unsuccessful upstreams (cancelled, failed)
|
|
83
83
|
* keep blocking: such edges "remain blocking" per the rewire_deps row of
|
|
84
84
|
* the conflict table, and waive_dep exists exactly to unblock them.
|
|
@@ -120,7 +120,7 @@ function recomputePlanReadiness(plan) {
|
|
|
120
120
|
} : plan;
|
|
121
121
|
}
|
|
122
122
|
/**
|
|
123
|
-
* Cycle check for rewire_deps (
|
|
123
|
+
* Cycle check for rewire_deps (a resulting cycle drops the
|
|
124
124
|
* WHOLE op with dep_cycle; rewire_deps is atomic). Answers whether the
|
|
125
125
|
* graph with `nodeId`'s deps replaced by `deps` contains a cycle
|
|
126
126
|
* reachable from `nodeId`. add_task cannot create cycles (nothing depends
|
|
@@ -147,19 +147,19 @@ function wouldCreateDepCycle(plan, nodeId, deps) {
|
|
|
147
147
|
* planHash (M7-T01): the canonical projection of a TaskPlan and its
|
|
148
148
|
* sha256, plus the fold-head assertion the appenders use.
|
|
149
149
|
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* sorted by NodeId, each node exactly the docs/07 3.1 record with `deps`
|
|
150
|
+
* DEF-8: planHash = sha256 of the canonical JSON of PlanState, nodes
|
|
151
|
+
* sorted by NodeId, each node exactly the canonicalNode record with `deps`
|
|
153
152
|
* sorted in the hash, plus the guard fold counters revisionCount and
|
|
154
153
|
* droppedRevisionStreak. Nothing wall-clock, nothing telemetric, enters
|
|
155
154
|
* the hash. Canonicalization and digest ride the frozen hashVersion 2
|
|
156
155
|
* deriver (RFC 8785 JCS + sha256), so the plan chain shares the identity
|
|
157
156
|
* pipeline of the journal kernel; a future grammar change arrives as a
|
|
158
|
-
* new deriver, never as an edit here
|
|
157
|
+
* new deriver, never as an edit here
|
|
158
|
+
* (https://docs.rulvar.com/guide/journal-compatibility).
|
|
159
159
|
*/
|
|
160
160
|
/** The hashVersion whose profile computes planHash today. */
|
|
161
161
|
const PLAN_HASH_VERSION = CURRENT_HASH_VERSION;
|
|
162
|
-
/** The exact per-node projection entering the hash
|
|
162
|
+
/** The exact per-node projection entering the hash. */
|
|
163
163
|
function canonicalNode(node) {
|
|
164
164
|
const projected = {
|
|
165
165
|
nodeId: node.nodeId,
|
|
@@ -178,7 +178,7 @@ function canonicalNode(node) {
|
|
|
178
178
|
}
|
|
179
179
|
/**
|
|
180
180
|
* The canonical JSON projection of PlanState: nodes sorted by NodeId plus
|
|
181
|
-
* the guard fold counters, nothing else
|
|
181
|
+
* the guard fold counters, nothing else.
|
|
182
182
|
*/
|
|
183
183
|
function canonicalPlanState(plan) {
|
|
184
184
|
return {
|
|
@@ -190,14 +190,14 @@ function canonicalPlanState(plan) {
|
|
|
190
190
|
/**
|
|
191
191
|
* planHash under one deriver profile (default: the current hashVersion 2
|
|
192
192
|
* profile). Replay recomputes each entry's planHashAfter with the
|
|
193
|
-
* predicate of that entry's OWN hashVersion
|
|
193
|
+
* predicate of that entry's OWN hashVersion, so the
|
|
194
194
|
* deriver is a parameter, not an ambient.
|
|
195
195
|
*/
|
|
196
196
|
function planHash(plan, deriver = deriverV2) {
|
|
197
197
|
return deriver.deriveKey(canonicalPlanState(plan));
|
|
198
198
|
}
|
|
199
199
|
/**
|
|
200
|
-
* The append-time head assertion
|
|
200
|
+
* The append-time head assertion: planHashBefore of the
|
|
201
201
|
* entry being appended MUST equal the current fold head. A failure is an
|
|
202
202
|
* engine bug and raises the typed PlanInvariantError; the run finishes
|
|
203
203
|
* with outcome error, never a silent brick.
|
|
@@ -218,11 +218,11 @@ function assertPlanHead(plan, expectedPlanHash, context) {
|
|
|
218
218
|
* PlanWriteLock (M7-T01): the in-process FIFO mutex serializing live
|
|
219
219
|
* appends to the sequential scope "plan".
|
|
220
220
|
*
|
|
221
|
-
* Owning
|
|
221
|
+
* Owning contract: https://docs.rulvar.com/guide/adaptive-orchestration
|
|
222
222
|
* (DEF-8, XF-07). The lock serializes ONLY plan-scope appends (acquire,
|
|
223
223
|
* read the fold head, evaluate, append, release); it MUST NOT substitute
|
|
224
224
|
* for resolution arbitration, which is owned by the ResolutionArbiter
|
|
225
|
-
* (
|
|
225
|
+
* (DEF-4). In queue mode
|
|
226
226
|
* the lease fencing epoch applies on top. Wall clock influences only
|
|
227
227
|
* WHICH order gets recorded live; replay reads the recorded order and
|
|
228
228
|
* never takes the lock.
|
|
@@ -259,14 +259,13 @@ var PlanWriteLock = class {
|
|
|
259
259
|
* toolset, used by spawn_agent, parallel_agents, add_task, and
|
|
260
260
|
* proposedDecomposition.
|
|
261
261
|
*
|
|
262
|
-
*
|
|
263
|
-
* orchestrator never sees or names concrete models; model_hint.startTier
|
|
262
|
+
* The orchestrator never sees or names concrete models; model_hint.startTier
|
|
264
263
|
* is the ONLY model influence it has and is clamped to the declared
|
|
265
|
-
* ladder
|
|
264
|
+
* ladder.
|
|
266
265
|
*/
|
|
267
266
|
/**
|
|
268
|
-
* The deterministic spec digest entering PlanNode.promptSpecHash
|
|
269
|
-
*
|
|
267
|
+
* The deterministic spec digest entering PlanNode.promptSpecHash:
|
|
268
|
+
* the canonical JSON of the full TaskSpec through the
|
|
270
269
|
* frozen hashVersion 2 canonicalization. A plan-internal digest, not a
|
|
271
270
|
* kernel content key: the paid-call identity stays with the child's own
|
|
272
271
|
* spawn entry.
|
|
@@ -289,8 +288,8 @@ function applyTaskSpecPatch(spec, patch) {
|
|
|
289
288
|
* plan.revision and plan.decision entry payloads plus the single-applier
|
|
290
289
|
* plan fold (M7-T04, DEF-8).
|
|
291
290
|
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
291
|
+
* Full contract: https://docs.rulvar.com/guide/adaptive-orchestration.
|
|
292
|
+
* There are several AUTHORS of plan mutations but exactly ONE
|
|
294
293
|
* APPLIER: the fold below, consuming a totally ordered stream of
|
|
295
294
|
* plan-mutating entries from the sequential scope "plan". Nothing mutates
|
|
296
295
|
* PlanState directly; state is a pure fold of entries. Replay NEVER
|
|
@@ -301,7 +300,7 @@ function applyTaskSpecPatch(spec, patch) {
|
|
|
301
300
|
* corrupting the journal further.
|
|
302
301
|
*/
|
|
303
302
|
/**
|
|
304
|
-
* Content keys
|
|
303
|
+
* Content keys: plan.revision keys over {kind, base,
|
|
305
304
|
* requestedOps}; plan.decision over {kind, origin, ops, causeRef}.
|
|
306
305
|
* Cosmetics (rationale) never enter a key; ordinal within scope "plan"
|
|
307
306
|
* distinguishes repeats, so forward-matching works without kernel
|
|
@@ -330,7 +329,7 @@ function emptyPlanFold(plan) {
|
|
|
330
329
|
doneRefs: {}
|
|
331
330
|
};
|
|
332
331
|
}
|
|
333
|
-
/** The streak RevisionGuards consume
|
|
332
|
+
/** The streak RevisionGuards consume. */
|
|
334
333
|
function effectiveDroppedStreak(state) {
|
|
335
334
|
return state.plan.droppedRevisionStreak + state.badBaseStreak;
|
|
336
335
|
}
|
|
@@ -372,7 +371,7 @@ function withNode(working, node, spec) {
|
|
|
372
371
|
* recorded outcomes; op-level legality was decided at rebase time and is
|
|
373
372
|
* never re-evaluated here. Exported for the rebase engine, which applies
|
|
374
373
|
* each op of a revision against the state already changed by the earlier
|
|
375
|
-
* applied ops of the same revision
|
|
374
|
+
* applied ops of the same revision.
|
|
376
375
|
*/
|
|
377
376
|
function applyAppliedOp(working, op, context) {
|
|
378
377
|
switch (op.op) {
|
|
@@ -483,7 +482,7 @@ function readPlanDecision(entry) {
|
|
|
483
482
|
return value;
|
|
484
483
|
}
|
|
485
484
|
/**
|
|
486
|
-
* THE single applier
|
|
485
|
+
* THE single applier: folds one plan-scope entry into the
|
|
487
486
|
* state. Replay consumes recorded outcomes (the APPLIED diff), never
|
|
488
487
|
* re-runs rebase, and timers do not run; hash verification runs under
|
|
489
488
|
* the entry's own hashVersion profile.
|
|
@@ -544,7 +543,7 @@ function applyPlanEntry(state, entry, options) {
|
|
|
544
543
|
}
|
|
545
544
|
/**
|
|
546
545
|
* The shared plan.decision applier core: engine authorship happens at
|
|
547
|
-
* the fold head under PlanWriteLock
|
|
546
|
+
* the fold head under PlanWriteLock, so the producer can
|
|
548
547
|
* PREVIEW the resulting state (and its planHashAfter) before appending,
|
|
549
548
|
* and the fold re-applies the recorded ops identically on replay.
|
|
550
549
|
*/
|
|
@@ -611,7 +610,7 @@ function lineageOfAdmission(admissions, opIndex) {
|
|
|
611
610
|
return verdict.lineage.logicalTaskId;
|
|
612
611
|
}
|
|
613
612
|
/**
|
|
614
|
-
* The escalated node's fate under a resolve_escalation op
|
|
613
|
+
* The escalated node's fate under a resolve_escalation op:
|
|
615
614
|
* retry re-opens the node for scheduling (pending; readiness decides),
|
|
616
615
|
* cancel closes it, accept marks the paid partial result done, decompose
|
|
617
616
|
* leaves the node escalated while its children (spawn_admitted in the
|
|
@@ -642,7 +641,7 @@ function resolveEscalatedNode(node, decision, escalationRef) {
|
|
|
642
641
|
//#endregion
|
|
643
642
|
//#region src/rebase.ts
|
|
644
643
|
/**
|
|
645
|
-
* Steps 2-4 of the committed algorithm
|
|
644
|
+
* Steps 2-4 of the committed algorithm: base validation,
|
|
646
645
|
* sequential per-op conflict resolution against the mutating head, and
|
|
647
646
|
* the post-revision counter update. Pure: the caller owns the lock, the
|
|
648
647
|
* append, and every effect.
|
|
@@ -720,9 +719,8 @@ function dropped(requested, reason, blockingRef) {
|
|
|
720
719
|
};
|
|
721
720
|
}
|
|
722
721
|
/**
|
|
723
|
-
* The complete per-op resolution table, op x node state at the fold head
|
|
724
|
-
*
|
|
725
|
-
* row; nothing else exists.
|
|
722
|
+
* The complete per-op resolution table, op x node state at the fold head.
|
|
723
|
+
* Normative and closed: nothing outside the rows below exists.
|
|
726
724
|
*/
|
|
727
725
|
function evaluateOp(op, opIndex, working, context, admissions, assignedNodeIds) {
|
|
728
726
|
if (context.frozen === true) return dropped(op, "plan_frozen");
|
|
@@ -898,7 +896,7 @@ function evaluateOp(op, opIndex, working, context, admissions, assignedNodeIds)
|
|
|
898
896
|
}
|
|
899
897
|
}
|
|
900
898
|
/**
|
|
901
|
-
* The cancel cascade
|
|
899
|
+
* The cancel cascade: the transitive BLOCKING dependents
|
|
902
900
|
* of the cancelled node, computed at apply time. An edge is blocking
|
|
903
901
|
* when not waived; `done` nodes never enter the cascade (done is
|
|
904
902
|
* immutable), and running dependents (only reachable via waived or
|
|
@@ -927,7 +925,7 @@ function cascadeOf(plan, root) {
|
|
|
927
925
|
//#region src/guards.ts
|
|
928
926
|
/** Appendix A: osc_guard reject threshold per key (shared default). */
|
|
929
927
|
const DEFAULT_MAX_OSCILLATIONS_PER_KEY = 2;
|
|
930
|
-
/** The hard per-run stall replan bound
|
|
928
|
+
/** The hard per-run stall replan bound. */
|
|
931
929
|
const DEFAULT_STALL_REPLAN_CAP = 4;
|
|
932
930
|
const DEFAULT_DROPPED_REVISION_LIMIT = 3;
|
|
933
931
|
/**
|
|
@@ -1053,7 +1051,7 @@ const DEFAULT_MAX_PINNED_WORKTREES = 4;
|
|
|
1053
1051
|
/**
|
|
1054
1052
|
* The worktree pin ledger: a pure fold counting live pins from abandon
|
|
1055
1053
|
* entries carrying `retainWorktree: true` (park pinning and DEF-5
|
|
1056
|
-
* retention share the cap by construction
|
|
1054
|
+
* retention share the cap by construction).
|
|
1057
1055
|
*/
|
|
1058
1056
|
var PinLedger = class PinLedger {
|
|
1059
1057
|
pinnedTargets = /* @__PURE__ */ new Set();
|
|
@@ -1098,7 +1096,7 @@ function unparkPlacementOf(input) {
|
|
|
1098
1096
|
* RunLedger (M7-T09): run-scoped, single-writer, journaled, strictly
|
|
1099
1097
|
* advisory distilled state for recovery-context quality and replanning.
|
|
1100
1098
|
*
|
|
1101
|
-
*
|
|
1099
|
+
* Contract: https://docs.rulvar.com/guide/adaptive-orchestration. ONLY
|
|
1102
1100
|
* the orchestrator scope writes; every authored write is a journaled
|
|
1103
1101
|
* effect entry of kind `ledger.op`; the VIEW is a pure fold of those ops
|
|
1104
1102
|
* joined to the journal's task table. The journal always wins on what is
|
|
@@ -1227,14 +1225,14 @@ function foldLedger(entries, options) {
|
|
|
1227
1225
|
return view;
|
|
1228
1226
|
}
|
|
1229
1227
|
/**
|
|
1230
|
-
* The committed ledger_read render budget (
|
|
1228
|
+
* The committed ledger_read render budget (Appendix A: 65536
|
|
1231
1229
|
* chars over the serialized view, the character measure; OQ-04 closed
|
|
1232
1230
|
* at M10 entry). The section caps stay the primary bound; under the
|
|
1233
1231
|
* default termination limits this belt never engages.
|
|
1234
1232
|
*/
|
|
1235
1233
|
const LEDGER_RENDER_BUDGET_CHARS = 65536;
|
|
1236
1234
|
/**
|
|
1237
|
-
* Deterministic render bound
|
|
1235
|
+
* Deterministic render bound: over budget, rows drop
|
|
1238
1236
|
* oldest-first, auto-derived joins before authored sections, and the
|
|
1239
1237
|
* mission brief slices last; every drop is a FLAGGED discrepancy line.
|
|
1240
1238
|
* A pure function of (view, budget): a re-executed wake turn renders
|
|
@@ -1280,7 +1278,7 @@ function boundLedgerRender(view, budgetChars = LEDGER_RENDER_BUDGET_CHARS) {
|
|
|
1280
1278
|
}
|
|
1281
1279
|
return bounded;
|
|
1282
1280
|
}
|
|
1283
|
-
/** Section-cap check for one authored op (
|
|
1281
|
+
/** Section-cap check for one authored op (Appendix A). */
|
|
1284
1282
|
function ledgerCapViolation(view, op) {
|
|
1285
1283
|
if (op.op === "brief_set" && view.brief !== void 0) return "the mission brief is immutable (brief_set is once per run)";
|
|
1286
1284
|
if ((op.op === "fact_add" || op.op === "fact_supersede") && view.facts.length >= LEDGER_SECTION_CAPS.facts) return `the facts section is capped at ${String(LEDGER_SECTION_CAPS.facts)}`;
|
|
@@ -1288,7 +1286,7 @@ function ledgerCapViolation(view, op) {
|
|
|
1288
1286
|
if (op.op === "observation_add" && view.observations.length >= LEDGER_SECTION_CAPS.observations) return `the observations section is capped at ${String(LEDGER_SECTION_CAPS.observations)}`;
|
|
1289
1287
|
}
|
|
1290
1288
|
/**
|
|
1291
|
-
* Compaction sufficiency
|
|
1289
|
+
* Compaction sufficiency: the orchestrate role may
|
|
1292
1290
|
* compact aggressively only when the ledger measurably suffices (at
|
|
1293
1291
|
* least one authored revision recorded and a minimum fact count);
|
|
1294
1292
|
* otherwise the engine falls back to conservative summarize.
|
|
@@ -1311,9 +1309,8 @@ function exportLedger(view) {
|
|
|
1311
1309
|
/**
|
|
1312
1310
|
* ModelLadder runtime pieces (M7-T10).
|
|
1313
1311
|
*
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1316
|
-
* canonicalization, declared once in core). This module is PURE: the
|
|
1312
|
+
* The ladder type family and canonicalization are declared once in
|
|
1313
|
+
* core. This module is PURE: the
|
|
1317
1314
|
* PlanRunner drives it through the extension IO. Every ladder control-flow
|
|
1318
1315
|
* verdict (trigger classification result, gate verdicts, spot-check
|
|
1319
1316
|
* selection) journals as a decision entry computed once live and replayed
|
|
@@ -1321,8 +1318,8 @@ function exportLedger(view) {
|
|
|
1321
1318
|
*/
|
|
1322
1319
|
/**
|
|
1323
1320
|
* Extracts the declared ladder from an agent profile: the ModelSpec union
|
|
1324
|
-
* carries it (`model: { ladder }`), or the loop-role routing entry
|
|
1325
|
-
*
|
|
1321
|
+
* carries it (`model: { ladder }`), or the loop-role routing entry.
|
|
1322
|
+
* The same declaration points feed ladderLengthOf
|
|
1326
1323
|
* and the frozen kMax, so admission and execution can never disagree on
|
|
1327
1324
|
* the ladder length.
|
|
1328
1325
|
*/
|
|
@@ -1346,8 +1343,8 @@ function canonicalLadderOf(profile) {
|
|
|
1346
1343
|
return canonicalizeLadder(declared, chainEffort === void 0 ? void 0 : { chainEffort });
|
|
1347
1344
|
}
|
|
1348
1345
|
/**
|
|
1349
|
-
* Clamps the orchestrator's `model_hint.startTier` to the declared ladder
|
|
1350
|
-
*
|
|
1346
|
+
* Clamps the orchestrator's `model_hint.startTier` to the declared ladder:
|
|
1347
|
+
* the hint is the ONLY model influence the
|
|
1351
1348
|
* orchestrator has, and it never names a model.
|
|
1352
1349
|
*/
|
|
1353
1350
|
function clampStartTier(ladder, hint) {
|
|
@@ -1357,14 +1354,14 @@ function clampStartTier(ladder, hint) {
|
|
|
1357
1354
|
/**
|
|
1358
1355
|
* The rung an attempt executes on: the clamped start tier plus the
|
|
1359
1356
|
* journaled raise count, hard-clamped at the top rung. `rungIndex` per
|
|
1360
|
-
* lineage is strictly monotone; there are no demotions
|
|
1357
|
+
* lineage is strictly monotone; there are no demotions.
|
|
1361
1358
|
*/
|
|
1362
1359
|
function executingRungOf(ladder, startTier, raises) {
|
|
1363
1360
|
return Math.min(startTier + raises, ladder.rungs.length - 1);
|
|
1364
1361
|
}
|
|
1365
1362
|
/**
|
|
1366
|
-
* Classifies a settled attempt into the typed transition trigger
|
|
1367
|
-
*
|
|
1363
|
+
* Classifies a settled attempt into the typed transition trigger:
|
|
1364
|
+
* schema-mismatch errors are 'schema-exhausted';
|
|
1368
1365
|
* the engine's no-progress abort is first-class 'no-progress' (it rides
|
|
1369
1366
|
* status 'limit' with the dedicated abort class, distinct from user
|
|
1370
1367
|
* cancellation by construction); cancelled, escalated, and skipped never
|
|
@@ -1390,7 +1387,7 @@ function ladderVerdictKey(attemptRef) {
|
|
|
1390
1387
|
attemptRef
|
|
1391
1388
|
});
|
|
1392
1389
|
}
|
|
1393
|
-
/** The forced verdict schema of the judge gate
|
|
1390
|
+
/** The forced verdict schema of the judge gate. */
|
|
1394
1391
|
const JUDGE_VERDICT_SCHEMA = {
|
|
1395
1392
|
type: "object",
|
|
1396
1393
|
properties: {
|
|
@@ -1420,9 +1417,9 @@ function judgePrompt(input) {
|
|
|
1420
1417
|
/**
|
|
1421
1418
|
* EscalationProtocol completion (M7-T11).
|
|
1422
1419
|
*
|
|
1423
|
-
*
|
|
1424
|
-
*
|
|
1425
|
-
*
|
|
1420
|
+
* Full protocol: https://docs.rulvar.com/guide/adaptive-orchestration;
|
|
1421
|
+
* resolutions (the DEF-4 family): https://docs.rulvar.com/guide/durability.
|
|
1422
|
+
* The M3 producers (report, flavors, the
|
|
1426
1423
|
* escalate tool, countsAgainstLimit derivation) live in core; this module
|
|
1427
1424
|
* owns the DECISION side under PlanRunner: the authoritative
|
|
1428
1425
|
* `escalation-decision` entries the lineage and termination folds consume,
|
|
@@ -1430,7 +1427,7 @@ function judgePrompt(input) {
|
|
|
1430
1427
|
*
|
|
1431
1428
|
* Channels, closed in v1:
|
|
1432
1429
|
* - Live Flavor A: `cancel_task` on an escalated node transforms into an
|
|
1433
|
-
* escalation resolution with verdict `cancel
|
|
1430
|
+
* escalation resolution with verdict `cancel`; the
|
|
1434
1431
|
* other verdicts on a TERMINAL report are engine territory.
|
|
1435
1432
|
* - Flavor B: the suspended report resolves through the DEF-4 family
|
|
1436
1433
|
* (timeout `defaultDecision`, a live `onEscalation` decision, or a
|
|
@@ -1452,7 +1449,7 @@ function resolvedByOf(by) {
|
|
|
1452
1449
|
if (by === "class_decision") return "class";
|
|
1453
1450
|
return "live";
|
|
1454
1451
|
}
|
|
1455
|
-
/** The plan.decision origin of one resolvedBy value
|
|
1452
|
+
/** The plan.decision origin of one resolvedBy value. */
|
|
1456
1453
|
function decisionOriginOf(resolvedBy) {
|
|
1457
1454
|
if (resolvedBy === "default") return "escalation-default";
|
|
1458
1455
|
if (resolvedBy === "class") return "escalation-class";
|
|
@@ -1463,21 +1460,20 @@ function decisionOriginOf(resolvedBy) {
|
|
|
1463
1460
|
/**
|
|
1464
1461
|
* The PlanRunner toolset (M7-T05): plan_view and plan_revise.
|
|
1465
1462
|
*
|
|
1466
|
-
*
|
|
1467
|
-
* 4.7. The JSON Schemas below are NORMATIVE: they enter toolsetHash and
|
|
1463
|
+
* The JSON Schemas below are NORMATIVE: they enter toolsetHash and
|
|
1468
1464
|
* therefore identity. plan_view is a pure fold pinned to the last
|
|
1469
1465
|
* WakeDigest (never a live read; a re-executed wake turn reads its
|
|
1470
1466
|
* original snapshot); plan_revise is the typed PlanOp diff with
|
|
1471
1467
|
* auto-rebase (M7-T04), whose tool result renders deterministically from
|
|
1472
1468
|
* the journaled entry.
|
|
1473
1469
|
*/
|
|
1474
|
-
/**
|
|
1470
|
+
/** plan_view takes no parameters. */
|
|
1475
1471
|
const PLAN_VIEW_SCHEMA = {
|
|
1476
1472
|
type: "object",
|
|
1477
1473
|
additionalProperties: false,
|
|
1478
1474
|
properties: {}
|
|
1479
1475
|
};
|
|
1480
|
-
/** The taskSpec projection shared with spawn_agent
|
|
1476
|
+
/** The taskSpec projection shared with spawn_agent. */
|
|
1481
1477
|
const TASK_SPEC_SCHEMA = {
|
|
1482
1478
|
type: "object",
|
|
1483
1479
|
additionalProperties: false,
|
|
@@ -1506,7 +1502,7 @@ const TASK_SPEC_SCHEMA = {
|
|
|
1506
1502
|
taskClass: { type: "string" }
|
|
1507
1503
|
}
|
|
1508
1504
|
};
|
|
1509
|
-
/**
|
|
1505
|
+
/** The plan_revise parameter schema (normative). */
|
|
1510
1506
|
const PLAN_REVISE_SCHEMA = {
|
|
1511
1507
|
type: "object",
|
|
1512
1508
|
additionalProperties: false,
|
|
@@ -1682,7 +1678,7 @@ const PLAN_VIEW_TOOL_NAME = "plan_view";
|
|
|
1682
1678
|
const PLAN_REVISE_TOOL_NAME = "plan_revise";
|
|
1683
1679
|
const LEDGER_APPEND_TOOL_NAME = "ledger_append";
|
|
1684
1680
|
const LEDGER_READ_TOOL_NAME = "ledger_read";
|
|
1685
|
-
/** The closed authored op vocabulary as JSON Schema
|
|
1681
|
+
/** The closed authored op vocabulary as JSON Schema. */
|
|
1686
1682
|
const LEDGER_APPEND_SCHEMA = {
|
|
1687
1683
|
type: "object",
|
|
1688
1684
|
additionalProperties: false,
|
|
@@ -1811,7 +1807,7 @@ const LEDGER_APPEND_SCHEMA = {
|
|
|
1811
1807
|
}
|
|
1812
1808
|
] } }
|
|
1813
1809
|
};
|
|
1814
|
-
/**
|
|
1810
|
+
/** ledger_read takes no parameters and pins to the turn snapshot. */
|
|
1815
1811
|
const LEDGER_READ_SCHEMA = {
|
|
1816
1812
|
type: "object",
|
|
1817
1813
|
additionalProperties: false,
|
|
@@ -1851,19 +1847,18 @@ function buildPlanTools(runtime) {
|
|
|
1851
1847
|
/**
|
|
1852
1848
|
* PlanRunner (M7-T05): the opt-in extension of mode (c).
|
|
1853
1849
|
*
|
|
1854
|
-
*
|
|
1855
|
-
*
|
|
1850
|
+
* Full contract: https://docs.rulvar.com/guide/adaptive-orchestration.
|
|
1851
|
+
* The ENGINE, not the model, schedules ready nodes through the
|
|
1856
1852
|
* existing semaphore and budget admission; children run under
|
|
1857
1853
|
* `plan/NodeId` scopes; every plan mutation is an entry in the single
|
|
1858
1854
|
* sequential scope "plan"; the orchestrator sleeps between wakes and
|
|
1859
1855
|
* revises the plan through typed diffs with auto-rebase. PlanRunner runs
|
|
1860
|
-
* write `termination.init` and carry the full adaptive machinery
|
|
1861
|
-
*
|
|
1856
|
+
* write `termination.init` and carry the full adaptive machinery;
|
|
1857
|
+
* the guards, reuse, park, ledger, ladder,
|
|
1862
1858
|
* escalation, and budget-cap layers complete in M7-T06..T13.
|
|
1863
1859
|
*
|
|
1864
1860
|
* PlanRunner is built EXCLUSIVELY from the public core API through the
|
|
1865
|
-
* orchestrator extension seam (
|
|
1866
|
-
* rule).
|
|
1861
|
+
* orchestrator extension seam (the seam-sufficiency rule).
|
|
1867
1862
|
*/
|
|
1868
1863
|
/** AgentResult terminal statuses mapped onto plan node statuses. */
|
|
1869
1864
|
function nodeStatusOf(status) {
|
|
@@ -1879,7 +1874,7 @@ function nodeStatusOf(status) {
|
|
|
1879
1874
|
const TERMINATION_INIT_KEY_KIND = "termination.init";
|
|
1880
1875
|
const TERMINATION_DENIED_KEY_KIND = "termination.denied";
|
|
1881
1876
|
/**
|
|
1882
|
-
* Builds the PlanRunner orchestrator extension
|
|
1877
|
+
* Builds the PlanRunner orchestrator extension.
|
|
1883
1878
|
* Attach via `orchestrate(engine, goal, { extension: planRunner(o) })` or
|
|
1884
1879
|
* the `orchestratePlanned` convenience surface.
|
|
1885
1880
|
*/
|
|
@@ -1930,8 +1925,8 @@ function planRunner(options) {
|
|
|
1930
1925
|
}
|
|
1931
1926
|
};
|
|
1932
1927
|
/**
|
|
1933
|
-
* Appends fold-fired verdicts strictly BEFORE their effects
|
|
1934
|
-
*
|
|
1928
|
+
* Appends fold-fired verdicts strictly BEFORE their effects; a
|
|
1929
|
+
* verdict already journaled (replay absorb) never duplicates.
|
|
1935
1930
|
*/
|
|
1936
1931
|
const drainGuardVerdicts = async () => {
|
|
1937
1932
|
while (pendingGuardVerdicts.length > 0) {
|
|
@@ -1971,7 +1966,7 @@ function planRunner(options) {
|
|
|
1971
1966
|
* SpawnKeys a byte-identical candidate would collide with: within one
|
|
1972
1967
|
* run, an identical TaskSpec resolves to the identical kernel content
|
|
1973
1968
|
* key, so donor discovery goes promptSpecHash -> prior nodes -> their
|
|
1974
|
-
* root entry keys (
|
|
1969
|
+
* root entry keys (strict byte equality, never fuzzy).
|
|
1975
1970
|
*/
|
|
1976
1971
|
const donorKeysOf = (spec) => {
|
|
1977
1972
|
const specHash = promptSpecHashOf(spec);
|
|
@@ -1985,7 +1980,7 @@ function planRunner(options) {
|
|
|
1985
1980
|
};
|
|
1986
1981
|
/**
|
|
1987
1982
|
* Re-issues the reuse effects recorded in one plan.revision entry
|
|
1988
|
-
* (
|
|
1983
|
+
* (deciding entry, then node.link, then the child root,
|
|
1989
1984
|
* then scheduling; a crash between any two is ordinary roll-forward).
|
|
1990
1985
|
* Idempotent: every append scans for its own identity first.
|
|
1991
1986
|
*/
|
|
@@ -2052,8 +2047,8 @@ function planRunner(options) {
|
|
|
2052
2047
|
}
|
|
2053
2048
|
};
|
|
2054
2049
|
/**
|
|
2055
|
-
* Builds the reuse transform for one add_task at the fold head
|
|
2056
|
-
*
|
|
2050
|
+
* Builds the reuse transform for one add_task at the fold head:
|
|
2051
|
+
* the verdict, the donor descriptor, and the placement
|
|
2057
2052
|
* embed into the revision entry; effects land after the append.
|
|
2058
2053
|
*/
|
|
2059
2054
|
const buildReuseTransform = (op, kind, donor) => {
|
|
@@ -2147,7 +2142,7 @@ function planRunner(options) {
|
|
|
2147
2142
|
}
|
|
2148
2143
|
};
|
|
2149
2144
|
};
|
|
2150
|
-
/** Compiles applied cancels into severing abandons
|
|
2145
|
+
/** Compiles applied cancels into severing abandons. */
|
|
2151
2146
|
const landCancelAbandons = async (value, authorizedBy) => {
|
|
2152
2147
|
for (const outcome of value.outcomes) {
|
|
2153
2148
|
if (outcome.kind === "dropped") continue;
|
|
@@ -2157,7 +2152,7 @@ function planRunner(options) {
|
|
|
2157
2152
|
for (const cascaded of applied.cascadeNodeIds ?? []) await abandonNode(cascaded, authorizedBy, "cancel_task cascade");
|
|
2158
2153
|
}
|
|
2159
2154
|
};
|
|
2160
|
-
/** Severs a cancelled node's dispatched branch
|
|
2155
|
+
/** Severs a cancelled node's dispatched branch. */
|
|
2161
2156
|
const abandonNode = async (nodeId, authorizedBy, reason) => {
|
|
2162
2157
|
const root = nodeRootOf(nodeId);
|
|
2163
2158
|
if (root === void 0) return;
|
|
@@ -2262,7 +2257,7 @@ function planRunner(options) {
|
|
|
2262
2257
|
return entry.seq;
|
|
2263
2258
|
};
|
|
2264
2259
|
/**
|
|
2265
|
-
* The rung-resolved dispatch fields of a laddered node
|
|
2260
|
+
* The rung-resolved dispatch fields of a laddered node:
|
|
2266
2261
|
* the concrete ModelRef enters the attempt's identity hash, the rung
|
|
2267
2262
|
* caps bind as usage limits (maxTokens reads as the per-turn output
|
|
2268
2263
|
* cap, so maxTurns x maxTokens bounds the worst-case failed attempt),
|
|
@@ -2288,7 +2283,7 @@ function planRunner(options) {
|
|
|
2288
2283
|
};
|
|
2289
2284
|
/**
|
|
2290
2285
|
* Runs the acceptance gates of one settled ok attempt in declaration
|
|
2291
|
-
* order, fail fast
|
|
2286
|
+
* order, fail fast. Every evaluation is a decision entry
|
|
2292
2287
|
* (kind 'decision', decisionType 'gate-verdict') computed once live and
|
|
2293
2288
|
* recovered by content key on re-execution; the spot-check draw is
|
|
2294
2289
|
* io.random (journaled ctx.random, never Math.random).
|
|
@@ -2374,7 +2369,7 @@ function planRunner(options) {
|
|
|
2374
2369
|
return { pass: true };
|
|
2375
2370
|
};
|
|
2376
2371
|
/**
|
|
2377
|
-
* One judge invocation
|
|
2372
|
+
* One judge invocation: a bounded child dispatch on the
|
|
2378
2373
|
* declared rung with the forced verdict schema. Identity is DERIVED
|
|
2379
2374
|
* (never minted live) so a re-executed turn replays the same judge by
|
|
2380
2375
|
* content match. A judge that itself errors fails CLOSED: acceptance
|
|
@@ -2420,7 +2415,7 @@ function planRunner(options) {
|
|
|
2420
2415
|
}
|
|
2421
2416
|
};
|
|
2422
2417
|
/**
|
|
2423
|
-
* The ladder driver of one settled attempt (
|
|
2418
|
+
* The ladder driver of one settled attempt (DEF-2/DEF-3).
|
|
2424
2419
|
* Returns 'raised' when the next rung attempt was authorized and
|
|
2425
2420
|
* dispatched (the node STAYS running under a new handle); 'none' when
|
|
2426
2421
|
* the ordinary terminal landing proceeds; or a forced terminal status
|
|
@@ -2604,7 +2599,7 @@ function planRunner(options) {
|
|
|
2604
2599
|
return (entry.value?.input ?? {}).kind;
|
|
2605
2600
|
};
|
|
2606
2601
|
/**
|
|
2607
|
-
* Writes THE authoritative escalation-decision entry
|
|
2602
|
+
* Writes THE authoritative escalation-decision entry:
|
|
2608
2603
|
* idempotent by content key (decide-once per report); the counting
|
|
2609
2604
|
* debit is atomic with the append and a DENIED debit lands
|
|
2610
2605
|
* termination.denied strictly before, flipping the entry to
|
|
@@ -2666,7 +2661,7 @@ function planRunner(options) {
|
|
|
2666
2661
|
return entry;
|
|
2667
2662
|
};
|
|
2668
2663
|
/**
|
|
2669
|
-
* Applies one decided escalation to the plan
|
|
2664
|
+
* Applies one decided escalation to the plan: the
|
|
2670
2665
|
* resolve_escalation op (retry re-opens the node in place, accept
|
|
2671
2666
|
* closes it done, cancel closes it cancelled and severs the branch,
|
|
2672
2667
|
* decompose leaves it escalated while the admitted children carry the
|
|
@@ -2709,9 +2704,9 @@ function planRunner(options) {
|
|
|
2709
2704
|
await scheduleReady();
|
|
2710
2705
|
};
|
|
2711
2706
|
/**
|
|
2712
|
-
* Decomposition admissions
|
|
2713
|
-
* admitted spawn with a FRESH lineage minted inside the decision
|
|
2714
|
-
*
|
|
2707
|
+
* Decomposition admissions: each proposed child is an
|
|
2708
|
+
* admitted spawn with a FRESH lineage minted inside the decision
|
|
2709
|
+
* entry; the spawn debits ride the decision.
|
|
2715
2710
|
*/
|
|
2716
2711
|
const admitDecomposition = (children) => {
|
|
2717
2712
|
const rows = [];
|
|
@@ -2740,7 +2735,7 @@ function planRunner(options) {
|
|
|
2740
2735
|
};
|
|
2741
2736
|
/**
|
|
2742
2737
|
* Absorbs the DEF-4 winner of a Flavor B suspension into the
|
|
2743
|
-
* authoritative decision (
|
|
2738
|
+
* authoritative decision (the resolution entry closes the
|
|
2744
2739
|
* suspension FIRST; the plan.decision references it strictly after).
|
|
2745
2740
|
* The timeout defaultDecision, a live onEscalation decision, and a
|
|
2746
2741
|
* class-level fan-out all land here through their journaled `by`.
|
|
@@ -2770,8 +2765,8 @@ function planRunner(options) {
|
|
|
2770
2765
|
return true;
|
|
2771
2766
|
};
|
|
2772
2767
|
/**
|
|
2773
|
-
* Lands revision-transform escalation resolutions
|
|
2774
|
-
* cancel_task on an escalated node): the authoritative decision with
|
|
2768
|
+
* Lands revision-transform escalation resolutions
|
|
2769
|
+
* (cancel_task on an escalated node): the authoritative decision with
|
|
2775
2770
|
* verdict cancel, then the resolve_escalation plan.decision, then the
|
|
2776
2771
|
* severing abandon; all idempotent for the roll-forward path.
|
|
2777
2772
|
*/
|
|
@@ -2833,7 +2828,7 @@ function planRunner(options) {
|
|
|
2833
2828
|
}
|
|
2834
2829
|
};
|
|
2835
2830
|
/**
|
|
2836
|
-
* The class-level decision
|
|
2831
|
+
* The class-level decision: ONE entry resolving N
|
|
2837
2832
|
* same-kind reports, per-lineage debits embedded as `debits` rows,
|
|
2838
2833
|
* resolvedBy 'class'. Returns undefined when any counting debit would
|
|
2839
2834
|
* be denied (the caller degrades to single-target decisions).
|
|
@@ -2969,7 +2964,7 @@ function planRunner(options) {
|
|
|
2969
2964
|
}
|
|
2970
2965
|
};
|
|
2971
2966
|
/**
|
|
2972
|
-
* A retry decision's amendments
|
|
2967
|
+
* A retry decision's amendments: amendedPrompt and
|
|
2973
2968
|
* startTier ride the journaled decision, so the re-dispatch is a pure
|
|
2974
2969
|
* function of the journal, identical live and on replay.
|
|
2975
2970
|
*/
|
|
@@ -3494,8 +3489,7 @@ function orchestratePlanned(engine, goal, opts) {
|
|
|
3494
3489
|
//#endregion
|
|
3495
3490
|
//#region src/cassettes.ts
|
|
3496
3491
|
/**
|
|
3497
|
-
* M7 gating cassette runners (M7-T14
|
|
3498
|
-
* docs/11, section "Frozen journal fixtures").
|
|
3492
|
+
* M7 gating cassette runners (M7-T14).
|
|
3499
3493
|
*
|
|
3500
3494
|
* Every scenario runs fully offline on a scripted adapter over the
|
|
3501
3495
|
* PUBLIC provider SPI and produces a NORMALIZED journal: wall clock,
|
|
@@ -3659,7 +3653,7 @@ async function settled(handle) {
|
|
|
3659
3653
|
}
|
|
3660
3654
|
/**
|
|
3661
3655
|
* revise-mid-run: a plan revision arrives while a worker subtree is
|
|
3662
|
-
* mid-flight
|
|
3656
|
+
* mid-flight. The first worker HANGS until the
|
|
3663
3657
|
* revision cancels it; the added replacement completes.
|
|
3664
3658
|
*/
|
|
3665
3659
|
async function runReviseMidRun() {
|
|
@@ -3735,7 +3729,7 @@ function assignedNodeIn(req) {
|
|
|
3735
3729
|
}
|
|
3736
3730
|
/**
|
|
3737
3731
|
* crash-during-revision: process death INSIDE the revision window, at
|
|
3738
|
-
* the pre-append kill point
|
|
3732
|
+
* the pre-append kill point: life 1 is truncated
|
|
3739
3733
|
* strictly BEFORE the second plan.revision entry; life 2 re-issues the
|
|
3740
3734
|
* revision live and rolls its effects forward.
|
|
3741
3735
|
*/
|
|
@@ -3804,7 +3798,7 @@ async function runCrashDuringRevision() {
|
|
|
3804
3798
|
}
|
|
3805
3799
|
/**
|
|
3806
3800
|
* oscillation-freeze: the coarse-signature oscillation detector freezes
|
|
3807
|
-
* further re-adds under hysteresis (
|
|
3801
|
+
* further re-adds under hysteresis (distinct from the
|
|
3808
3802
|
* per-key osc_guard reject).
|
|
3809
3803
|
*/
|
|
3810
3804
|
async function runOscillationFreeze(options) {
|
|
@@ -3858,7 +3852,7 @@ async function runOscillationFreeze(options) {
|
|
|
3858
3852
|
}
|
|
3859
3853
|
/**
|
|
3860
3854
|
* park-unpark: park of a running node with checkpoint retention, later
|
|
3861
|
-
* unpark and continuation
|
|
3855
|
+
* unpark and continuation. The worker
|
|
3862
3856
|
* pays one tool turn, hangs in its second, parks at the boundary, and
|
|
3863
3857
|
* the unparked continuation resumes from the retained checkpoint (the
|
|
3864
3858
|
* booted history carries the paid turn).
|
|
@@ -4010,7 +4004,7 @@ function ladderScript(strongTurn) {
|
|
|
4010
4004
|
/**
|
|
4011
4005
|
* half-escalated-ladder: some rungs terminal, the active rung dangling
|
|
4012
4006
|
* mid-attempt at the crash; resume continues the ladder without
|
|
4013
|
-
* repaying completed rungs
|
|
4007
|
+
* repaying completed rungs.
|
|
4014
4008
|
*/
|
|
4015
4009
|
async function runHalfEscalatedLadder() {
|
|
4016
4010
|
const adapter = cassetteAdapter(ladderScript({ hangUntilAborted: true }));
|
|
@@ -4040,7 +4034,7 @@ async function runHalfEscalatedLadder() {
|
|
|
4040
4034
|
/**
|
|
4041
4035
|
* budget-denied-rung: the budget guard denies the rung respawn; the
|
|
4042
4036
|
* denial journals as termination.denied strictly before the verdict and
|
|
4043
|
-
* the ladder takes its declared fallback path
|
|
4037
|
+
* the ladder takes its declared fallback path.
|
|
4044
4038
|
*/
|
|
4045
4039
|
async function runBudgetDeniedRung() {
|
|
4046
4040
|
const adapter = cassetteAdapter(ladderScript({ text: "never reached" }));
|
|
@@ -4093,7 +4087,7 @@ function capScript(finalTurn) {
|
|
|
4093
4087
|
* cap-freeze-then-finish (DEF-7): the soft boundary crossed with live
|
|
4094
4088
|
* children; the cap decision precedes its effects; admitted nodes run to
|
|
4095
4089
|
* completion; the final quiescence wake gets the finish-only toolset;
|
|
4096
|
-
* outcome ok with forcedFinish
|
|
4090
|
+
* outcome ok with forcedFinish.
|
|
4097
4091
|
*/
|
|
4098
4092
|
async function runCapFreezeThenFinish() {
|
|
4099
4093
|
const adapter = cassetteAdapter(capScript(() => ({ toolCall: {
|
|
@@ -4276,7 +4270,7 @@ async function runRungRetryLineage() {
|
|
|
4276
4270
|
/**
|
|
4277
4271
|
* decompose-mints-children (DEF-3): an escalation decomposition mints
|
|
4278
4272
|
* FRESH logical tasks inside the decision entry; the spawn debits ride
|
|
4279
|
-
* the same entry
|
|
4273
|
+
* the same entry.
|
|
4280
4274
|
*/
|
|
4281
4275
|
async function runDecomposeMintsChildren() {
|
|
4282
4276
|
let phase = 0;
|
|
@@ -4387,8 +4381,7 @@ async function runQueueFailoverDuringForcedFinish(deps) {
|
|
|
4387
4381
|
//#region src/m9-cassettes.ts
|
|
4388
4382
|
/**
|
|
4389
4383
|
* M9 catalog completion runners: the DEF-2 and DEF-3 cassette rows that
|
|
4390
|
-
* were deferred at M7 (M9-T04
|
|
4391
|
-
* section "Gating cassette sets per milestone", M9 row).
|
|
4384
|
+
* were deferred at M7 (M9-T04).
|
|
4392
4385
|
*
|
|
4393
4386
|
* Same discipline as the M7 runners (cassettes.ts): every scenario runs
|
|
4394
4387
|
* fully offline on the scripted adapter over the PUBLIC provider SPI,
|
|
@@ -5421,7 +5414,7 @@ async function runLegacyJournalResume() {
|
|
|
5421
5414
|
* rungs burn their single turn on the echo tool (limit, raise) and whose
|
|
5422
5415
|
* top rung is scriptable. Severing the node mid-top-rung leaves the two
|
|
5423
5416
|
* completed rung attempts as ELIGIBLE PAID entries under the node's
|
|
5424
|
-
* coverage, which is exactly what a graft donor needs
|
|
5417
|
+
* coverage, which is exactly what a graft donor needs.
|
|
5425
5418
|
*/
|
|
5426
5419
|
function graftLadderProfile(isolation) {
|
|
5427
5420
|
return {
|
|
@@ -5491,7 +5484,7 @@ function linkEntriesOf(entries) {
|
|
|
5491
5484
|
* reuse_full: the verdict is embedded in the plan.revision, the
|
|
5492
5485
|
* node.link (mode full, claim shared) and the by-ref root are present,
|
|
5493
5486
|
* the reused subtree costs zero live calls, and reclaimedUsdAtLink
|
|
5494
|
-
* equals the donor spend
|
|
5487
|
+
* equals the donor spend.
|
|
5495
5488
|
*/
|
|
5496
5489
|
async function runOscillationFullReuse() {
|
|
5497
5490
|
let phase = 0;
|
|
@@ -5568,7 +5561,7 @@ async function runOscillationFullReuse() {
|
|
|
5568
5561
|
* mid-top-rung after two completed rung attempts; the byte-identical
|
|
5569
5562
|
* re-add grafts (exclusive link), the completed rung attempts
|
|
5570
5563
|
* forward-match through the scope alias, and only the interrupted rung
|
|
5571
|
-
* reruns live, exactly once
|
|
5564
|
+
* reruns live, exactly once.
|
|
5572
5565
|
*/
|
|
5573
5566
|
async function runGraftPartialSubtree() {
|
|
5574
5567
|
let phase = 0;
|
|
@@ -5653,7 +5646,7 @@ async function runGraftPartialSubtree() {
|
|
|
5653
5646
|
* crash-between-link-and-root (DEF-5): the full-reuse scenario is cut
|
|
5654
5647
|
* strictly AFTER the durable node.link and BEFORE the by-ref root; the
|
|
5655
5648
|
* resume rolls forward: the link forward-matches, the root is re-issued,
|
|
5656
|
-
* and nothing is paid twice
|
|
5649
|
+
* and nothing is paid twice.
|
|
5657
5650
|
*/
|
|
5658
5651
|
async function runCrashBetweenLinkAndRoot() {
|
|
5659
5652
|
const script = (state) => {
|
|
@@ -5743,7 +5736,7 @@ async function runCrashBetweenLinkAndRoot() {
|
|
|
5743
5736
|
* oscillation-guard-trip (DEF-5): the third re-add of one SpawnKey at
|
|
5744
5737
|
* maxOscillationsPerKey 2 rejects osc_guard as a typed plan_revise
|
|
5745
5738
|
* error; the run closes through the non-HITL path and the embedded
|
|
5746
|
-
* verdicts replay identically
|
|
5739
|
+
* verdicts replay identically.
|
|
5747
5740
|
*/
|
|
5748
5741
|
async function runOscillationGuardTrip() {
|
|
5749
5742
|
let phase = 0;
|
|
@@ -5817,8 +5810,8 @@ async function runOscillationGuardTrip() {
|
|
|
5817
5810
|
* worktree-disposed-degrade (DEF-5): a worktree-isolated graft donor
|
|
5818
5811
|
* whose tree was NOT retained degrades to a fresh admit with the
|
|
5819
5812
|
* embedded DedupNote graft_unsafe; a second section verifies reuse_full
|
|
5820
|
-
* stays allowed for a worktree donor whose root is terminal (
|
|
5821
|
-
*
|
|
5813
|
+
* stays allowed for a worktree donor whose root is terminal (the pin
|
|
5814
|
+
* condition applies to grafts only).
|
|
5822
5815
|
*/
|
|
5823
5816
|
async function runWorktreeDisposedDegrade() {
|
|
5824
5817
|
let phase = 0;
|
|
@@ -5941,7 +5934,7 @@ async function runWorktreeDisposedDegrade() {
|
|
|
5941
5934
|
* tasks; the first grafts (exclusive claim), the second admits fresh;
|
|
5942
5935
|
* the grafted node is severed and the key added a third time: the link
|
|
5943
5936
|
* points at the chain head and the drain is transitive, oldest first;
|
|
5944
|
-
* oscillationCount for the key reaches 2
|
|
5937
|
+
* oscillationCount for the key reaches 2.
|
|
5945
5938
|
*/
|
|
5946
5939
|
async function runClaimExclusivityAndChain() {
|
|
5947
5940
|
let phase = 0;
|
|
@@ -6027,7 +6020,7 @@ async function runClaimExclusivityAndChain() {
|
|
|
6027
6020
|
* done, a second node escalates, and a third completes; the wake
|
|
6028
6021
|
* submits ONE stale-based revision {waive_dep, park_task, cancel_task}
|
|
6029
6022
|
* whose trio drops with the exact reasons and the blockingRef pointing
|
|
6030
|
-
* at the defaultDecision resolution
|
|
6023
|
+
* at the defaultDecision resolution.
|
|
6031
6024
|
*/
|
|
6032
6025
|
async function runReviseRacingDefaultDecision() {
|
|
6033
6026
|
let phase = 0;
|
|
@@ -6144,7 +6137,7 @@ async function runReviseRacingDefaultDecision() {
|
|
|
6144
6137
|
* crash-after-append-before-effects (DEF-8): the kill lands immediately
|
|
6145
6138
|
* after the durable plan.revision carrying add_task x2 plus cancel_task
|
|
6146
6139
|
* on a running node; the resume re-issues the effects: both children
|
|
6147
|
-
* spawn live exactly once and the cancel lands
|
|
6140
|
+
* spawn live exactly once and the cancel lands.
|
|
6148
6141
|
*/
|
|
6149
6142
|
async function runCrashAfterAppendBeforeEffects() {
|
|
6150
6143
|
const script = (state) => {
|
|
@@ -6225,7 +6218,7 @@ async function runCrashAfterAppendBeforeEffects() {
|
|
|
6225
6218
|
* amend-vs-running-then-cancel-add (DEF-8): amend_task on a running node
|
|
6226
6219
|
* drops node_running; the next revision cancels it and adds the amended
|
|
6227
6220
|
* prompt as a NEW node continuing the SAME logical task; the abandon
|
|
6228
|
-
* covers the old branch and replay repays neither
|
|
6221
|
+
* covers the old branch and replay repays neither.
|
|
6229
6222
|
*/
|
|
6230
6223
|
async function runAmendVsRunningThenCancelAdd() {
|
|
6231
6224
|
let phase = 0;
|
|
@@ -6290,7 +6283,7 @@ async function runAmendVsRunningThenCancelAdd() {
|
|
|
6290
6283
|
* intra-revision-self-conflict (DEF-8): one revision {cancel_task X,
|
|
6291
6284
|
* amend_task X, rewire_deps with an edge onto X} resolves strictly in
|
|
6292
6285
|
* submission order per the sequential intra-revision application
|
|
6293
|
-
* semantics
|
|
6286
|
+
* semantics.
|
|
6294
6287
|
*/
|
|
6295
6288
|
async function runIntraRevisionSelfConflict() {
|
|
6296
6289
|
let phase = 0;
|
|
@@ -6365,7 +6358,7 @@ async function runIntraRevisionSelfConflict() {
|
|
|
6365
6358
|
* bad-base-streak-terminates (DEF-8): three consecutive revisions with a
|
|
6366
6359
|
* fabricated base.planHash land as all-dropped bad-base entries; the
|
|
6367
6360
|
* dropped streak reaches its limit and the non-HITL RevisionGuards
|
|
6368
|
-
* fallback (finish-with-partial) closes the run
|
|
6361
|
+
* fallback (finish-with-partial) closes the run.
|
|
6369
6362
|
*/
|
|
6370
6363
|
async function runBadBaseStreakTerminates() {
|
|
6371
6364
|
let phase = 0;
|
|
@@ -6403,7 +6396,7 @@ async function runBadBaseStreakTerminates() {
|
|
|
6403
6396
|
* park-races-child-completion (DEF-8): park_task lands on a running node
|
|
6404
6397
|
* whose terminal appends moments later; parkRequested is extinguished by
|
|
6405
6398
|
* the child-result transition, no checkpoint is written, and the node is
|
|
6406
|
-
* done
|
|
6399
|
+
* done.
|
|
6407
6400
|
*/
|
|
6408
6401
|
async function runParkRacesChildCompletion() {
|
|
6409
6402
|
let phase = 0;
|
|
@@ -6474,7 +6467,7 @@ async function runParkRacesChildCompletion() {
|
|
|
6474
6467
|
* reserve-survives-run-exhaustion (DEF-7): cheap workers eat the run
|
|
6475
6468
|
* ceiling until admission rejects the spawn that would invade the
|
|
6476
6469
|
* committed finalize reserve; the final wake executes from the reserve
|
|
6477
|
-
* and the rejections forward-match on replay
|
|
6470
|
+
* and the rejections forward-match on replay.
|
|
6478
6471
|
*/
|
|
6479
6472
|
async function runReserveSurvivesRunExhaustion() {
|
|
6480
6473
|
let phase = 0;
|
|
@@ -6647,7 +6640,7 @@ function planScenario() {
|
|
|
6647
6640
|
};
|
|
6648
6641
|
}
|
|
6649
6642
|
/**
|
|
6650
|
-
* kb-pin-replay
|
|
6643
|
+
* kb-pin-replay: the pin at admission and the repin at
|
|
6651
6644
|
* the wake, card bytes embedded, model names withheld.
|
|
6652
6645
|
*/
|
|
6653
6646
|
async function runKbPinReplay() {
|
|
@@ -6672,7 +6665,7 @@ async function runKbPinReplay() {
|
|
|
6672
6665
|
return normalizeAdaptiveJournal(entries);
|
|
6673
6666
|
}
|
|
6674
6667
|
/**
|
|
6675
|
-
* kb-repin-expiry
|
|
6668
|
+
* kb-repin-expiry: the repin re-applies the claim
|
|
6676
6669
|
* filters against a FRESH read; a claim the store dropped between the
|
|
6677
6670
|
* pin and the wake stops steering, while the boot pin's bytes stand.
|
|
6678
6671
|
*/
|