@rulvar/core 1.229.0 → 1.231.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +185 -8
  2. package/dist/index.js +1121 -938
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8708,6 +8708,12 @@ function assertFencedWrites(stores) {
8708
8708
  //#region src/stores/reconcile.ts
8709
8709
  /** The decisionType of the journaled run settle entry. */
8710
8710
  const RUN_SETTLE_DECISION_TYPE = "run_settle";
8711
+ /**
8712
+ * The decisionType of the journaled spawn admission (RV2702): the
8713
+ * entry that names every child an orchestration judged, which is what
8714
+ * makes an offline roster a read rather than a guess.
8715
+ */
8716
+ const SPAWN_ADMISSION_DECISION_TYPE = "spawn-admission";
8711
8717
  const RUN_STATUSES = /* @__PURE__ */ new Set([
8712
8718
  "ok",
8713
8719
  "error",
@@ -8788,13 +8794,25 @@ function readRejectedFinishCandidates(raw) {
8788
8794
  *
8789
8795
  * The twenty-fifth comparison run was killed and resumed, and its two
8790
8796
  * terminals mixed both kinds with nothing marking which was which: the
8791
- * money was cumulative, the wake count and the replay figures were not,
8797
+ * money was cumulative, the live-only counters were not,
8792
8798
  * and reconciling them into one honest account of the logical run was
8793
8799
  * hand work over a joined journal. Keys are field paths as a consumer
8794
- * reads them off `RunOutcome` (`cost.orchestrator.wakes`); the
8795
- * doctrine test holds this table against the keys a real outcome
8796
- * carries, so a new terminal field cannot ship without declaring what
8797
- * it counts.
8800
+ * reads them off `RunOutcome` (`cost.orchestrator.wakes`): the type
8801
+ * requires every field of the outcome, and the `satisfies` below
8802
+ * requires every counted leaf under `cost` (RV2801), because an index
8803
+ * signature admits nested paths and demands none, so the five that were
8804
+ * declared were declared by hand and by luck while four
8805
+ * (`cost.usageApprox`, `cost.abandoned.usd`, `cost.abandoned.usageApprox`,
8806
+ * `cost.orchestrator.share`) were simply missing. That is the RV2701
8807
+ * blindness one level down: a gate whose subject is nested figures
8808
+ * cannot stop at the top level.
8809
+ *
8810
+ * What neither can decide is whether a declared scope is TRUE, and a
8811
+ * wrong scope is worse than a missing one: a missing one is noticed, a
8812
+ * wrong one is believed. The doctrine test suspends a real run, resumes
8813
+ * it, and holds every declared figure against its own claim (RV2801),
8814
+ * which is how three `cost.orchestrator.*` paths were found calling
8815
+ * themselves `'segment'` while the terminal folded them cumulatively.
8798
8816
  */
8799
8817
  const TERMINAL_TELEMETRY_SCOPE = Object.freeze({
8800
8818
  status: "terminal",
@@ -8808,6 +8826,7 @@ const TERMINAL_TELEMETRY_SCOPE = Object.freeze({
8808
8826
  salvagedTerminalOutputChildren: "cumulative",
8809
8827
  belowFloorOkChildren: "cumulative",
8810
8828
  acceptanceChildren: "cumulative",
8829
+ childrenAtFailure: "cumulative",
8811
8830
  semanticPasses: "terminal",
8812
8831
  claimConsistencyMeta: "terminal",
8813
8832
  synthesisSkipped: "terminal",
@@ -8822,10 +8841,14 @@ const TERMINAL_TELEMETRY_SCOPE = Object.freeze({
8822
8841
  "cost.totalUsd": "cumulative",
8823
8842
  "cost.grossUsd": "cumulative",
8824
8843
  "cost.wireRequests": "cumulative",
8844
+ "cost.usageApprox": "cumulative",
8845
+ "cost.abandoned.usd": "cumulative",
8846
+ "cost.abandoned.usageApprox": "cumulative",
8825
8847
  "cost.orchestrator.spentUsd": "cumulative",
8826
- "cost.orchestrator.wakes": "segment",
8827
- "cost.orchestrator.forcedFinish": "segment",
8828
- "cost.orchestrator.reserveUsedUsd": "segment",
8848
+ "cost.orchestrator.share": "cumulative",
8849
+ "cost.orchestrator.wakes": "cumulative",
8850
+ "cost.orchestrator.forcedFinish": "cumulative",
8851
+ "cost.orchestrator.reserveUsedUsd": "cumulative",
8829
8852
  transportRetries: "segment",
8830
8853
  schemaRejectedFinishExchanges: "segment",
8831
8854
  schemaRecoveredFinishExchanges: "segment"
@@ -8869,6 +8892,91 @@ function logicalRunTelemetry(entries) {
8869
8892
  entriesAfterLastSettle: sinceLastSettle
8870
8893
  };
8871
8894
  }
8895
+ /**
8896
+ * Every orchestration's children, folded from a run's journal (RV2702).
8897
+ *
8898
+ * `childrenAtFailure` (RV2602) answers this for a LIVE consumer, and it
8899
+ * dies with the process that held it: the settle persists the
8900
+ * completion lift and nothing else, so a post-mortem over a journal,
8901
+ * which is all a paid run leaves behind, had no way to ask what the
8902
+ * children produced. Every ingredient was already written down. This
8903
+ * is the fold.
8904
+ *
8905
+ * It reads what resume reads. A `spawn-admission` decision names every
8906
+ * child the controller judged, with its ordinal, its profile, its
8907
+ * verdict, and the scope its dispatch pins to; the dispatch and
8908
+ * terminal `agent` entries under that scope are the child itself, and
8909
+ * the RV806 evidence verdict rides the terminal. Nothing is
8910
+ * re-derived and no validator runs again, so a journal written by any
8911
+ * prior version reads exactly as well as today's, which is the point:
8912
+ * the runs worth a post-mortem are the ones already in the archive.
8913
+ *
8914
+ * Two things it deliberately does NOT claim. It is not the live
8915
+ * roster: this reading happens after the RV1903 exit barrier settled
8916
+ * the stragglers, so a child the live field would have called
8917
+ * unsettled usually has a terminal here, and `status` is absent only
8918
+ * where the journal truly ends mid-flight. And it names children by
8919
+ * their dispatch seq rather than by nodeId, because the seq is the
8920
+ * handle the orchestrator's own turns used and the one a reader can
8921
+ * follow into the transcript.
8922
+ */
8923
+ function childRostersFromJournal(entries) {
8924
+ const rosters = /* @__PURE__ */ new Map();
8925
+ const ordered = [...entries].sort((a, b) => a.seq - b.seq);
8926
+ const abandoned = buildAbandonFold(ordered);
8927
+ const dispatchesByScope = /* @__PURE__ */ new Map();
8928
+ const terminalsByScopeKey = /* @__PURE__ */ new Map();
8929
+ for (const entry of ordered) {
8930
+ if (entry.kind !== "agent") continue;
8931
+ if (entry.status === "running") {
8932
+ const rows = dispatchesByScope.get(entry.scope);
8933
+ if (rows === void 0) dispatchesByScope.set(entry.scope, [entry]);
8934
+ else rows.push(entry);
8935
+ continue;
8936
+ }
8937
+ const key = JSON.stringify([entry.scope, entry.key]);
8938
+ const rows = terminalsByScopeKey.get(key);
8939
+ if (rows === void 0) terminalsByScopeKey.set(key, [entry]);
8940
+ else rows.push(entry);
8941
+ }
8942
+ const cursors = /* @__PURE__ */ new Map();
8943
+ for (const entry of ordered) {
8944
+ if (entry.kind !== "decision") continue;
8945
+ const value = entry.value;
8946
+ if (value?.decisionType !== "spawn-admission" || value.origin !== "spawn_agent" && value.origin !== "parallel_agents") continue;
8947
+ const childScope = typeof value.childScope === "string" ? value.childScope : entry.scope;
8948
+ let roster = rosters.get(childScope);
8949
+ if (roster === void 0) {
8950
+ roster = {
8951
+ childScope,
8952
+ admitted: 0,
8953
+ rejected: 0,
8954
+ children: []
8955
+ };
8956
+ rosters.set(childScope, roster);
8957
+ }
8958
+ if (value.decision?.verdict?.kind !== "admit") {
8959
+ roster.rejected += 1;
8960
+ continue;
8961
+ }
8962
+ roster.admitted += 1;
8963
+ const rows = dispatchesByScope.get(childScope) ?? [];
8964
+ let cursor = cursors.get(childScope) ?? 0;
8965
+ while (cursor < rows.length && (rows[cursor]?.seq ?? 0) <= entry.seq) cursor += 1;
8966
+ const dispatch = rows[cursor];
8967
+ cursors.set(childScope, cursor + 1);
8968
+ if (dispatch === void 0) continue;
8969
+ const terminal = terminalsByScopeKey.get(JSON.stringify([childScope, dispatch.key]))?.find((candidate) => candidate.seq > dispatch.seq);
8970
+ roster.children.push({
8971
+ handle: dispatch.seq,
8972
+ ...abandoned.isAbandoned(dispatch.seq) ? { abandoned: true } : {},
8973
+ ...terminal?.costAttribution?.agentType === void 0 ? {} : { agentType: terminal.costAttribution.agentType },
8974
+ ...terminal === void 0 ? {} : { status: terminal.status },
8975
+ ...terminal?.evidence === void 0 ? {} : { evidence: { ...terminal.evidence } }
8976
+ });
8977
+ }
8978
+ return [...rosters.values()];
8979
+ }
8872
8980
  function structure(entries) {
8873
8981
  const referenced = /* @__PURE__ */ new Set();
8874
8982
  for (const entry of entries) if (entry.ref !== void 0) referenced.add(entry.ref);
@@ -8983,472 +9091,834 @@ async function reconcileRunMeta(store, runId, opts) {
8983
9091
  };
8984
9092
  }
8985
9093
  //#endregion
8986
- //#region src/stores/jsonl.ts
8987
- /**
8988
- * JsonlFileStore (M2-T01): the durable file store. One JSON entry per
8989
- * line per run; the journal doubles as an event log. Meta records live
8990
- * beside the journal and are replaced atomically, so listRuns never
8991
- * parses payloads.
8992
- *
8993
- * Contract (DEF-4 tightening):
8994
- * - A1 atomicity: a torn trailing line (crash mid-append) is never
8995
- * visible in load; the incomplete fragment is dropped and overwritten
8996
- * by the next append. Whole records on that line are data, never
8997
- * fragment (RV701): a crash that persisted every JSON byte but not
8998
- * the '\n' leaves a parseable tail that load serves and append
8999
- * terminates before writing, and repair salvages complete records a
9000
- * glued line carries instead of discarding the line, so an entry a
9001
- * load has served can never be un-served by a later repair.
9002
- * - A2 total per-run order: load returns append order, stable across
9003
- * calls (the kernel's per-run queue serializes appends).
9004
- * - A3 read-your-writes: append resolves after the line is written.
9005
- * - A4 opaque payload: entries round-trip byte-for-byte as JSON; unknown
9006
- * kinds and fields pass through untouched.
9007
- *
9008
- * Leasing is NOT implemented here: LeasableStore ships with
9009
- * @rulvar/store-sqlite (M5); JsonlFileStore is single-writer by
9010
- * convention.
9011
- */
9012
- const JOURNAL_SUFFIX = ".jsonl";
9013
- const META_SUFFIX = ".meta.json";
9014
- function safeName(runId) {
9015
- if (!/^[A-Za-z0-9._-]+$/.test(runId)) throw new JournalOrderViolation(`JsonlFileStore: runId '${runId}' is not filesystem-safe ([A-Za-z0-9._-] only)`);
9016
- return runId;
9017
- }
9094
+ //#region src/l0/telemetry-reduce.ts
9095
+ const ZERO = {
9096
+ inputTokens: 0,
9097
+ outputTokens: 0,
9098
+ cacheReadTokens: 0,
9099
+ cacheWriteTokens: 0
9100
+ };
9018
9101
  /**
9019
- * Whole JSON values glued on one line, split apart without parser
9020
- * ambiguity (RV701): depth is tracked outside string literals only, and
9021
- * every candidate must still round-trip JSON.parse. A line that is not a
9022
- * clean concatenation from its first byte salvages its whole prefix
9023
- * values and returns everything after them as the torn fragment, so the
9024
- * caller keeps accepted records and drops exactly the unacknowledged
9025
- * tail a crash tore.
9102
+ * Reduces one run's event stream (or any slice of it) to the invocation
9103
+ * table. Feed it the events in emission order; both a live stream and a
9104
+ * replayed one produce the same usage and cost columns.
9026
9105
  */
9027
- function splitConcatenatedJson(line) {
9028
- const whole = [];
9029
- let start = 0;
9030
- let depth = 0;
9031
- let inString = false;
9032
- let escaped = false;
9033
- for (let i = 0; i < line.length; i += 1) {
9034
- const ch = line[i];
9035
- if (inString) {
9036
- if (escaped) escaped = false;
9037
- else if (ch === "\\") escaped = true;
9038
- else if (ch === "\"") inString = false;
9039
- continue;
9040
- }
9041
- if (ch === "\"") {
9042
- inString = true;
9043
- continue;
9106
+ function reduceInvocationTable(events) {
9107
+ const rows = /* @__PURE__ */ new Map();
9108
+ const order = [];
9109
+ const openPhases = /* @__PURE__ */ new Map();
9110
+ const byRole = {};
9111
+ let totalCostUsd = 0;
9112
+ const rowFor = (event) => {
9113
+ let row = rows.get(event.spanId);
9114
+ if (row === void 0) {
9115
+ row = {
9116
+ spanId: event.spanId,
9117
+ agentType: event.agentType,
9118
+ ...event.label === void 0 ? {} : { label: event.label },
9119
+ usage: ZERO,
9120
+ costUsd: 0,
9121
+ costBasis: "aggregate-estimate",
9122
+ usageApprox: false,
9123
+ retryCount: 0,
9124
+ replayed: event.replayed === true,
9125
+ open: true,
9126
+ phases: []
9127
+ };
9128
+ rows.set(event.spanId, row);
9129
+ order.push(row);
9044
9130
  }
9045
- if (ch === "{" || ch === "[") {
9046
- depth += 1;
9047
- continue;
9131
+ return row;
9132
+ };
9133
+ for (const event of events) switch (event.type) {
9134
+ case "agent:start": {
9135
+ const row = rowFor(event);
9136
+ row.role = event.role;
9137
+ break;
9048
9138
  }
9049
- if (ch === "}" || ch === "]") {
9050
- depth -= 1;
9051
- if (depth < 0) return {
9052
- whole,
9053
- fragment: line.slice(start)
9139
+ case "agent:phase:start": {
9140
+ const row = rowFor(event);
9141
+ const phase = {
9142
+ invocation: event.invocation,
9143
+ role: event.role,
9144
+ model: event.model,
9145
+ durationMs: 0,
9146
+ usage: ZERO,
9147
+ costUsd: 0,
9148
+ costBasis: "aggregate-estimate",
9149
+ retries: 0,
9150
+ replayed: event.replayed === true,
9151
+ open: true
9054
9152
  };
9055
- if (depth === 0) {
9056
- const candidate = line.slice(start, i + 1);
9057
- try {
9058
- whole.push(JSON.parse(candidate));
9059
- } catch {
9060
- return {
9061
- whole,
9062
- fragment: line.slice(start)
9063
- };
9064
- }
9065
- start = i + 1;
9153
+ row.phases.push(phase);
9154
+ openPhases.set(`${event.spanId}#${event.invocation}`, phase);
9155
+ break;
9156
+ }
9157
+ case "agent:phase:end": {
9158
+ const key = `${event.spanId}#${event.invocation}`;
9159
+ let phase = openPhases.get(key);
9160
+ if (phase === void 0) {
9161
+ phase = {
9162
+ invocation: event.invocation,
9163
+ role: event.role,
9164
+ model: event.model,
9165
+ durationMs: 0,
9166
+ usage: ZERO,
9167
+ costUsd: 0,
9168
+ costBasis: "aggregate-estimate",
9169
+ retries: 0,
9170
+ replayed: event.replayed === true,
9171
+ open: true
9172
+ };
9173
+ rowFor(event).phases.push(phase);
9066
9174
  }
9175
+ openPhases.delete(key);
9176
+ phase.open = false;
9177
+ phase.role = event.role;
9178
+ phase.model = event.model;
9179
+ phase.durationMs = event.durationMs;
9180
+ phase.usage = event.usage;
9181
+ phase.costUsd = event.costUsd;
9182
+ phase.costBasis = event.costBasis ?? "aggregate-estimate";
9183
+ phase.outcome = event.outcome;
9184
+ phase.retries = event.retries ?? 0;
9185
+ const bucket = byRole[event.role] ??= {
9186
+ usage: ZERO,
9187
+ costUsd: 0,
9188
+ costBasis: "per-call"
9189
+ };
9190
+ bucket.usage = sumUsage(bucket.usage, event.usage);
9191
+ bucket.costUsd += event.costUsd;
9192
+ if (phase.costBasis === "aggregate-estimate") bucket.costBasis = "aggregate-estimate";
9193
+ break;
9194
+ }
9195
+ case "agent:end": {
9196
+ const row = rowFor(event);
9197
+ row.open = false;
9198
+ row.status = event.status;
9199
+ row.usage = event.usage;
9200
+ row.costUsd = event.costUsd;
9201
+ row.costBasis = event.costBasis ?? "aggregate-estimate";
9202
+ row.usageApprox = event.usageApprox === true;
9203
+ row.retryCount = event.retryCount ?? 0;
9204
+ if (event.toolBudget !== void 0) row.toolBudget = event.toolBudget;
9205
+ totalCostUsd += event.costUsd;
9206
+ break;
9067
9207
  }
9208
+ default: break;
9068
9209
  }
9069
9210
  return {
9070
- whole,
9071
- fragment: line.slice(start)
9211
+ agents: order,
9212
+ byRole,
9213
+ totalCostUsd
9072
9214
  };
9073
9215
  }
9074
- var JsonlFileStore = class {
9075
- dir;
9076
- /**
9077
- * The stored tail seq per run, lazily initialized from the file on the
9078
- * first append this instance performs (obligation A5). Per instance by
9079
- * design: cross-process writers are the lease seam's job.
9080
- */
9081
- lastSeq = /* @__PURE__ */ new Map();
9082
- /**
9083
- * The verify-only load switch (RV1512): with `repairOnLoad: false`,
9084
- * `load` serves the salvageable records WITHOUT rewriting the file,
9085
- * so an auditor's "verification" read never destroys the evidence
9086
- * of a tear it found. The default keeps the owner semantics byte
9087
- * for byte: a torn tail repairs on load exactly as documented in
9088
- * the A1 model above. Mutations (`append`, `putMeta`, `delete`)
9089
- * are unaffected by the flag; an auditor that must not write simply
9090
- * does not call them.
9091
- */
9092
- repairOnLoad;
9093
- constructor(options) {
9094
- this.dir = options.dir;
9095
- this.repairOnLoad = options.repairOnLoad !== false;
9096
- mkdirSync(this.dir, { recursive: true });
9097
- }
9098
- journalPath(runId) {
9099
- return join(this.dir, `${safeName(runId)}${JOURNAL_SUFFIX}`);
9100
- }
9101
- metaPath(runId) {
9102
- return join(this.dir, `${safeName(runId)}${META_SUFFIX}`);
9103
- }
9104
- async append(runId, e) {
9105
- let tail = this.lastSeq.get(runId);
9106
- if (tail === void 0) {
9107
- const existing = await this.load(runId);
9108
- this.terminateUnterminatedTail(runId);
9109
- const last = existing[existing.length - 1];
9110
- tail = last !== void 0 && Number.isFinite(last.seq) ? last.seq : Number.NEGATIVE_INFINITY;
9111
- this.lastSeq.set(runId, tail);
9112
- }
9113
- if (Number.isFinite(e.seq) && e.seq <= tail) throw new JournalOrderViolation(`JsonlFileStore: append of seq ${e.seq} to run '${runId}' is not after the stored tail seq ${tail}; a concurrent writer raced this journal from a stale tail`);
9114
- appendFileSync(this.journalPath(runId), `${JSON.stringify(e)}\n`, "utf8");
9115
- if (Number.isFinite(e.seq)) this.lastSeq.set(runId, e.seq);
9116
- }
9117
- async load(runId) {
9118
- let raw;
9119
- try {
9120
- raw = readFileSync(this.journalPath(runId), "utf8");
9121
- } catch (thrown) {
9122
- if (thrown.code === "ENOENT") return [];
9123
- throw thrown;
9124
- }
9125
- const lines = raw.split("\n");
9126
- const entries = [];
9127
- for (let i = 0; i < lines.length; i += 1) {
9128
- const line = lines[i] ?? "";
9129
- if (line === "") continue;
9130
- try {
9131
- entries.push(JSON.parse(line));
9132
- } catch (thrown) {
9133
- if (lines.slice(i + 1).every((rest) => rest === "")) {
9134
- for (const value of splitConcatenatedJson(line).whole) entries.push(value);
9135
- if (this.repairOnLoad) this.repairTornTail(runId, entries);
9136
- break;
9216
+ /**
9217
+ * The label the claim-consistency judge invocation dispatches under
9218
+ * (RV1502; named here since RV1604 so the critical-path reducer and the
9219
+ * orchestrator share one constant): the judge rides role 'synthesize',
9220
+ * and this label is what tells its wall apart from a real final
9221
+ * composition in {@link reduceCriticalPath}.
9222
+ */
9223
+ const CLAIM_JUDGE_LABEL = "claim-consistency-judge";
9224
+ /** Total length of the union of possibly overlapping intervals. */
9225
+ function unionLength(intervals) {
9226
+ const positive = intervals.filter((interval) => interval.to > interval.from);
9227
+ if (positive.length === 0) return 0;
9228
+ const sorted = [...positive].sort((a, b) => a.from - b.from);
9229
+ let total = 0;
9230
+ let from = sorted[0]?.from ?? 0;
9231
+ let to = sorted[0]?.to ?? 0;
9232
+ for (const interval of sorted.slice(1)) if (interval.from > to) {
9233
+ total += to - from;
9234
+ from = interval.from;
9235
+ to = interval.to;
9236
+ } else if (interval.to > to) to = interval.to;
9237
+ return total + (to - from);
9238
+ }
9239
+ function reduceCriticalPath(events) {
9240
+ let runStart;
9241
+ let runEnd;
9242
+ const startBySpan = /* @__PURE__ */ new Map();
9243
+ let lastWorkerEnd;
9244
+ let workerSpans = 0;
9245
+ let synthesisMs = 0;
9246
+ let finalCompositionMs = 0;
9247
+ let semanticJudgeMs = 0;
9248
+ const coordinationModel = [];
9249
+ const coordinationTools = [];
9250
+ const synthesisSpans = [];
9251
+ const spanOf = (durationMs) => Number.isFinite(durationMs) && durationMs > 0 ? durationMs : 0;
9252
+ for (const event of events) {
9253
+ const at = Date.parse(event.ts);
9254
+ if (!Number.isFinite(at)) continue;
9255
+ switch (event.type) {
9256
+ case "run:start":
9257
+ runStart ??= at;
9258
+ break;
9259
+ case "run:end":
9260
+ runEnd = at;
9261
+ break;
9262
+ case "agent:start":
9263
+ startBySpan.set(event.spanId, {
9264
+ role: event.role,
9265
+ at,
9266
+ ...event.label === void 0 ? {} : { label: event.label }
9267
+ });
9268
+ break;
9269
+ case "agent:phase:end":
9270
+ if (startBySpan.get(event.spanId)?.role === "orchestrate") coordinationModel.push({
9271
+ phase: event.role,
9272
+ from: at - spanOf(event.durationMs),
9273
+ to: at
9274
+ });
9275
+ break;
9276
+ case "tool:end":
9277
+ if (startBySpan.get(event.spanId)?.role === "orchestrate") coordinationTools.push({
9278
+ name: event.toolName,
9279
+ from: at - spanOf(event.durationMs),
9280
+ to: at
9281
+ });
9282
+ break;
9283
+ case "agent:end": {
9284
+ const started = startBySpan.get(event.spanId);
9285
+ if (started === void 0) break;
9286
+ if (started.role === "synthesize") {
9287
+ const wall = Math.max(0, at - started.at);
9288
+ const judge = started.label === CLAIM_JUDGE_LABEL;
9289
+ synthesisMs += wall;
9290
+ if (judge) semanticJudgeMs += wall;
9291
+ else finalCompositionMs += wall;
9292
+ synthesisSpans.push({
9293
+ from: started.at,
9294
+ to: at,
9295
+ judge
9296
+ });
9297
+ } else if (started.role !== "orchestrate") {
9298
+ workerSpans += 1;
9299
+ lastWorkerEnd = lastWorkerEnd === void 0 ? at : Math.max(lastWorkerEnd, at);
9137
9300
  }
9138
- throw new JournalOrderViolation(`JsonlFileStore: corrupt journal line ${i + 1} of run '${runId}' (not the trailing line, so this is not a torn append)`, { cause: thrown });
9301
+ break;
9139
9302
  }
9303
+ default: break;
9140
9304
  }
9141
- return entries;
9142
9305
  }
9143
- /**
9144
- * Restores the trailing '\n' of a parseable-but-unterminated tail
9145
- * (RV701). One byte appended in place terminates the record exactly
9146
- * where the crash left it; the file's bytes before it stay untouched.
9147
- * No-op on a missing, empty, or already-terminated journal.
9148
- */
9149
- terminateUnterminatedTail(runId) {
9150
- const path = this.journalPath(runId);
9151
- let fd;
9152
- try {
9153
- fd = openSync(path, "r");
9154
- } catch (thrown) {
9155
- if (thrown.code === "ENOENT") return;
9156
- throw thrown;
9157
- }
9158
- let needsNewline = false;
9159
- try {
9160
- const size = fstatSync(fd).size;
9161
- if (size > 0) {
9162
- const lastByte = /* @__PURE__ */ new Uint8Array(1);
9163
- readSync(fd, lastByte, 0, 1, size - 1);
9164
- needsNewline = lastByte[0] !== 10;
9165
- }
9166
- } finally {
9167
- closeSync(fd);
9306
+ const path = {
9307
+ synthesisMs,
9308
+ finalCompositionMs,
9309
+ semanticJudgeMs,
9310
+ workerSpans
9311
+ };
9312
+ if (runStart !== void 0 && runEnd !== void 0) path.runWallMs = Math.max(0, runEnd - runStart);
9313
+ if (runEnd !== void 0 && lastWorkerEnd !== void 0) {
9314
+ path.postFanInMs = Math.max(0, runEnd - lastWorkerEnd);
9315
+ const windowFrom = Math.min(lastWorkerEnd, runEnd);
9316
+ const windowTo = runEnd;
9317
+ const clip = (interval) => {
9318
+ if (interval.to < windowFrom || interval.from > windowTo) return;
9319
+ return {
9320
+ from: Math.max(interval.from, windowFrom),
9321
+ to: Math.min(interval.to, windowTo)
9322
+ };
9323
+ };
9324
+ const byPhase = {};
9325
+ const modelClipped = [];
9326
+ for (const interval of coordinationModel) {
9327
+ const clipped = clip(interval);
9328
+ if (clipped === void 0) continue;
9329
+ byPhase[interval.phase] = (byPhase[interval.phase] ?? 0) + (clipped.to - clipped.from);
9330
+ modelClipped.push(clipped);
9168
9331
  }
9169
- if (needsNewline) appendFileSync(path, "\n", "utf8");
9170
- }
9171
- repairTornTail(runId, whole) {
9172
- const path = this.journalPath(runId);
9173
- const temp = `${path}.tmp`;
9174
- writeFileSync(temp, whole.map((entry) => JSON.stringify(entry)).join("\n") + (whole.length > 0 ? "\n" : ""), "utf8");
9175
- renameSync(temp, path);
9176
- }
9177
- async putMeta(m) {
9178
- const path = this.metaPath(m.runId);
9179
- const temp = `${path}.tmp`;
9180
- writeFileSync(temp, JSON.stringify(m, null, 2), "utf8");
9181
- renameSync(temp, path);
9182
- }
9183
- async getMeta(runId) {
9184
- try {
9185
- return JSON.parse(readFileSync(this.metaPath(runId), "utf8"));
9186
- } catch {
9187
- return;
9332
+ const synthesisClipped = [];
9333
+ let judgeClippedMs = 0;
9334
+ let compositionClippedMs = 0;
9335
+ for (const span of synthesisSpans) {
9336
+ const clipped = clip(span);
9337
+ if (clipped === void 0) continue;
9338
+ synthesisClipped.push(clipped);
9339
+ if (span.judge) judgeClippedMs += clipped.to - clipped.from;
9340
+ else compositionClippedMs += clipped.to - clipped.from;
9188
9341
  }
9189
- }
9190
- async listRuns(f) {
9191
- const metas = [];
9192
- for (const file of readdirSync(this.dir)) {
9193
- if (!file.endsWith(META_SUFFIX)) continue;
9194
- try {
9195
- metas.push(JSON.parse(readFileSync(join(this.dir, file), "utf8")));
9196
- } catch {}
9342
+ const byName = {};
9343
+ const callsByName = {};
9344
+ const toolsClipped = [];
9345
+ for (const interval of coordinationTools) {
9346
+ const clipped = clip(interval);
9347
+ if (clipped === void 0) continue;
9348
+ byName[interval.name] = (byName[interval.name] ?? 0) + (clipped.to - clipped.from);
9349
+ callsByName[interval.name] = (callsByName[interval.name] ?? 0) + 1;
9350
+ toolsClipped.push(clipped);
9197
9351
  }
9198
- return metas.filter((meta) => metaMatchesFilter(meta, f));
9352
+ const lengthOf = (intervals) => intervals.reduce((sum, interval) => sum + (interval.to - interval.from), 0);
9353
+ const coveredMs = unionLength([
9354
+ ...modelClipped,
9355
+ ...toolsClipped,
9356
+ ...synthesisClipped
9357
+ ]);
9358
+ const modelOnlyMs = unionLength([...modelClipped, ...toolsClipped]) - unionLength(toolsClipped);
9359
+ const breakdown = {
9360
+ coordinationModelMs: lengthOf(modelClipped),
9361
+ coordinationModelMsByPhase: byPhase,
9362
+ coordinationModelOnlyMs: modelOnlyMs,
9363
+ coordinationToolMs: lengthOf(toolsClipped),
9364
+ coordinationToolMsByName: byName,
9365
+ coordinationToolCallsByName: callsByName,
9366
+ synthesisMs: lengthOf(synthesisClipped),
9367
+ finalCompositionMs: compositionClippedMs,
9368
+ semanticJudgeMs: judgeClippedMs,
9369
+ coveredMs,
9370
+ residueMs: Math.max(0, path.postFanInMs - coveredMs)
9371
+ };
9372
+ if (path.postFanInMs > 0) breakdown.residueShare = breakdown.residueMs / path.postFanInMs;
9373
+ path.postFanIn = breakdown;
9199
9374
  }
9200
- async delete(runId) {
9201
- rmSync(this.journalPath(runId), { force: true });
9202
- rmSync(this.metaPath(runId), { force: true });
9203
- this.lastSeq.delete(runId);
9375
+ if (path.runWallMs !== void 0 && path.runWallMs > 0) {
9376
+ if (path.postFanInMs !== void 0) path.postFanInShare = path.postFanInMs / path.runWallMs;
9377
+ path.synthesisShare = synthesisMs / path.runWallMs;
9204
9378
  }
9379
+ return path;
9380
+ }
9381
+ //#endregion
9382
+ //#region src/stores/critical-path.ts
9383
+ const parse = (at) => {
9384
+ if (at === void 0) return;
9385
+ const ms = Date.parse(at);
9386
+ return Number.isFinite(ms) ? ms : void 0;
9205
9387
  };
9206
- const TRANSCRIPT_SUFFIX = ".bin";
9207
9388
  /**
9208
- * File-backed TranscriptStore (M6-T02): blobs (transcripts, checkpoints,
9209
- * persisted CompiledWorkflow sources) as one file per ref under `dir`,
9210
- * so compiled runs resume across processes. Refs follow the
9211
- * `<runId>/<name>` convention; nested segments become directories.
9389
+ * Fold a run's critical path out of its journal.
9212
9390
  *
9213
- * Every ref is contained under `dir` (v1.36.0 review SEC-P1): each
9214
- * segment must match `[A-Za-z0-9._-]` and be neither empty, '.', nor
9215
- * '..', and the resolved path must stay under the resolved root. A '..'
9216
- * segment used to pass the per-segment alphabet (dots are in it) and, via
9217
- * `join`, escape the root; a caller passing an untrusted ref (or an
9218
- * untrusted runId, which prefixes checkpoint and workflow-source refs)
9219
- * could read, write, or delete `.bin` files outside `dir`.
9391
+ * @param entries the journal of one run, in any order
9220
9392
  */
9221
- var FileTranscriptStore = class {
9222
- dir;
9223
- constructor(options) {
9224
- this.dir = options.dir;
9225
- mkdirSync(this.dir, { recursive: true });
9226
- }
9227
- blobPath(ref) {
9228
- const segments = ref.split("/");
9229
- for (const segment of segments) if (segment === "" || segment === "." || segment === ".." || !/^[A-Za-z0-9._-]+$/.test(segment)) throw new JournalOrderViolation(`FileTranscriptStore: ref segment '${segment}' is not filesystem-safe`);
9230
- const name = segments.pop() ?? "";
9231
- const path = join(this.dir, ...segments, `${name}${TRANSCRIPT_SUFFIX}`);
9232
- const root = resolve(this.dir);
9233
- const resolved = resolve(path);
9234
- if (resolved !== root && !resolved.startsWith(`${root}${sep}`)) throw new JournalOrderViolation(`FileTranscriptStore: ref '${ref}' resolves outside the configured root`);
9235
- return path;
9236
- }
9237
- async put(ref, blob) {
9238
- const path = this.blobPath(ref);
9239
- mkdirSync(dirname(path), { recursive: true });
9240
- const temp = `${path}.tmp`;
9241
- writeFileSync(temp, blob);
9242
- renameSync(temp, path);
9243
- }
9244
- async get(ref) {
9245
- try {
9246
- return new Uint8Array(readFileSync(this.blobPath(ref)));
9247
- } catch (error) {
9248
- if (error.code === "ENOENT") return null;
9249
- throw error;
9250
- }
9251
- }
9252
- async list(runId) {
9253
- if (runId === "." || runId === "..") throw new JournalOrderViolation(`FileTranscriptStore: runId '${runId}' is not filesystem-safe`);
9254
- const root = join(this.dir, safeName(runId));
9255
- const refs = [];
9256
- const walk = (dir, prefix) => {
9257
- let names;
9258
- try {
9259
- names = readdirSync(dir);
9260
- } catch {
9261
- return;
9262
- }
9263
- for (const name of names) {
9264
- const path = join(dir, name);
9265
- if (statSync(path).isDirectory()) walk(path, `${prefix}${name}/`);
9266
- else if (name.endsWith(TRANSCRIPT_SUFFIX)) refs.push(`${prefix}${name.slice(0, -4)}`);
9267
- }
9268
- };
9269
- walk(root, `${runId}/`);
9270
- return refs.sort();
9271
- }
9272
- async delete(ref) {
9273
- try {
9274
- rmSync(this.blobPath(ref));
9275
- } catch (error) {
9276
- if (error.code !== "ENOENT") throw error;
9393
+ function criticalPathFromJournal(entries) {
9394
+ const ordered = [...entries].sort((a, b) => a.seq - b.seq);
9395
+ let runStart;
9396
+ let runEnd;
9397
+ let lastWorkerEnd;
9398
+ let workerSpans = 0;
9399
+ let unclassifiedSpans = 0;
9400
+ let synthesisMs = 0;
9401
+ let finalCompositionMs = 0;
9402
+ let semanticJudgeMs = 0;
9403
+ let labelledSynthesis = false;
9404
+ let unlabelledSynthesis = false;
9405
+ for (const entry of ordered) {
9406
+ const startedAt = parse(entry.startedAt);
9407
+ const endedAt = parse(entry.endedAt);
9408
+ if (startedAt !== void 0) runStart = runStart === void 0 ? startedAt : Math.min(runStart, startedAt);
9409
+ const last = endedAt ?? startedAt;
9410
+ if (last !== void 0) runEnd = runEnd === void 0 ? last : Math.max(runEnd, last);
9411
+ if (entry.kind !== "agent" || entry.status === "running" || entry.status === "suspended") continue;
9412
+ const role = entry.costAttribution?.role;
9413
+ if (role === void 0) {
9414
+ unclassifiedSpans += 1;
9415
+ continue;
9277
9416
  }
9278
- }
9279
- };
9280
- //#endregion
9281
- //#region src/model/pricing.ts
9282
- /**
9283
- * Resolves the pricing for a model: the versioned table wins; the
9284
- * adapter-reported caps.pricing is the fallback; undefined means
9285
- * unpriced (the CostReport surfaces it, never a silent zero).
9286
- */
9287
- function resolvePricing(ref, table, capsPricing) {
9288
- return table?.models[ref] ?? capsPricing;
9289
- }
9290
- /** The tier a full prompt lands in: the highest threshold strictly below it. */
9291
- function tierFor(pricing, inputTokens) {
9292
- let tier;
9293
- for (const candidate of pricing.tiers ?? []) if (inputTokens > candidate.aboveInputTokens && (tier === void 0 || candidate.aboveInputTokens > tier.aboveInputTokens)) tier = candidate;
9294
- return tier;
9295
- }
9296
- /**
9297
- * Decomposes one usage against one pricing row into the four billing
9298
- * components. Under the Usage invariant inputTokens is the FULL prompt
9299
- * including cache reads and writes, so the input rate bills only the
9300
- * uncached remainder and cache tokens bill at their own rates, never
9301
- * twice; a row that omits a cache rate bills those tokens at the plain
9302
- * input rate rather than silently for free. A row may carry
9303
- * long-context tiers: the highest threshold strictly below the full
9304
- * prompt re-prices the ENTIRE request (input-side rates scale by
9305
- * inputMultiplier, the output rate by outputMultiplier). Cache writes
9306
- * price at the 5m premium rate by default; when the usage carries the
9307
- * TTL split (RV810: `cacheWrite5mTokens` and `cacheWrite1hTokens`,
9308
- * filled by adapters whose provider distinguishes write TTLs), the 1h
9309
- * share prices at `cacheWrite1hUsdPerMTok` (falling back to the plain
9310
- * write rate when the row lacks it) and everything the 1h share does
9311
- * not claim, the 5m share plus any unattributed remainder an upstream
9312
- * invariant violation left, bills at the write rate, never silently
9313
- * for free. The component's `tokens` stays the WHOLE
9314
- * `cacheWriteTokens` either way, so statement reconciliation keys are
9315
- * unchanged.
9316
- */
9317
- function priceComponentsOf(pricing, usage) {
9318
- const tier = tierFor(pricing, usage.inputTokens);
9319
- const inputMul = tier?.inputMultiplier ?? 1;
9320
- const outputMul = tier?.outputMultiplier ?? 1;
9321
- const uncachedInputTokens = Math.max(0, usage.inputTokens - usage.cacheReadTokens - usage.cacheWriteTokens);
9322
- const writeRate = pricing.cacheWriteUsdPerMTok ?? pricing.inputUsdPerMTok;
9323
- const write1hRate = pricing.cacheWrite1hUsdPerMTok ?? writeRate;
9324
- const write1hTokens = usage.cacheWrite5mTokens !== void 0 || usage.cacheWrite1hTokens !== void 0 ? usage.cacheWrite1hTokens ?? 0 : 0;
9325
- const writeDefaultTokens = Math.max(0, usage.cacheWriteTokens - write1hTokens);
9326
- return {
9327
- input: {
9328
- tokens: uncachedInputTokens,
9329
- usd: uncachedInputTokens / 1e6 * pricing.inputUsdPerMTok * inputMul
9330
- },
9331
- output: {
9332
- tokens: usage.outputTokens,
9333
- usd: usage.outputTokens / 1e6 * pricing.outputUsdPerMTok * outputMul
9334
- },
9335
- cachedInput: {
9336
- tokens: usage.cacheReadTokens,
9337
- usd: usage.cacheReadTokens / 1e6 * (pricing.cacheReadUsdPerMTok ?? pricing.inputUsdPerMTok) * inputMul
9338
- },
9339
- cacheWrite: {
9340
- tokens: usage.cacheWriteTokens,
9341
- usd: (writeDefaultTokens / 1e6 * writeRate + write1hTokens / 1e6 * write1hRate) * inputMul
9417
+ if (role === "orchestrate") continue;
9418
+ if (role !== "synthesize") {
9419
+ workerSpans += 1;
9420
+ if (endedAt !== void 0) lastWorkerEnd = lastWorkerEnd === void 0 ? endedAt : Math.max(lastWorkerEnd, endedAt);
9421
+ continue;
9342
9422
  }
9343
- };
9344
- }
9345
- /**
9346
- * Dollars from normalized usage against one pricing row: the sum of the
9347
- * {@link priceComponentsOf} terms in their declared order, byte for
9348
- * byte the historical expression (uncached input, output, cached input,
9349
- * cache writes).
9350
- */
9351
- function priceUsdOf(pricing, usage) {
9352
- const parts = priceComponentsOf(pricing, usage);
9353
- return parts.input.usd + parts.output.usd + parts.cachedInput.usd + parts.cacheWrite.usd;
9354
- }
9355
- /**
9356
- * The output tokens `remainingUsd` still buys from one pricing row after
9357
- * paying for an estimated prompt of `estimatedInputTokens`, priced with
9358
- * the same tier rules as settlement (the tier is selected by the
9359
- * estimated prompt). Floored to whole tokens; zero or negative means not
9360
- * even one output token fits, so the turn must not be dispatched.
9361
- * Undefined when the row prices output at zero (a free model needs no
9362
- * output bound).
9363
- */
9364
- function affordableOutputTokens(pricing, remainingUsd, estimatedInputTokens) {
9365
- const tier = tierFor(pricing, estimatedInputTokens);
9366
- const outputRate = pricing.outputUsdPerMTok * (tier?.outputMultiplier ?? 1);
9367
- if (outputRate <= 0) return;
9368
- const inputUsd = priceUsdOf(pricing, {
9369
- inputTokens: estimatedInputTokens,
9370
- outputTokens: 0,
9371
- cacheReadTokens: 0,
9372
- cacheWriteTokens: 0
9373
- });
9374
- return Math.floor((remainingUsd - inputUsd) / outputRate * 1e6);
9375
- }
9376
- const RATE_FIELDS = [
9377
- "inputUsdPerMTok",
9378
- "outputUsdPerMTok",
9379
- "cacheReadUsdPerMTok",
9380
- "cacheWriteUsdPerMTok",
9381
- "cacheWrite1hUsdPerMTok"
9382
- ];
9383
- const TIER_FIELDS = [
9384
- "aboveInputTokens",
9385
- "inputMultiplier",
9386
- "outputMultiplier"
9387
- ];
9388
- /**
9389
- * Compares a pricing seed against rates extracted from the provider's
9390
- * documented pricing page, in BOTH directions (RV902): a seed rate the
9391
- * page moved or dropped is a finding, and so is a documented billable
9392
- * rate the seed never declared, because a billable column missing from
9393
- * the seed is a silent underpricing channel (the 1h cache-write premium
9394
- * hid exactly there). Declared long-context tiers compare field by
9395
- * field. Returns human-readable findings, empty when the sides agree;
9396
- * the weekly rates audit (scripts/rates-audit.mjs) runs this exact
9397
- * comparator over the live pages, and the fault-injection kit drives it
9398
- * as a permanent gate (RV909). It verifies DOCUMENTATION, not billing:
9399
- * only a statement reconciliation over saved exports settles what the
9400
- * provider's meter actually charges.
9401
- */
9402
- function compareRates(seed, page) {
9403
- const findings = [];
9404
- for (const field of RATE_FIELDS) {
9405
- const seedValue = seed[field];
9406
- const pageValue = page[field];
9407
- if (seedValue === void 0) {
9408
- if (pageValue !== void 0) findings.push(`${field}: the page shows ${String(pageValue)} but the seed declares no such rate`);
9423
+ if (startedAt === void 0 || endedAt === void 0) continue;
9424
+ const wall = Math.max(0, endedAt - startedAt);
9425
+ synthesisMs += wall;
9426
+ const label = entry.costAttribution?.label;
9427
+ if (label === void 0) {
9428
+ unlabelledSynthesis = true;
9409
9429
  continue;
9410
9430
  }
9411
- if (pageValue === void 0) findings.push(`${field}: seed ${String(seedValue)} but the page shows no such rate`);
9412
- else if (!(Math.abs(seedValue - pageValue) <= 1e-9)) findings.push(`${field}: seed ${String(seedValue)} vs page ${String(pageValue)}`);
9431
+ labelledSynthesis = true;
9432
+ if (label === "claim-consistency-judge" || label.startsWith(`claim-consistency-judge-`)) semanticJudgeMs += wall;
9433
+ else finalCompositionMs += wall;
9413
9434
  }
9414
- const seedTiers = seed.tiers;
9415
- const pageTiers = page.tiers;
9416
- if (!Array.isArray(seedTiers)) {
9417
- if (Array.isArray(pageTiers) && pageTiers.length > 0) findings.push(`tiers: the page shows ${String(pageTiers.length)} but the seed declares none`);
9418
- } else if (!Array.isArray(pageTiers) || pageTiers.length !== seedTiers.length) findings.push(`tiers: seed declares ${String(seedTiers.length)}, page shows ${Array.isArray(pageTiers) ? String(pageTiers.length) : "none"}`);
9419
- else for (let i = 0; i < seedTiers.length; i += 1) for (const field of TIER_FIELDS) {
9420
- const seedValue = seedTiers[i]?.[field] ?? NaN;
9421
- const pageValue = pageTiers[i]?.[field] ?? NaN;
9422
- if (!(Math.abs(seedValue - pageValue) <= 1e-9)) findings.push(`tiers[${String(i)}].${field}: seed ${String(seedValue)} vs page ${String(pageValue)}`);
9435
+ const segments = logicalRunTelemetry(ordered).segments;
9436
+ const path = {
9437
+ workerSpans,
9438
+ synthesisMs,
9439
+ unclassifiedSpans,
9440
+ segments
9441
+ };
9442
+ if (labelledSynthesis && !unlabelledSynthesis) {
9443
+ path.finalCompositionMs = finalCompositionMs;
9444
+ path.semanticJudgeMs = semanticJudgeMs;
9445
+ }
9446
+ if (segments > 1 || runStart === void 0 || runEnd === void 0) return path;
9447
+ path.runWallMs = Math.max(0, runEnd - runStart);
9448
+ if (lastWorkerEnd !== void 0) path.postFanInMs = Math.max(0, runEnd - lastWorkerEnd);
9449
+ if (path.runWallMs > 0) {
9450
+ if (path.postFanInMs !== void 0) path.postFanInShare = path.postFanInMs / path.runWallMs;
9451
+ path.synthesisShare = synthesisMs / path.runWallMs;
9423
9452
  }
9424
- return findings;
9453
+ return path;
9425
9454
  }
9426
9455
  //#endregion
9427
- //#region src/model/quota.ts
9456
+ //#region src/stores/jsonl.ts
9428
9457
  /**
9429
- * Quota rules and the in-process reference QuotaLimiter (RV-215).
9430
- * The rule model is shared by every reference implementation
9431
- * (memoryQuotaLimiter here, SqliteQuotaLimiter in
9432
- * @rulvar/store-sqlite): fixed one-minute windows aligned to the
9433
- * epoch, admission at reservation time, reconciliation to actual
9434
- * usage inside the same window. The hard guarantee is on
9435
- * `requestsPerMinute` (every wire attempt is exactly one request);
9436
- * `tokensPerMinute` admits on the heuristic estimate and settles to
9437
- * actual usage, so token windows are approximate at admission and
9438
- * exact at settlement.
9458
+ * JsonlFileStore (M2-T01): the durable file store. One JSON entry per
9459
+ * line per run; the journal doubles as an event log. Meta records live
9460
+ * beside the journal and are replaced atomically, so listRuns never
9461
+ * parses payloads.
9439
9462
  *
9440
- * Docs: https://docs.rulvar.com/guide/model-routing
9463
+ * Contract (DEF-4 tightening):
9464
+ * - A1 atomicity: a torn trailing line (crash mid-append) is never
9465
+ * visible in load; the incomplete fragment is dropped and overwritten
9466
+ * by the next append. Whole records on that line are data, never
9467
+ * fragment (RV701): a crash that persisted every JSON byte but not
9468
+ * the '\n' leaves a parseable tail that load serves and append
9469
+ * terminates before writing, and repair salvages complete records a
9470
+ * glued line carries instead of discarding the line, so an entry a
9471
+ * load has served can never be un-served by a later repair.
9472
+ * - A2 total per-run order: load returns append order, stable across
9473
+ * calls (the kernel's per-run queue serializes appends).
9474
+ * - A3 read-your-writes: append resolves after the line is written.
9475
+ * - A4 opaque payload: entries round-trip byte-for-byte as JSON; unknown
9476
+ * kinds and fields pass through untouched.
9477
+ *
9478
+ * Leasing is NOT implemented here: LeasableStore ships with
9479
+ * @rulvar/store-sqlite (M5); JsonlFileStore is single-writer by
9480
+ * convention.
9441
9481
  */
9482
+ const JOURNAL_SUFFIX = ".jsonl";
9483
+ const META_SUFFIX = ".meta.json";
9484
+ function safeName(runId) {
9485
+ if (!/^[A-Za-z0-9._-]+$/.test(runId)) throw new JournalOrderViolation(`JsonlFileStore: runId '${runId}' is not filesystem-safe ([A-Za-z0-9._-] only)`);
9486
+ return runId;
9487
+ }
9442
9488
  /**
9443
- * Captured at module load, before the InProcessRunner's
9444
- * nondeterminism guard can patch the global: the limiter's clock is
9445
- * engine infrastructure on the live-only dispatch path and must never
9446
- * be blamed on workflow code.
9489
+ * Whole JSON values glued on one line, split apart without parser
9490
+ * ambiguity (RV701): depth is tracked outside string literals only, and
9491
+ * every candidate must still round-trip JSON.parse. A line that is not a
9492
+ * clean concatenation from its first byte salvages its whole prefix
9493
+ * values and returns everything after them as the torn fragment, so the
9494
+ * caller keeps accepted records and drops exactly the unacknowledged
9495
+ * tail a crash tore.
9447
9496
  */
9448
- const nativeNow = Date.now;
9449
- /** The fixed accounting window every PerMinute cap counts over. */
9450
- const QUOTA_WINDOW_MS = 6e4;
9451
- /**
9497
+ function splitConcatenatedJson(line) {
9498
+ const whole = [];
9499
+ let start = 0;
9500
+ let depth = 0;
9501
+ let inString = false;
9502
+ let escaped = false;
9503
+ for (let i = 0; i < line.length; i += 1) {
9504
+ const ch = line[i];
9505
+ if (inString) {
9506
+ if (escaped) escaped = false;
9507
+ else if (ch === "\\") escaped = true;
9508
+ else if (ch === "\"") inString = false;
9509
+ continue;
9510
+ }
9511
+ if (ch === "\"") {
9512
+ inString = true;
9513
+ continue;
9514
+ }
9515
+ if (ch === "{" || ch === "[") {
9516
+ depth += 1;
9517
+ continue;
9518
+ }
9519
+ if (ch === "}" || ch === "]") {
9520
+ depth -= 1;
9521
+ if (depth < 0) return {
9522
+ whole,
9523
+ fragment: line.slice(start)
9524
+ };
9525
+ if (depth === 0) {
9526
+ const candidate = line.slice(start, i + 1);
9527
+ try {
9528
+ whole.push(JSON.parse(candidate));
9529
+ } catch {
9530
+ return {
9531
+ whole,
9532
+ fragment: line.slice(start)
9533
+ };
9534
+ }
9535
+ start = i + 1;
9536
+ }
9537
+ }
9538
+ }
9539
+ return {
9540
+ whole,
9541
+ fragment: line.slice(start)
9542
+ };
9543
+ }
9544
+ var JsonlFileStore = class {
9545
+ dir;
9546
+ /**
9547
+ * The stored tail seq per run, lazily initialized from the file on the
9548
+ * first append this instance performs (obligation A5). Per instance by
9549
+ * design: cross-process writers are the lease seam's job.
9550
+ */
9551
+ lastSeq = /* @__PURE__ */ new Map();
9552
+ /**
9553
+ * The verify-only load switch (RV1512): with `repairOnLoad: false`,
9554
+ * `load` serves the salvageable records WITHOUT rewriting the file,
9555
+ * so an auditor's "verification" read never destroys the evidence
9556
+ * of a tear it found. The default keeps the owner semantics byte
9557
+ * for byte: a torn tail repairs on load exactly as documented in
9558
+ * the A1 model above. Mutations (`append`, `putMeta`, `delete`)
9559
+ * are unaffected by the flag; an auditor that must not write simply
9560
+ * does not call them.
9561
+ */
9562
+ repairOnLoad;
9563
+ constructor(options) {
9564
+ this.dir = options.dir;
9565
+ this.repairOnLoad = options.repairOnLoad !== false;
9566
+ mkdirSync(this.dir, { recursive: true });
9567
+ }
9568
+ journalPath(runId) {
9569
+ return join(this.dir, `${safeName(runId)}${JOURNAL_SUFFIX}`);
9570
+ }
9571
+ metaPath(runId) {
9572
+ return join(this.dir, `${safeName(runId)}${META_SUFFIX}`);
9573
+ }
9574
+ async append(runId, e) {
9575
+ let tail = this.lastSeq.get(runId);
9576
+ if (tail === void 0) {
9577
+ const existing = await this.load(runId);
9578
+ this.terminateUnterminatedTail(runId);
9579
+ const last = existing[existing.length - 1];
9580
+ tail = last !== void 0 && Number.isFinite(last.seq) ? last.seq : Number.NEGATIVE_INFINITY;
9581
+ this.lastSeq.set(runId, tail);
9582
+ }
9583
+ if (Number.isFinite(e.seq) && e.seq <= tail) throw new JournalOrderViolation(`JsonlFileStore: append of seq ${e.seq} to run '${runId}' is not after the stored tail seq ${tail}; a concurrent writer raced this journal from a stale tail`);
9584
+ appendFileSync(this.journalPath(runId), `${JSON.stringify(e)}\n`, "utf8");
9585
+ if (Number.isFinite(e.seq)) this.lastSeq.set(runId, e.seq);
9586
+ }
9587
+ async load(runId) {
9588
+ let raw;
9589
+ try {
9590
+ raw = readFileSync(this.journalPath(runId), "utf8");
9591
+ } catch (thrown) {
9592
+ if (thrown.code === "ENOENT") return [];
9593
+ throw thrown;
9594
+ }
9595
+ const lines = raw.split("\n");
9596
+ const entries = [];
9597
+ for (let i = 0; i < lines.length; i += 1) {
9598
+ const line = lines[i] ?? "";
9599
+ if (line === "") continue;
9600
+ try {
9601
+ entries.push(JSON.parse(line));
9602
+ } catch (thrown) {
9603
+ if (lines.slice(i + 1).every((rest) => rest === "")) {
9604
+ for (const value of splitConcatenatedJson(line).whole) entries.push(value);
9605
+ if (this.repairOnLoad) this.repairTornTail(runId, entries);
9606
+ break;
9607
+ }
9608
+ throw new JournalOrderViolation(`JsonlFileStore: corrupt journal line ${i + 1} of run '${runId}' (not the trailing line, so this is not a torn append)`, { cause: thrown });
9609
+ }
9610
+ }
9611
+ return entries;
9612
+ }
9613
+ /**
9614
+ * Restores the trailing '\n' of a parseable-but-unterminated tail
9615
+ * (RV701). One byte appended in place terminates the record exactly
9616
+ * where the crash left it; the file's bytes before it stay untouched.
9617
+ * No-op on a missing, empty, or already-terminated journal.
9618
+ */
9619
+ terminateUnterminatedTail(runId) {
9620
+ const path = this.journalPath(runId);
9621
+ let fd;
9622
+ try {
9623
+ fd = openSync(path, "r");
9624
+ } catch (thrown) {
9625
+ if (thrown.code === "ENOENT") return;
9626
+ throw thrown;
9627
+ }
9628
+ let needsNewline = false;
9629
+ try {
9630
+ const size = fstatSync(fd).size;
9631
+ if (size > 0) {
9632
+ const lastByte = /* @__PURE__ */ new Uint8Array(1);
9633
+ readSync(fd, lastByte, 0, 1, size - 1);
9634
+ needsNewline = lastByte[0] !== 10;
9635
+ }
9636
+ } finally {
9637
+ closeSync(fd);
9638
+ }
9639
+ if (needsNewline) appendFileSync(path, "\n", "utf8");
9640
+ }
9641
+ repairTornTail(runId, whole) {
9642
+ const path = this.journalPath(runId);
9643
+ const temp = `${path}.tmp`;
9644
+ writeFileSync(temp, whole.map((entry) => JSON.stringify(entry)).join("\n") + (whole.length > 0 ? "\n" : ""), "utf8");
9645
+ renameSync(temp, path);
9646
+ }
9647
+ async putMeta(m) {
9648
+ const path = this.metaPath(m.runId);
9649
+ const temp = `${path}.tmp`;
9650
+ writeFileSync(temp, JSON.stringify(m, null, 2), "utf8");
9651
+ renameSync(temp, path);
9652
+ }
9653
+ async getMeta(runId) {
9654
+ try {
9655
+ return JSON.parse(readFileSync(this.metaPath(runId), "utf8"));
9656
+ } catch {
9657
+ return;
9658
+ }
9659
+ }
9660
+ async listRuns(f) {
9661
+ const metas = [];
9662
+ for (const file of readdirSync(this.dir)) {
9663
+ if (!file.endsWith(META_SUFFIX)) continue;
9664
+ try {
9665
+ metas.push(JSON.parse(readFileSync(join(this.dir, file), "utf8")));
9666
+ } catch {}
9667
+ }
9668
+ return metas.filter((meta) => metaMatchesFilter(meta, f));
9669
+ }
9670
+ async delete(runId) {
9671
+ rmSync(this.journalPath(runId), { force: true });
9672
+ rmSync(this.metaPath(runId), { force: true });
9673
+ this.lastSeq.delete(runId);
9674
+ }
9675
+ };
9676
+ const TRANSCRIPT_SUFFIX = ".bin";
9677
+ /**
9678
+ * File-backed TranscriptStore (M6-T02): blobs (transcripts, checkpoints,
9679
+ * persisted CompiledWorkflow sources) as one file per ref under `dir`,
9680
+ * so compiled runs resume across processes. Refs follow the
9681
+ * `<runId>/<name>` convention; nested segments become directories.
9682
+ *
9683
+ * Every ref is contained under `dir` (v1.36.0 review SEC-P1): each
9684
+ * segment must match `[A-Za-z0-9._-]` and be neither empty, '.', nor
9685
+ * '..', and the resolved path must stay under the resolved root. A '..'
9686
+ * segment used to pass the per-segment alphabet (dots are in it) and, via
9687
+ * `join`, escape the root; a caller passing an untrusted ref (or an
9688
+ * untrusted runId, which prefixes checkpoint and workflow-source refs)
9689
+ * could read, write, or delete `.bin` files outside `dir`.
9690
+ */
9691
+ var FileTranscriptStore = class {
9692
+ dir;
9693
+ constructor(options) {
9694
+ this.dir = options.dir;
9695
+ mkdirSync(this.dir, { recursive: true });
9696
+ }
9697
+ blobPath(ref) {
9698
+ const segments = ref.split("/");
9699
+ for (const segment of segments) if (segment === "" || segment === "." || segment === ".." || !/^[A-Za-z0-9._-]+$/.test(segment)) throw new JournalOrderViolation(`FileTranscriptStore: ref segment '${segment}' is not filesystem-safe`);
9700
+ const name = segments.pop() ?? "";
9701
+ const path = join(this.dir, ...segments, `${name}${TRANSCRIPT_SUFFIX}`);
9702
+ const root = resolve(this.dir);
9703
+ const resolved = resolve(path);
9704
+ if (resolved !== root && !resolved.startsWith(`${root}${sep}`)) throw new JournalOrderViolation(`FileTranscriptStore: ref '${ref}' resolves outside the configured root`);
9705
+ return path;
9706
+ }
9707
+ async put(ref, blob) {
9708
+ const path = this.blobPath(ref);
9709
+ mkdirSync(dirname(path), { recursive: true });
9710
+ const temp = `${path}.tmp`;
9711
+ writeFileSync(temp, blob);
9712
+ renameSync(temp, path);
9713
+ }
9714
+ async get(ref) {
9715
+ try {
9716
+ return new Uint8Array(readFileSync(this.blobPath(ref)));
9717
+ } catch (error) {
9718
+ if (error.code === "ENOENT") return null;
9719
+ throw error;
9720
+ }
9721
+ }
9722
+ async list(runId) {
9723
+ if (runId === "." || runId === "..") throw new JournalOrderViolation(`FileTranscriptStore: runId '${runId}' is not filesystem-safe`);
9724
+ const root = join(this.dir, safeName(runId));
9725
+ const refs = [];
9726
+ const walk = (dir, prefix) => {
9727
+ let names;
9728
+ try {
9729
+ names = readdirSync(dir);
9730
+ } catch {
9731
+ return;
9732
+ }
9733
+ for (const name of names) {
9734
+ const path = join(dir, name);
9735
+ if (statSync(path).isDirectory()) walk(path, `${prefix}${name}/`);
9736
+ else if (name.endsWith(TRANSCRIPT_SUFFIX)) refs.push(`${prefix}${name.slice(0, -4)}`);
9737
+ }
9738
+ };
9739
+ walk(root, `${runId}/`);
9740
+ return refs.sort();
9741
+ }
9742
+ async delete(ref) {
9743
+ try {
9744
+ rmSync(this.blobPath(ref));
9745
+ } catch (error) {
9746
+ if (error.code !== "ENOENT") throw error;
9747
+ }
9748
+ }
9749
+ };
9750
+ //#endregion
9751
+ //#region src/model/pricing.ts
9752
+ /**
9753
+ * Resolves the pricing for a model: the versioned table wins; the
9754
+ * adapter-reported caps.pricing is the fallback; undefined means
9755
+ * unpriced (the CostReport surfaces it, never a silent zero).
9756
+ */
9757
+ function resolvePricing(ref, table, capsPricing) {
9758
+ return table?.models[ref] ?? capsPricing;
9759
+ }
9760
+ /** The tier a full prompt lands in: the highest threshold strictly below it. */
9761
+ function tierFor(pricing, inputTokens) {
9762
+ let tier;
9763
+ for (const candidate of pricing.tiers ?? []) if (inputTokens > candidate.aboveInputTokens && (tier === void 0 || candidate.aboveInputTokens > tier.aboveInputTokens)) tier = candidate;
9764
+ return tier;
9765
+ }
9766
+ /**
9767
+ * Decomposes one usage against one pricing row into the four billing
9768
+ * components. Under the Usage invariant inputTokens is the FULL prompt
9769
+ * including cache reads and writes, so the input rate bills only the
9770
+ * uncached remainder and cache tokens bill at their own rates, never
9771
+ * twice; a row that omits a cache rate bills those tokens at the plain
9772
+ * input rate rather than silently for free. A row may carry
9773
+ * long-context tiers: the highest threshold strictly below the full
9774
+ * prompt re-prices the ENTIRE request (input-side rates scale by
9775
+ * inputMultiplier, the output rate by outputMultiplier). Cache writes
9776
+ * price at the 5m premium rate by default; when the usage carries the
9777
+ * TTL split (RV810: `cacheWrite5mTokens` and `cacheWrite1hTokens`,
9778
+ * filled by adapters whose provider distinguishes write TTLs), the 1h
9779
+ * share prices at `cacheWrite1hUsdPerMTok` (falling back to the plain
9780
+ * write rate when the row lacks it) and everything the 1h share does
9781
+ * not claim, the 5m share plus any unattributed remainder an upstream
9782
+ * invariant violation left, bills at the write rate, never silently
9783
+ * for free. The component's `tokens` stays the WHOLE
9784
+ * `cacheWriteTokens` either way, so statement reconciliation keys are
9785
+ * unchanged.
9786
+ */
9787
+ function priceComponentsOf(pricing, usage) {
9788
+ const tier = tierFor(pricing, usage.inputTokens);
9789
+ const inputMul = tier?.inputMultiplier ?? 1;
9790
+ const outputMul = tier?.outputMultiplier ?? 1;
9791
+ const uncachedInputTokens = Math.max(0, usage.inputTokens - usage.cacheReadTokens - usage.cacheWriteTokens);
9792
+ const writeRate = pricing.cacheWriteUsdPerMTok ?? pricing.inputUsdPerMTok;
9793
+ const write1hRate = pricing.cacheWrite1hUsdPerMTok ?? writeRate;
9794
+ const write1hTokens = usage.cacheWrite5mTokens !== void 0 || usage.cacheWrite1hTokens !== void 0 ? usage.cacheWrite1hTokens ?? 0 : 0;
9795
+ const writeDefaultTokens = Math.max(0, usage.cacheWriteTokens - write1hTokens);
9796
+ return {
9797
+ input: {
9798
+ tokens: uncachedInputTokens,
9799
+ usd: uncachedInputTokens / 1e6 * pricing.inputUsdPerMTok * inputMul
9800
+ },
9801
+ output: {
9802
+ tokens: usage.outputTokens,
9803
+ usd: usage.outputTokens / 1e6 * pricing.outputUsdPerMTok * outputMul
9804
+ },
9805
+ cachedInput: {
9806
+ tokens: usage.cacheReadTokens,
9807
+ usd: usage.cacheReadTokens / 1e6 * (pricing.cacheReadUsdPerMTok ?? pricing.inputUsdPerMTok) * inputMul
9808
+ },
9809
+ cacheWrite: {
9810
+ tokens: usage.cacheWriteTokens,
9811
+ usd: (writeDefaultTokens / 1e6 * writeRate + write1hTokens / 1e6 * write1hRate) * inputMul
9812
+ }
9813
+ };
9814
+ }
9815
+ /**
9816
+ * Dollars from normalized usage against one pricing row: the sum of the
9817
+ * {@link priceComponentsOf} terms in their declared order, byte for
9818
+ * byte the historical expression (uncached input, output, cached input,
9819
+ * cache writes).
9820
+ */
9821
+ function priceUsdOf(pricing, usage) {
9822
+ const parts = priceComponentsOf(pricing, usage);
9823
+ return parts.input.usd + parts.output.usd + parts.cachedInput.usd + parts.cacheWrite.usd;
9824
+ }
9825
+ /**
9826
+ * The output tokens `remainingUsd` still buys from one pricing row after
9827
+ * paying for an estimated prompt of `estimatedInputTokens`, priced with
9828
+ * the same tier rules as settlement (the tier is selected by the
9829
+ * estimated prompt). Floored to whole tokens; zero or negative means not
9830
+ * even one output token fits, so the turn must not be dispatched.
9831
+ * Undefined when the row prices output at zero (a free model needs no
9832
+ * output bound).
9833
+ */
9834
+ function affordableOutputTokens(pricing, remainingUsd, estimatedInputTokens) {
9835
+ const tier = tierFor(pricing, estimatedInputTokens);
9836
+ const outputRate = pricing.outputUsdPerMTok * (tier?.outputMultiplier ?? 1);
9837
+ if (outputRate <= 0) return;
9838
+ const inputUsd = priceUsdOf(pricing, {
9839
+ inputTokens: estimatedInputTokens,
9840
+ outputTokens: 0,
9841
+ cacheReadTokens: 0,
9842
+ cacheWriteTokens: 0
9843
+ });
9844
+ return Math.floor((remainingUsd - inputUsd) / outputRate * 1e6);
9845
+ }
9846
+ const RATE_FIELDS = [
9847
+ "inputUsdPerMTok",
9848
+ "outputUsdPerMTok",
9849
+ "cacheReadUsdPerMTok",
9850
+ "cacheWriteUsdPerMTok",
9851
+ "cacheWrite1hUsdPerMTok"
9852
+ ];
9853
+ const TIER_FIELDS = [
9854
+ "aboveInputTokens",
9855
+ "inputMultiplier",
9856
+ "outputMultiplier"
9857
+ ];
9858
+ /**
9859
+ * Compares a pricing seed against rates extracted from the provider's
9860
+ * documented pricing page, in BOTH directions (RV902): a seed rate the
9861
+ * page moved or dropped is a finding, and so is a documented billable
9862
+ * rate the seed never declared, because a billable column missing from
9863
+ * the seed is a silent underpricing channel (the 1h cache-write premium
9864
+ * hid exactly there). Declared long-context tiers compare field by
9865
+ * field. Returns human-readable findings, empty when the sides agree;
9866
+ * the weekly rates audit (scripts/rates-audit.mjs) runs this exact
9867
+ * comparator over the live pages, and the fault-injection kit drives it
9868
+ * as a permanent gate (RV909). It verifies DOCUMENTATION, not billing:
9869
+ * only a statement reconciliation over saved exports settles what the
9870
+ * provider's meter actually charges.
9871
+ */
9872
+ function compareRates(seed, page) {
9873
+ const findings = [];
9874
+ for (const field of RATE_FIELDS) {
9875
+ const seedValue = seed[field];
9876
+ const pageValue = page[field];
9877
+ if (seedValue === void 0) {
9878
+ if (pageValue !== void 0) findings.push(`${field}: the page shows ${String(pageValue)} but the seed declares no such rate`);
9879
+ continue;
9880
+ }
9881
+ if (pageValue === void 0) findings.push(`${field}: seed ${String(seedValue)} but the page shows no such rate`);
9882
+ else if (!(Math.abs(seedValue - pageValue) <= 1e-9)) findings.push(`${field}: seed ${String(seedValue)} vs page ${String(pageValue)}`);
9883
+ }
9884
+ const seedTiers = seed.tiers;
9885
+ const pageTiers = page.tiers;
9886
+ if (!Array.isArray(seedTiers)) {
9887
+ if (Array.isArray(pageTiers) && pageTiers.length > 0) findings.push(`tiers: the page shows ${String(pageTiers.length)} but the seed declares none`);
9888
+ } else if (!Array.isArray(pageTiers) || pageTiers.length !== seedTiers.length) findings.push(`tiers: seed declares ${String(seedTiers.length)}, page shows ${Array.isArray(pageTiers) ? String(pageTiers.length) : "none"}`);
9889
+ else for (let i = 0; i < seedTiers.length; i += 1) for (const field of TIER_FIELDS) {
9890
+ const seedValue = seedTiers[i]?.[field] ?? NaN;
9891
+ const pageValue = pageTiers[i]?.[field] ?? NaN;
9892
+ if (!(Math.abs(seedValue - pageValue) <= 1e-9)) findings.push(`tiers[${String(i)}].${field}: seed ${String(seedValue)} vs page ${String(pageValue)}`);
9893
+ }
9894
+ return findings;
9895
+ }
9896
+ //#endregion
9897
+ //#region src/model/quota.ts
9898
+ /**
9899
+ * Quota rules and the in-process reference QuotaLimiter (RV-215).
9900
+ * The rule model is shared by every reference implementation
9901
+ * (memoryQuotaLimiter here, SqliteQuotaLimiter in
9902
+ * @rulvar/store-sqlite): fixed one-minute windows aligned to the
9903
+ * epoch, admission at reservation time, reconciliation to actual
9904
+ * usage inside the same window. The hard guarantee is on
9905
+ * `requestsPerMinute` (every wire attempt is exactly one request);
9906
+ * `tokensPerMinute` admits on the heuristic estimate and settles to
9907
+ * actual usage, so token windows are approximate at admission and
9908
+ * exact at settlement.
9909
+ *
9910
+ * Docs: https://docs.rulvar.com/guide/model-routing
9911
+ */
9912
+ /**
9913
+ * Captured at module load, before the InProcessRunner's
9914
+ * nondeterminism guard can patch the global: the limiter's clock is
9915
+ * engine infrastructure on the live-only dispatch path and must never
9916
+ * be blamed on workflow code.
9917
+ */
9918
+ const nativeNow = Date.now;
9919
+ /** The fixed accounting window every PerMinute cap counts over. */
9920
+ const QUOTA_WINDOW_MS = 6e4;
9921
+ /**
9452
9922
  * Validates a quota rule set as a typed ConfigError before any
9453
9923
  * limiter can admit under it: a non-array or empty set, a rule
9454
9924
  * without a cap, a malformed dimension, or a malformed cap all fail
@@ -16364,520 +16834,232 @@ var AdmissionController = class {
16364
16834
  this.lineageIndex?.noteAdmitted(logicalTaskId);
16365
16835
  }
16366
16836
  /**
16367
- * Evaluates one spawn live, strictly BEFORE its decision entry is
16368
- * appended. On admit the reserve is committed on the whole ancestor
16369
- * account chain atomically with the evaluation; the caller journals the
16370
- * returned decision and only then produces effects (child account,
16371
- * dispatch). On reject nothing is committed and the reject verdict is
16372
- * journaled by the caller so replay re-delivers it without
16373
- * re-evaluation.
16374
- */
16375
- /**
16376
- * The reserve the DISPATCH layer will actually commit for this spec:
16377
- * the estimate (or the flat default) clamped by the explicit child
16378
- * budget when one exists, because only an explicit budget opens a
16379
- * child-allowance account at dispatch; the childBudgetFraction cap
16380
- * never materializes as an account and must not shrink the
16381
- * projection. The token-count-priced estimate of ctx.agent is
16382
- * unreachable here (async); a divergence there lands as a journaled
16383
- * dispatch rejection instead of a strand. Delegates to the exported
16384
- * {@link dispatchProjectionReserveUsd} so the live gate and
16385
- * preflightEstimate share ONE formula (the 1.63.0 experiment review,
16386
- * P0.3).
16387
- */
16388
- projectedDispatchReserveUsd(spec) {
16389
- return dispatchProjectionReserveUsd(spec, this.flatReserveUsd);
16390
- }
16391
- admit(spec, options) {
16392
- const commitReserve = options?.commitReserve ?? true;
16393
- const nodeKey = spec.nodeKey ?? spec.parentAccountScope;
16394
- const depth = spawnDepthOf(spec.childScope);
16395
- const childrenBefore = this.childrenOf.get(nodeKey) ?? 0;
16396
- const evaluated = this.evaluateLineage(spec);
16397
- const statsBefore = {
16398
- spawnsBefore: this.budget.spent().agentsSpawned,
16399
- childrenOfParentBefore: childrenBefore,
16400
- depth,
16401
- ...evaluated.statsBefore === void 0 ? {} : { lineage: evaluated.statsBefore }
16402
- };
16403
- if (evaluated.decision.kind === "reject") return {
16404
- verdict: {
16405
- kind: "reject",
16406
- reason: evaluated.decision.reason
16407
- },
16408
- statsBefore
16409
- };
16410
- if (this.terminationAccount !== void 0) {
16411
- if ((spec.ladderLength ?? 1) > this.terminationAccount.limits.kMax) return {
16412
- verdict: {
16413
- kind: "reject",
16414
- reason: { code: "ladder_exceeds_frozen" }
16415
- },
16416
- statsBefore
16417
- };
16418
- if (this.terminationAccount.spawnUnitsExhausted) return {
16419
- verdict: {
16420
- kind: "reject",
16421
- reason: { code: "termination_exhausted" }
16422
- },
16423
- statsBefore
16424
- };
16425
- }
16426
- if (depth > this.maxDepth) return {
16427
- verdict: {
16428
- kind: "reject",
16429
- reason: { code: "depth" }
16430
- },
16431
- statsBefore
16432
- };
16433
- if (childrenBefore >= this.maxChildrenPerNode) return {
16434
- verdict: {
16435
- kind: "reject",
16436
- reason: { code: "quota" }
16437
- },
16438
- statsBefore
16439
- };
16440
- if (this.maxTotalSpawns !== void 0 && this.admittedTotal >= this.maxTotalSpawns) return {
16441
- verdict: {
16442
- kind: "reject",
16443
- reason: { code: "lifetime" }
16444
- },
16445
- statsBefore
16446
- };
16447
- if (spec.roster !== void 0) {
16448
- const seatsRemaining = spec.roster.floor - spec.roster.admittedChildren;
16449
- if (seatsRemaining > 0) {
16450
- const perSeatProjectionUsd = this.projectedDispatchReserveUsd(spec);
16451
- const remainder = this.budget.remainderOf(spec.parentAccountScope);
16452
- if (remainder !== void 0 && remainder < seatsRemaining * perSeatProjectionUsd + spec.roster.liveExposureUsd) return {
16453
- verdict: {
16454
- kind: "reject",
16455
- reason: {
16456
- code: "roster_floor",
16457
- floor: spec.roster.floor,
16458
- admittedChildren: spec.roster.admittedChildren,
16459
- seatsRemaining,
16460
- perSeatProjectionUsd,
16461
- liveExposureUsd: spec.roster.liveExposureUsd,
16462
- remainderUsd: remainder
16463
- }
16464
- },
16465
- statsBefore
16466
- };
16467
- }
16468
- }
16469
- const spawnToolOrigin = spec.origin === "spawn_agent" || spec.origin === "parallel_agents";
16470
- let childCeilingUsd;
16471
- const parentRemainder = this.budget.remainderOf(spec.parentAccountScope);
16472
- if (spawnToolOrigin) {
16473
- if (spec.budgetUsd !== void 0) childCeilingUsd = spec.budgetUsd;
16474
- } else if (parentRemainder !== void 0) {
16475
- const fractionCap = this.childBudgetFraction * parentRemainder;
16476
- childCeilingUsd = spec.budgetUsd === void 0 ? fractionCap : Math.min(spec.budgetUsd, fractionCap);
16477
- } else if (spec.budgetUsd !== void 0) childCeilingUsd = spec.budgetUsd;
16478
- let reserveUsd = spec.estCostUsd ?? this.flatReserveUsd;
16479
- const source = spec.estCostUsd === void 0 ? "default" : "estCost";
16480
- let clampedBy;
16481
- if (childCeilingUsd !== void 0 && reserveUsd > childCeilingUsd) {
16482
- clampedBy = spec.budgetUsd !== void 0 && childCeilingUsd === spec.budgetUsd ? "explicit-budget" : "fraction-ceiling";
16483
- reserveUsd = childCeilingUsd;
16484
- }
16485
- const reserve = {
16486
- reserveUsd,
16487
- source
16488
- };
16489
- if (clampedBy !== void 0) reserve.clampedBy = clampedBy;
16490
- if (childCeilingUsd !== void 0) reserve.childCeilingUsd = childCeilingUsd;
16491
- if (this.budget.spawnHeadroom <= 0) return {
16492
- verdict: {
16493
- kind: "reject",
16494
- reason: { code: "lifetime" }
16495
- },
16496
- statsBefore
16497
- };
16498
- if (commitReserve) try {
16499
- this.budget.admitSpawn(reserveUsd, spec.parentAccountScope);
16500
- } catch {
16501
- return {
16502
- verdict: {
16503
- kind: "reject",
16504
- reason: { code: "budget" }
16505
- },
16506
- statsBefore
16507
- };
16508
- }
16509
- else {
16510
- const remainder = this.budget.remainderOf(spec.parentAccountScope);
16511
- const projection = this.projectedDispatchReserveUsd(spec);
16512
- if (remainder !== void 0 && (remainder <= 0 || remainder < projection + (spec.pendingReserveUsd ?? 0))) return {
16513
- verdict: {
16514
- kind: "reject",
16515
- reason: { code: "budget" }
16516
- },
16517
- statsBefore
16518
- };
16519
- }
16520
- this.childrenOf.set(nodeKey, childrenBefore + 1);
16521
- this.admittedTotal += 1;
16522
- const lineage = evaluated.decision.lineage;
16523
- this.registerLineageAdmit(lineage.logicalTaskId);
16524
- let spawnUnitsAfter = this.budget.spawnHeadroom;
16525
- if (this.terminationAccount !== void 0) {
16526
- const debited = this.terminationAccount.debitSpawn({
16527
- logicalTaskId: lineage.logicalTaskId,
16528
- isNew: spec.lineage === void 0,
16529
- ladderLength: spec.ladderLength ?? 1
16530
- });
16531
- if (!debited.ok) return {
16532
- verdict: {
16533
- kind: "reject",
16534
- reason: { code: "termination_exhausted" }
16535
- },
16536
- statsBefore
16537
- };
16538
- spawnUnitsAfter = debited.spawnUnitsAfter;
16539
- }
16540
- return {
16541
- verdict: {
16542
- kind: "admit",
16543
- reserve,
16544
- spawnUnitsAfter,
16545
- lineage: {
16546
- logicalTaskId: lineage.logicalTaskId,
16547
- isNew: spec.lineage === void 0,
16548
- depth
16549
- }
16550
- },
16551
- statsBefore,
16552
- nodeId: this.mintId(),
16553
- lineage,
16554
- ...this.terminationAccount === void 0 ? {} : { ladderLength: spec.ladderLength ?? 1 }
16555
- };
16556
- }
16557
- /**
16558
- * Resume roll-forward for an orchestrator child (M6-T07): restores the
16559
- * children-quota counter only. The budget seed already counts settled
16560
- * agent dispatches, and an in-flight child re-commits its reserve
16561
- * through the ctx.agent dispatch path.
16562
- */
16563
- recoverChild(nodeKey) {
16564
- this.childrenOf.set(nodeKey, (this.childrenOf.get(nodeKey) ?? 0) + 1);
16565
- this.admittedTotal += 1;
16566
- }
16567
- /**
16568
- * Resume roll-forward for a child that already SETTLED before the
16569
- * resume: re-registers the counters (maxChildrenPerNode, the lifetime
16570
- * cap, statsBefore fidelity) without committing any reserve; the spend
16571
- * itself sits in the root ledger seed.
16837
+ * Evaluates one spawn live, strictly BEFORE its decision entry is
16838
+ * appended. On admit the reserve is committed on the whole ancestor
16839
+ * account chain atomically with the evaluation; the caller journals the
16840
+ * returned decision and only then produces effects (child account,
16841
+ * dispatch). On reject nothing is committed and the reject verdict is
16842
+ * journaled by the caller so replay re-delivers it without
16843
+ * re-evaluation.
16572
16844
  */
16573
- recoverSettled(parentAccountScope) {
16574
- this.budget.admitRecovered(0, parentAccountScope);
16575
- this.childrenOf.set(parentAccountScope, (this.childrenOf.get(parentAccountScope) ?? 0) + 1);
16576
- this.admittedTotal += 1;
16577
- }
16578
16845
  /**
16579
- * Resume roll-forward for an admission whose decision entry exists but
16580
- * whose child has NOT settled: re-applies the recorded reserve and
16581
- * counters without re-evaluating any limit (replay never
16582
- * re-evaluates admission; reserves are recovered, never
16583
- * re-estimated).
16846
+ * The reserve the DISPATCH layer will actually commit for this spec:
16847
+ * the estimate (or the flat default) clamped by the explicit child
16848
+ * budget when one exists, because only an explicit budget opens a
16849
+ * child-allowance account at dispatch; the childBudgetFraction cap
16850
+ * never materializes as an account and must not shrink the
16851
+ * projection. The token-count-priced estimate of ctx.agent is
16852
+ * unreachable here (async); a divergence there lands as a journaled
16853
+ * dispatch rejection instead of a strand. Delegates to the exported
16854
+ * {@link dispatchProjectionReserveUsd} so the live gate and
16855
+ * preflightEstimate share ONE formula (the 1.63.0 experiment review,
16856
+ * P0.3).
16584
16857
  */
16585
- recoverInFlight(parentAccountScope, verdict) {
16586
- if (verdict.kind === "reject") return;
16587
- const reserveUsd = verdict.kind === "reuse_full" ? 0 : verdict.reserve.reserveUsd;
16588
- this.budget.admitRecovered(reserveUsd, parentAccountScope);
16589
- this.childrenOf.set(parentAccountScope, (this.childrenOf.get(parentAccountScope) ?? 0) + 1);
16590
- this.admittedTotal += 1;
16591
- }
16592
- };
16593
- //#endregion
16594
- //#region src/l0/telemetry-reduce.ts
16595
- const ZERO = {
16596
- inputTokens: 0,
16597
- outputTokens: 0,
16598
- cacheReadTokens: 0,
16599
- cacheWriteTokens: 0
16600
- };
16601
- /**
16602
- * Reduces one run's event stream (or any slice of it) to the invocation
16603
- * table. Feed it the events in emission order; both a live stream and a
16604
- * replayed one produce the same usage and cost columns.
16605
- */
16606
- function reduceInvocationTable(events) {
16607
- const rows = /* @__PURE__ */ new Map();
16608
- const order = [];
16609
- const openPhases = /* @__PURE__ */ new Map();
16610
- const byRole = {};
16611
- let totalCostUsd = 0;
16612
- const rowFor = (event) => {
16613
- let row = rows.get(event.spanId);
16614
- if (row === void 0) {
16615
- row = {
16616
- spanId: event.spanId,
16617
- agentType: event.agentType,
16618
- ...event.label === void 0 ? {} : { label: event.label },
16619
- usage: ZERO,
16620
- costUsd: 0,
16621
- costBasis: "aggregate-estimate",
16622
- usageApprox: false,
16623
- retryCount: 0,
16624
- replayed: event.replayed === true,
16625
- open: true,
16626
- phases: []
16627
- };
16628
- rows.set(event.spanId, row);
16629
- order.push(row);
16630
- }
16631
- return row;
16632
- };
16633
- for (const event of events) switch (event.type) {
16634
- case "agent:start": {
16635
- const row = rowFor(event);
16636
- row.role = event.role;
16637
- break;
16638
- }
16639
- case "agent:phase:start": {
16640
- const row = rowFor(event);
16641
- const phase = {
16642
- invocation: event.invocation,
16643
- role: event.role,
16644
- model: event.model,
16645
- durationMs: 0,
16646
- usage: ZERO,
16647
- costUsd: 0,
16648
- costBasis: "aggregate-estimate",
16649
- retries: 0,
16650
- replayed: event.replayed === true,
16651
- open: true
16652
- };
16653
- row.phases.push(phase);
16654
- openPhases.set(`${event.spanId}#${event.invocation}`, phase);
16655
- break;
16656
- }
16657
- case "agent:phase:end": {
16658
- const key = `${event.spanId}#${event.invocation}`;
16659
- let phase = openPhases.get(key);
16660
- if (phase === void 0) {
16661
- phase = {
16662
- invocation: event.invocation,
16663
- role: event.role,
16664
- model: event.model,
16665
- durationMs: 0,
16666
- usage: ZERO,
16667
- costUsd: 0,
16668
- costBasis: "aggregate-estimate",
16669
- retries: 0,
16670
- replayed: event.replayed === true,
16671
- open: true
16672
- };
16673
- rowFor(event).phases.push(phase);
16674
- }
16675
- openPhases.delete(key);
16676
- phase.open = false;
16677
- phase.role = event.role;
16678
- phase.model = event.model;
16679
- phase.durationMs = event.durationMs;
16680
- phase.usage = event.usage;
16681
- phase.costUsd = event.costUsd;
16682
- phase.costBasis = event.costBasis ?? "aggregate-estimate";
16683
- phase.outcome = event.outcome;
16684
- phase.retries = event.retries ?? 0;
16685
- const bucket = byRole[event.role] ??= {
16686
- usage: ZERO,
16687
- costUsd: 0,
16688
- costBasis: "per-call"
16689
- };
16690
- bucket.usage = sumUsage(bucket.usage, event.usage);
16691
- bucket.costUsd += event.costUsd;
16692
- if (phase.costBasis === "aggregate-estimate") bucket.costBasis = "aggregate-estimate";
16693
- break;
16694
- }
16695
- case "agent:end": {
16696
- const row = rowFor(event);
16697
- row.open = false;
16698
- row.status = event.status;
16699
- row.usage = event.usage;
16700
- row.costUsd = event.costUsd;
16701
- row.costBasis = event.costBasis ?? "aggregate-estimate";
16702
- row.usageApprox = event.usageApprox === true;
16703
- row.retryCount = event.retryCount ?? 0;
16704
- if (event.toolBudget !== void 0) row.toolBudget = event.toolBudget;
16705
- totalCostUsd += event.costUsd;
16706
- break;
16707
- }
16708
- default: break;
16858
+ projectedDispatchReserveUsd(spec) {
16859
+ return dispatchProjectionReserveUsd(spec, this.flatReserveUsd);
16709
16860
  }
16710
- return {
16711
- agents: order,
16712
- byRole,
16713
- totalCostUsd
16714
- };
16715
- }
16716
- /**
16717
- * The label the claim-consistency judge invocation dispatches under
16718
- * (RV1502; named here since RV1604 so the critical-path reducer and the
16719
- * orchestrator share one constant): the judge rides role 'synthesize',
16720
- * and this label is what tells its wall apart from a real final
16721
- * composition in {@link reduceCriticalPath}.
16722
- */
16723
- const CLAIM_JUDGE_LABEL = "claim-consistency-judge";
16724
- /** Total length of the union of possibly overlapping intervals. */
16725
- function unionLength(intervals) {
16726
- const positive = intervals.filter((interval) => interval.to > interval.from);
16727
- if (positive.length === 0) return 0;
16728
- const sorted = [...positive].sort((a, b) => a.from - b.from);
16729
- let total = 0;
16730
- let from = sorted[0]?.from ?? 0;
16731
- let to = sorted[0]?.to ?? 0;
16732
- for (const interval of sorted.slice(1)) if (interval.from > to) {
16733
- total += to - from;
16734
- from = interval.from;
16735
- to = interval.to;
16736
- } else if (interval.to > to) to = interval.to;
16737
- return total + (to - from);
16738
- }
16739
- function reduceCriticalPath(events) {
16740
- let runStart;
16741
- let runEnd;
16742
- const startBySpan = /* @__PURE__ */ new Map();
16743
- let lastWorkerEnd;
16744
- let workerSpans = 0;
16745
- let synthesisMs = 0;
16746
- let finalCompositionMs = 0;
16747
- let semanticJudgeMs = 0;
16748
- const coordinationModel = [];
16749
- const coordinationTools = [];
16750
- const synthesisSpans = [];
16751
- const spanOf = (durationMs) => Number.isFinite(durationMs) && durationMs > 0 ? durationMs : 0;
16752
- for (const event of events) {
16753
- const at = Date.parse(event.ts);
16754
- if (!Number.isFinite(at)) continue;
16755
- switch (event.type) {
16756
- case "run:start":
16757
- runStart ??= at;
16758
- break;
16759
- case "run:end":
16760
- runEnd = at;
16761
- break;
16762
- case "agent:start":
16763
- startBySpan.set(event.spanId, {
16764
- role: event.role,
16765
- at,
16766
- ...event.label === void 0 ? {} : { label: event.label }
16767
- });
16768
- break;
16769
- case "agent:phase:end":
16770
- if (startBySpan.get(event.spanId)?.role === "orchestrate") coordinationModel.push({
16771
- phase: event.role,
16772
- from: at - spanOf(event.durationMs),
16773
- to: at
16774
- });
16775
- break;
16776
- case "tool:end":
16777
- if (startBySpan.get(event.spanId)?.role === "orchestrate") coordinationTools.push({
16778
- name: event.toolName,
16779
- from: at - spanOf(event.durationMs),
16780
- to: at
16781
- });
16782
- break;
16783
- case "agent:end": {
16784
- const started = startBySpan.get(event.spanId);
16785
- if (started === void 0) break;
16786
- if (started.role === "synthesize") {
16787
- const wall = Math.max(0, at - started.at);
16788
- const judge = started.label === CLAIM_JUDGE_LABEL;
16789
- synthesisMs += wall;
16790
- if (judge) semanticJudgeMs += wall;
16791
- else finalCompositionMs += wall;
16792
- synthesisSpans.push({
16793
- from: started.at,
16794
- to: at,
16795
- judge
16796
- });
16797
- } else if (started.role !== "orchestrate") {
16798
- workerSpans += 1;
16799
- lastWorkerEnd = lastWorkerEnd === void 0 ? at : Math.max(lastWorkerEnd, at);
16800
- }
16801
- break;
16861
+ admit(spec, options) {
16862
+ const commitReserve = options?.commitReserve ?? true;
16863
+ const nodeKey = spec.nodeKey ?? spec.parentAccountScope;
16864
+ const depth = spawnDepthOf(spec.childScope);
16865
+ const childrenBefore = this.childrenOf.get(nodeKey) ?? 0;
16866
+ const evaluated = this.evaluateLineage(spec);
16867
+ const statsBefore = {
16868
+ spawnsBefore: this.budget.spent().agentsSpawned,
16869
+ childrenOfParentBefore: childrenBefore,
16870
+ depth,
16871
+ ...evaluated.statsBefore === void 0 ? {} : { lineage: evaluated.statsBefore }
16872
+ };
16873
+ if (evaluated.decision.kind === "reject") return {
16874
+ verdict: {
16875
+ kind: "reject",
16876
+ reason: evaluated.decision.reason
16877
+ },
16878
+ statsBefore
16879
+ };
16880
+ if (this.terminationAccount !== void 0) {
16881
+ if ((spec.ladderLength ?? 1) > this.terminationAccount.limits.kMax) return {
16882
+ verdict: {
16883
+ kind: "reject",
16884
+ reason: { code: "ladder_exceeds_frozen" }
16885
+ },
16886
+ statsBefore
16887
+ };
16888
+ if (this.terminationAccount.spawnUnitsExhausted) return {
16889
+ verdict: {
16890
+ kind: "reject",
16891
+ reason: { code: "termination_exhausted" }
16892
+ },
16893
+ statsBefore
16894
+ };
16895
+ }
16896
+ if (depth > this.maxDepth) return {
16897
+ verdict: {
16898
+ kind: "reject",
16899
+ reason: { code: "depth" }
16900
+ },
16901
+ statsBefore
16902
+ };
16903
+ if (childrenBefore >= this.maxChildrenPerNode) return {
16904
+ verdict: {
16905
+ kind: "reject",
16906
+ reason: { code: "quota" }
16907
+ },
16908
+ statsBefore
16909
+ };
16910
+ if (this.maxTotalSpawns !== void 0 && this.admittedTotal >= this.maxTotalSpawns) return {
16911
+ verdict: {
16912
+ kind: "reject",
16913
+ reason: { code: "lifetime" }
16914
+ },
16915
+ statsBefore
16916
+ };
16917
+ if (spec.roster !== void 0) {
16918
+ const seatsRemaining = spec.roster.floor - spec.roster.admittedChildren;
16919
+ if (seatsRemaining > 0) {
16920
+ const perSeatProjectionUsd = this.projectedDispatchReserveUsd(spec);
16921
+ const remainder = this.budget.remainderOf(spec.parentAccountScope);
16922
+ if (remainder !== void 0 && remainder < seatsRemaining * perSeatProjectionUsd + spec.roster.liveExposureUsd) return {
16923
+ verdict: {
16924
+ kind: "reject",
16925
+ reason: {
16926
+ code: "roster_floor",
16927
+ floor: spec.roster.floor,
16928
+ admittedChildren: spec.roster.admittedChildren,
16929
+ seatsRemaining,
16930
+ perSeatProjectionUsd,
16931
+ liveExposureUsd: spec.roster.liveExposureUsd,
16932
+ remainderUsd: remainder
16933
+ }
16934
+ },
16935
+ statsBefore
16936
+ };
16802
16937
  }
16803
- default: break;
16804
16938
  }
16805
- }
16806
- const path = {
16807
- synthesisMs,
16808
- finalCompositionMs,
16809
- semanticJudgeMs,
16810
- workerSpans
16811
- };
16812
- if (runStart !== void 0 && runEnd !== void 0) path.runWallMs = Math.max(0, runEnd - runStart);
16813
- if (runEnd !== void 0 && lastWorkerEnd !== void 0) {
16814
- path.postFanInMs = Math.max(0, runEnd - lastWorkerEnd);
16815
- const windowFrom = Math.min(lastWorkerEnd, runEnd);
16816
- const windowTo = runEnd;
16817
- const clip = (interval) => {
16818
- if (interval.to < windowFrom || interval.from > windowTo) return;
16939
+ const spawnToolOrigin = spec.origin === "spawn_agent" || spec.origin === "parallel_agents";
16940
+ let childCeilingUsd;
16941
+ const parentRemainder = this.budget.remainderOf(spec.parentAccountScope);
16942
+ if (spawnToolOrigin) {
16943
+ if (spec.budgetUsd !== void 0) childCeilingUsd = spec.budgetUsd;
16944
+ } else if (parentRemainder !== void 0) {
16945
+ const fractionCap = this.childBudgetFraction * parentRemainder;
16946
+ childCeilingUsd = spec.budgetUsd === void 0 ? fractionCap : Math.min(spec.budgetUsd, fractionCap);
16947
+ } else if (spec.budgetUsd !== void 0) childCeilingUsd = spec.budgetUsd;
16948
+ let reserveUsd = spec.estCostUsd ?? this.flatReserveUsd;
16949
+ const source = spec.estCostUsd === void 0 ? "default" : "estCost";
16950
+ let clampedBy;
16951
+ if (childCeilingUsd !== void 0 && reserveUsd > childCeilingUsd) {
16952
+ clampedBy = spec.budgetUsd !== void 0 && childCeilingUsd === spec.budgetUsd ? "explicit-budget" : "fraction-ceiling";
16953
+ reserveUsd = childCeilingUsd;
16954
+ }
16955
+ const reserve = {
16956
+ reserveUsd,
16957
+ source
16958
+ };
16959
+ if (clampedBy !== void 0) reserve.clampedBy = clampedBy;
16960
+ if (childCeilingUsd !== void 0) reserve.childCeilingUsd = childCeilingUsd;
16961
+ if (this.budget.spawnHeadroom <= 0) return {
16962
+ verdict: {
16963
+ kind: "reject",
16964
+ reason: { code: "lifetime" }
16965
+ },
16966
+ statsBefore
16967
+ };
16968
+ if (commitReserve) try {
16969
+ this.budget.admitSpawn(reserveUsd, spec.parentAccountScope);
16970
+ } catch {
16819
16971
  return {
16820
- from: Math.max(interval.from, windowFrom),
16821
- to: Math.min(interval.to, windowTo)
16972
+ verdict: {
16973
+ kind: "reject",
16974
+ reason: { code: "budget" }
16975
+ },
16976
+ statsBefore
16822
16977
  };
16823
- };
16824
- const byPhase = {};
16825
- const modelClipped = [];
16826
- for (const interval of coordinationModel) {
16827
- const clipped = clip(interval);
16828
- if (clipped === void 0) continue;
16829
- byPhase[interval.phase] = (byPhase[interval.phase] ?? 0) + (clipped.to - clipped.from);
16830
- modelClipped.push(clipped);
16831
16978
  }
16832
- const synthesisClipped = [];
16833
- let judgeClippedMs = 0;
16834
- let compositionClippedMs = 0;
16835
- for (const span of synthesisSpans) {
16836
- const clipped = clip(span);
16837
- if (clipped === void 0) continue;
16838
- synthesisClipped.push(clipped);
16839
- if (span.judge) judgeClippedMs += clipped.to - clipped.from;
16840
- else compositionClippedMs += clipped.to - clipped.from;
16979
+ else {
16980
+ const remainder = this.budget.remainderOf(spec.parentAccountScope);
16981
+ const projection = this.projectedDispatchReserveUsd(spec);
16982
+ if (remainder !== void 0 && (remainder <= 0 || remainder < projection + (spec.pendingReserveUsd ?? 0))) return {
16983
+ verdict: {
16984
+ kind: "reject",
16985
+ reason: { code: "budget" }
16986
+ },
16987
+ statsBefore
16988
+ };
16841
16989
  }
16842
- const byName = {};
16843
- const callsByName = {};
16844
- const toolsClipped = [];
16845
- for (const interval of coordinationTools) {
16846
- const clipped = clip(interval);
16847
- if (clipped === void 0) continue;
16848
- byName[interval.name] = (byName[interval.name] ?? 0) + (clipped.to - clipped.from);
16849
- callsByName[interval.name] = (callsByName[interval.name] ?? 0) + 1;
16850
- toolsClipped.push(clipped);
16990
+ this.childrenOf.set(nodeKey, childrenBefore + 1);
16991
+ this.admittedTotal += 1;
16992
+ const lineage = evaluated.decision.lineage;
16993
+ this.registerLineageAdmit(lineage.logicalTaskId);
16994
+ let spawnUnitsAfter = this.budget.spawnHeadroom;
16995
+ if (this.terminationAccount !== void 0) {
16996
+ const debited = this.terminationAccount.debitSpawn({
16997
+ logicalTaskId: lineage.logicalTaskId,
16998
+ isNew: spec.lineage === void 0,
16999
+ ladderLength: spec.ladderLength ?? 1
17000
+ });
17001
+ if (!debited.ok) return {
17002
+ verdict: {
17003
+ kind: "reject",
17004
+ reason: { code: "termination_exhausted" }
17005
+ },
17006
+ statsBefore
17007
+ };
17008
+ spawnUnitsAfter = debited.spawnUnitsAfter;
16851
17009
  }
16852
- const lengthOf = (intervals) => intervals.reduce((sum, interval) => sum + (interval.to - interval.from), 0);
16853
- const coveredMs = unionLength([
16854
- ...modelClipped,
16855
- ...toolsClipped,
16856
- ...synthesisClipped
16857
- ]);
16858
- const modelOnlyMs = unionLength([...modelClipped, ...toolsClipped]) - unionLength(toolsClipped);
16859
- const breakdown = {
16860
- coordinationModelMs: lengthOf(modelClipped),
16861
- coordinationModelMsByPhase: byPhase,
16862
- coordinationModelOnlyMs: modelOnlyMs,
16863
- coordinationToolMs: lengthOf(toolsClipped),
16864
- coordinationToolMsByName: byName,
16865
- coordinationToolCallsByName: callsByName,
16866
- synthesisMs: lengthOf(synthesisClipped),
16867
- finalCompositionMs: compositionClippedMs,
16868
- semanticJudgeMs: judgeClippedMs,
16869
- coveredMs,
16870
- residueMs: Math.max(0, path.postFanInMs - coveredMs)
17010
+ return {
17011
+ verdict: {
17012
+ kind: "admit",
17013
+ reserve,
17014
+ spawnUnitsAfter,
17015
+ lineage: {
17016
+ logicalTaskId: lineage.logicalTaskId,
17017
+ isNew: spec.lineage === void 0,
17018
+ depth
17019
+ }
17020
+ },
17021
+ statsBefore,
17022
+ nodeId: this.mintId(),
17023
+ lineage,
17024
+ ...this.terminationAccount === void 0 ? {} : { ladderLength: spec.ladderLength ?? 1 }
16871
17025
  };
16872
- if (path.postFanInMs > 0) breakdown.residueShare = breakdown.residueMs / path.postFanInMs;
16873
- path.postFanIn = breakdown;
16874
17026
  }
16875
- if (path.runWallMs !== void 0 && path.runWallMs > 0) {
16876
- if (path.postFanInMs !== void 0) path.postFanInShare = path.postFanInMs / path.runWallMs;
16877
- path.synthesisShare = synthesisMs / path.runWallMs;
17027
+ /**
17028
+ * Resume roll-forward for an orchestrator child (M6-T07): restores the
17029
+ * children-quota counter only. The budget seed already counts settled
17030
+ * agent dispatches, and an in-flight child re-commits its reserve
17031
+ * through the ctx.agent dispatch path.
17032
+ */
17033
+ recoverChild(nodeKey) {
17034
+ this.childrenOf.set(nodeKey, (this.childrenOf.get(nodeKey) ?? 0) + 1);
17035
+ this.admittedTotal += 1;
16878
17036
  }
16879
- return path;
16880
- }
17037
+ /**
17038
+ * Resume roll-forward for a child that already SETTLED before the
17039
+ * resume: re-registers the counters (maxChildrenPerNode, the lifetime
17040
+ * cap, statsBefore fidelity) without committing any reserve; the spend
17041
+ * itself sits in the root ledger seed.
17042
+ */
17043
+ recoverSettled(parentAccountScope) {
17044
+ this.budget.admitRecovered(0, parentAccountScope);
17045
+ this.childrenOf.set(parentAccountScope, (this.childrenOf.get(parentAccountScope) ?? 0) + 1);
17046
+ this.admittedTotal += 1;
17047
+ }
17048
+ /**
17049
+ * Resume roll-forward for an admission whose decision entry exists but
17050
+ * whose child has NOT settled: re-applies the recorded reserve and
17051
+ * counters without re-evaluating any limit (replay never
17052
+ * re-evaluates admission; reserves are recovered, never
17053
+ * re-estimated).
17054
+ */
17055
+ recoverInFlight(parentAccountScope, verdict) {
17056
+ if (verdict.kind === "reject") return;
17057
+ const reserveUsd = verdict.kind === "reuse_full" ? 0 : verdict.reserve.reserveUsd;
17058
+ this.budget.admitRecovered(reserveUsd, parentAccountScope);
17059
+ this.childrenOf.set(parentAccountScope, (this.childrenOf.get(parentAccountScope) ?? 0) + 1);
17060
+ this.admittedTotal += 1;
17061
+ }
17062
+ };
16881
17063
  //#endregion
16882
17064
  //#region src/model/profile-card.ts
16883
17065
  function toolNamesOf(profile) {
@@ -18620,6 +18802,7 @@ function createCtx(internals, rootWorkflow) {
18620
18802
  agentType,
18621
18803
  role: primaryRole,
18622
18804
  budgetAccount: state.budgetScope ?? "run",
18805
+ ...opts.label === void 0 ? {} : { label: opts.label },
18623
18806
  ...opts[kFinalizeReserve] === true ? { finalizeReserve: true } : {}
18624
18807
  },
18625
18808
  transcriptRef: result.transcriptRef
@@ -28228,4 +28411,4 @@ function createSandboxBridge(ctx, options) {
28228
28411
  };
28229
28412
  }
28230
28413
  //#endregion
28231
- export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_JUDGE_LABEL, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DECISION_CHAIN_KINDS, DEFAULT_ANCHOR_PATTERN, DEFAULT_ARTIFACT_PATTERN, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_CITATION_SAMPLE, DEFAULT_CLAIM_JUDGE_MAX_TURNS, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_CALLS_PER_ENTRY, DEFAULT_EVIDENCE_GRADE_PHRASES, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_EVIDENCE_OVERHEAD_CALLS, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_CLAIM_PAIRS, DEFAULT_MAX_CONTRADICTIONS, DEFAULT_MAX_DEPTH, DEFAULT_MAX_EXCERPT_CHARS, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PAIR_EXCERPT_CHARS, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_POOL_PER_PAIR, DEFAULT_MAX_QUOTA_DENIALS, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_RUN_FACT_PAIRS, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_AUTHORITY_HASH, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EXPOSURE_WAIT_SWEEP_MS, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_SECTIONAL_SCHEMA, FINISH_TOOL_NAME, FUTURE_RATES_TOLERANCE_MS, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GET_SETTLED_CHILD_RESULTS_SCHEMA, GET_SETTLED_CHILD_RESULTS_TOOL_NAME, GitWorktreeProvider, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, IN_FLIGHT_EXPOSURE_REFUSAL_PREFIX, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JOURNAL_ENVELOPE_MARKER, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JournalSealedError, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_CRITICAL_UNCOVERED, MAX_DEPTH_CEILING, MAX_RUN_FACTS_SHEET_CHARS, MAX_RUN_ID_LENGTH, MAX_TIMER_DELAY_MS, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, PlanInvariantError, QUOTA_WINDOW_MS, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_FACTS_ANCHOR, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SettlementError, SpanRegistry, SupersededError, TERMINAL_TELEMETRY_SCOPE, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, accountSpendFromJournal, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, assertSafeRunId, atCompactionThreshold, attestToolset, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, citationTargetsValidator, citedValueValidator, claimCoverageOf, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compareRates, compilePermissionChain, compilePermissionPreset, compileSecretMasker, compileVerifiedLayer, constantTimeEqual, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createEnvelopeEncryption, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispatchProjectionReserveUsd, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, enforceToolsetAttestation, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidenceGradeValidator, evidencePreservedValidator, executeWorkflow, executionFactsOf, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, findContradictions, finishContract, foldLedger, foldTermination, formatCharacterValidator, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, headingStructureValidator, identityJcs, implementationAgentProfile, invoiceFromJournal, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, journalPricingSnapshot, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, localKeyProvider, logicalRunTelemetry, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, orchestratorAdmissionEstCostUsd, pairDraftClaims, pairRunFactClaims, parallelScope, parseModelRef, parseScopePath, persistedTerminalEnvelope, phiInitialOf, pilotAgentProfile, pipelineScope, planNodeScope, preflightEstimate, priceComponentsOf, priceEntryBilling, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualRequestsDelta, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleKey, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reconcileStatement, reduceAuditTrail, reduceCriticalPath, reduceDecisionChain, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, sectionCitationsValidator, sectionPatternCountValidator, selectStructuredOutputTier, selfTestFinishValidation, shouldCompact, snapshotQuotaRules, snapshotUsage, spawnDepthOf, spliceSections, statementFromRows, stripFencedBlocks, sumUsage, summarizeInstruction, summarizeOutput, terminalEnvelopeOf, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolAuthority, toolContract, toolContractHash, toolsetAuthorityHash, toolsetHash, ttlState, usageViolations, validateDetachedResolution, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateToolsetAttestation, validateUsageLimits, wordCountValidator, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
28414
+ export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_JUDGE_LABEL, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DECISION_CHAIN_KINDS, DEFAULT_ANCHOR_PATTERN, DEFAULT_ARTIFACT_PATTERN, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_CITATION_SAMPLE, DEFAULT_CLAIM_JUDGE_MAX_TURNS, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_CALLS_PER_ENTRY, DEFAULT_EVIDENCE_GRADE_PHRASES, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_EVIDENCE_OVERHEAD_CALLS, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_CLAIM_PAIRS, DEFAULT_MAX_CONTRADICTIONS, DEFAULT_MAX_DEPTH, DEFAULT_MAX_EXCERPT_CHARS, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PAIR_EXCERPT_CHARS, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_POOL_PER_PAIR, DEFAULT_MAX_QUOTA_DENIALS, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_RUN_FACT_PAIRS, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_AUTHORITY_HASH, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EXPOSURE_WAIT_SWEEP_MS, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_SECTIONAL_SCHEMA, FINISH_TOOL_NAME, FUTURE_RATES_TOLERANCE_MS, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GET_SETTLED_CHILD_RESULTS_SCHEMA, GET_SETTLED_CHILD_RESULTS_TOOL_NAME, GitWorktreeProvider, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, IN_FLIGHT_EXPOSURE_REFUSAL_PREFIX, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JOURNAL_ENVELOPE_MARKER, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JournalSealedError, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_CRITICAL_UNCOVERED, MAX_DEPTH_CEILING, MAX_RUN_FACTS_SHEET_CHARS, MAX_RUN_ID_LENGTH, MAX_TIMER_DELAY_MS, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, PlanInvariantError, QUOTA_WINDOW_MS, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_FACTS_ANCHOR, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_ADMISSION_DECISION_TYPE, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SettlementError, SpanRegistry, SupersededError, TERMINAL_TELEMETRY_SCOPE, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, accountSpendFromJournal, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, assertSafeRunId, atCompactionThreshold, attestToolset, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, childRostersFromJournal, citationTargetsValidator, citedValueValidator, claimCoverageOf, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compareRates, compilePermissionChain, compilePermissionPreset, compileSecretMasker, compileVerifiedLayer, constantTimeEqual, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createEnvelopeEncryption, createSandboxBridge, criticalPathFromJournal, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispatchProjectionReserveUsd, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, enforceToolsetAttestation, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidenceGradeValidator, evidencePreservedValidator, executeWorkflow, executionFactsOf, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, findContradictions, finishContract, foldLedger, foldTermination, formatCharacterValidator, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, headingStructureValidator, identityJcs, implementationAgentProfile, invoiceFromJournal, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, journalPricingSnapshot, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, localKeyProvider, logicalRunTelemetry, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, orchestratorAdmissionEstCostUsd, pairDraftClaims, pairRunFactClaims, parallelScope, parseModelRef, parseScopePath, persistedTerminalEnvelope, phiInitialOf, pilotAgentProfile, pipelineScope, planNodeScope, preflightEstimate, priceComponentsOf, priceEntryBilling, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualRequestsDelta, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleKey, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reconcileStatement, reduceAuditTrail, reduceCriticalPath, reduceDecisionChain, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, sectionCitationsValidator, sectionPatternCountValidator, selectStructuredOutputTier, selfTestFinishValidation, shouldCompact, snapshotQuotaRules, snapshotUsage, spawnDepthOf, spliceSections, statementFromRows, stripFencedBlocks, sumUsage, summarizeInstruction, summarizeOutput, terminalEnvelopeOf, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolAuthority, toolContract, toolContractHash, toolsetAuthorityHash, toolsetHash, ttlState, usageViolations, validateDetachedResolution, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateToolsetAttestation, validateUsageLimits, wordCountValidator, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };