@rulvar/core 1.235.0 → 1.237.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +162 -4
- package/dist/index.js +108 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1217,6 +1217,15 @@ type RunMeta = {
|
|
|
1217
1217
|
allowUnpriced?: string[];
|
|
1218
1218
|
};
|
|
1219
1219
|
/**
|
|
1220
|
+
* The host-declared config identity (RunOptions.configFingerprint,
|
|
1221
|
+
* RV3210): an opaque pin over what the workflow body closes over,
|
|
1222
|
+
* recorded at genesis and compared on every resume that asserts one.
|
|
1223
|
+
* Absent when the run declared none. A store that drops the field
|
|
1224
|
+
* degrades the check to the UNRECORDED warning, never a false pass
|
|
1225
|
+
* or a false refusal (absence means NOT RECORDED).
|
|
1226
|
+
*/
|
|
1227
|
+
configFingerprint?: string;
|
|
1228
|
+
/**
|
|
1220
1229
|
* Count of execution segments this run has STARTED (a fresh start
|
|
1221
1230
|
* writes 1; every resume writes prior + 1, durably, BEFORE the
|
|
1222
1231
|
* segment emits its first event). The engine derives each segment's
|
|
@@ -1670,6 +1679,46 @@ interface TerminalEnvelope {
|
|
|
1670
1679
|
/** Agents admitted over the run's lifetime, resume seed included. */
|
|
1671
1680
|
agentsSpawned: number;
|
|
1672
1681
|
/**
|
|
1682
|
+
* Whether the artifact this terminal carries passed the declared
|
|
1683
|
+
* finish contract (RV2506), mirrored onto the envelope since RV3304:
|
|
1684
|
+
* the 2026-08-12 comparison run settled ok/complete over a retained
|
|
1685
|
+
* contradiction, and neither the HTTP response nor the persisted
|
|
1686
|
+
* rebuild could say whether anything ever judged the deliverable.
|
|
1687
|
+
* Absent when no contract judged anything; absence means NOT
|
|
1688
|
+
* RECORDED, never "accepted".
|
|
1689
|
+
*/
|
|
1690
|
+
deliverableAccepted?: boolean;
|
|
1691
|
+
/**
|
|
1692
|
+
* Whether this terminal carries a deliverable to read at all
|
|
1693
|
+
* (RV2506); same mirror and posture. Distinct from
|
|
1694
|
+
* `deliverableAccepted`: an unjudged artifact still EXISTS, and a
|
|
1695
|
+
* run with no artifact still has a completion claim.
|
|
1696
|
+
*/
|
|
1697
|
+
resultAvailable?: boolean;
|
|
1698
|
+
/**
|
|
1699
|
+
* The journal seq of the decision entry recording the acceptance of
|
|
1700
|
+
* the artifact this terminal carries (RV2506); same mirror, absent
|
|
1701
|
+
* unless the acceptance actually rendered. Read it with
|
|
1702
|
+
* `rulvar inspect` to see WHICH validators accepted WHICH hash.
|
|
1703
|
+
*/
|
|
1704
|
+
acceptedArtifactRef?: number;
|
|
1705
|
+
/**
|
|
1706
|
+
* The claim consistency pass meta, detached (RV3304): `judgedStage`,
|
|
1707
|
+
* `judgedHash`, the coverage grade and the `findings` count, so the
|
|
1708
|
+
* surface a consumer gates on says WHAT was semantically verified,
|
|
1709
|
+
* over WHICH document, and what the judge found, without reaching
|
|
1710
|
+
* into the workflow value. Mutating this copy never touches the
|
|
1711
|
+
* outcome the engine owns.
|
|
1712
|
+
*/
|
|
1713
|
+
claimConsistencyMeta?: Record<string, unknown>;
|
|
1714
|
+
/**
|
|
1715
|
+
* The host declared config identity the run was started under
|
|
1716
|
+
* (RV3210), echoed here since RV3304 so a decision consumer binds
|
|
1717
|
+
* the verdict above to the configuration that produced it without a
|
|
1718
|
+
* second read of the run record. Absent when the run declared none.
|
|
1719
|
+
*/
|
|
1720
|
+
configFingerprint?: string;
|
|
1721
|
+
/**
|
|
1673
1722
|
* Where THIS copy of the envelope was assembled (RV1209). Absent, the
|
|
1674
1723
|
* historical byte contract, means the settlement chokepoint built it
|
|
1675
1724
|
* from the live outcome, so every field above is the run's own
|
|
@@ -7784,6 +7833,24 @@ interface RunOptions {
|
|
|
7784
7833
|
/** Explicit id; otherwise the engine mints a ULID. */
|
|
7785
7834
|
runId?: string;
|
|
7786
7835
|
/**
|
|
7836
|
+
* An opaque host-declared identity over the config the workflow body
|
|
7837
|
+
* CLOSES OVER (RV3210, the honest answer to `hashWorkflowBody`'s
|
|
7838
|
+
* closure blindness: the body-text hash cannot see captured values,
|
|
7839
|
+
* so two byte-identical bodies over different closures pin
|
|
7840
|
+
* identically). Recorded in RunMeta at genesis and compared on every
|
|
7841
|
+
* resume that supplies one: a mismatch refuses the resume typed
|
|
7842
|
+
* BEFORE ownership, meta writes, and appends, because the host
|
|
7843
|
+
* itself asserted the identity; a recorded fingerprint the resume
|
|
7844
|
+
* does not supply warns (`RULVAR_RESUME_FINGERPRINT_UNCHECKED`), and
|
|
7845
|
+
* a supplied fingerprint the run never recorded warns
|
|
7846
|
+
* (`RULVAR_RESUME_FINGERPRINT_UNRECORDED`) instead of failing,
|
|
7847
|
+
* because absence means NOT RECORDED. The preferred pattern is still
|
|
7848
|
+
* to close over nothing and pass config through args; the
|
|
7849
|
+
* fingerprint is the pin for what must stay closed over. A non-empty
|
|
7850
|
+
* string of at most 512 characters.
|
|
7851
|
+
*/
|
|
7852
|
+
configFingerprint?: string;
|
|
7853
|
+
/**
|
|
7787
7854
|
* Run ceiling B0; immutable after start. Enforced by projected
|
|
7788
7855
|
* admission (a spawn whose reserve does not fit is denied before any
|
|
7789
7856
|
* dispatch), the per-turn guard with a budget-derived maxOutputTokens
|
|
@@ -7931,6 +7998,18 @@ interface ResumeOptions {
|
|
|
7931
7998
|
*/
|
|
7932
7999
|
bodyHash?: "warn" | "refuse";
|
|
7933
8000
|
/**
|
|
8001
|
+
* The host's asserted config identity for this resume (RV3210),
|
|
8002
|
+
* compared against the RunMeta-recorded
|
|
8003
|
+
* {@link RunOptions.configFingerprint} BEFORE ownership, meta
|
|
8004
|
+
* writes, or any append. Both present and unequal is a typed
|
|
8005
|
+
* ConfigError always, no posture knob: supplying the fingerprint IS
|
|
8006
|
+
* the assertion. A recorded fingerprint the resume does not supply
|
|
8007
|
+
* warns (`RULVAR_RESUME_FINGERPRINT_UNCHECKED`); a supplied one the
|
|
8008
|
+
* run never recorded warns (`RULVAR_RESUME_FINGERPRINT_UNRECORDED`),
|
|
8009
|
+
* because absence means NOT RECORDED, never a verdict.
|
|
8010
|
+
*/
|
|
8011
|
+
configFingerprint?: string;
|
|
8012
|
+
/**
|
|
7934
8013
|
* Dry-run: replay-strict matching; the first would-be-live call throws
|
|
7935
8014
|
* JournalMissError and the run settles with that typed error, zero live
|
|
7936
8015
|
* calls performed.
|
|
@@ -10322,7 +10401,12 @@ interface OrchestrateClaimConsistency {
|
|
|
10322
10401
|
* explicitly (a ConfigError without that synthesis, the
|
|
10323
10402
|
* contradictions precedent), and non-empty findings block the
|
|
10324
10403
|
* `skipWhenDraftValid` gate: a draft contradicting its own pool
|
|
10325
|
-
* never earns the skip.
|
|
10404
|
+
* never earns the skip. The carry can only ride a prompt that still
|
|
10405
|
+
* lies ahead, so it binds the pass that runs BEFORE the synthesis:
|
|
10406
|
+
* under `stage: 'both'` the draft pass carries and the final pass
|
|
10407
|
+
* reports, and `stage: 'final'` with 'carry' is a ConfigError at
|
|
10408
|
+
* intake, because a posture that reads as a gate must not quietly
|
|
10409
|
+
* behave as 'report'. 'fail' fails the run typed with
|
|
10326
10410
|
* `data.source` 'orchestrator_claim_consistency' BEFORE any
|
|
10327
10411
|
* synthesis dispatch; the judge itself has already been paid, which
|
|
10328
10412
|
* is the honest minimum for a semantic verdict. A judge that does
|
|
@@ -10546,6 +10630,18 @@ interface OrchestrateClaimConsistencyMeta {
|
|
|
10546
10630
|
*/
|
|
10547
10631
|
judgeDeclined?: true;
|
|
10548
10632
|
/**
|
|
10633
|
+
* How many judged contradictions the pass FOUND on the judged
|
|
10634
|
+
* document, present exactly when the judge settled ok (RV3304): `0`
|
|
10635
|
+
* is a clean verdict, a positive count is a disagreement that stayed
|
|
10636
|
+
* wherever the posture did not stop the run. The findings themselves
|
|
10637
|
+
* ride `claimContradictions` beside this meta on the acceptance
|
|
10638
|
+
* envelope, but the meta travels ALONE onto RunOutcome, the
|
|
10639
|
+
* journaled run settle, and the terminal envelope, and the
|
|
10640
|
+
* 2026-08-12 comparison run settled ok/complete over a retained
|
|
10641
|
+
* finding no terminal surface could count.
|
|
10642
|
+
*/
|
|
10643
|
+
findings?: number;
|
|
10644
|
+
/**
|
|
10549
10645
|
* The one field a consumer reads INSTEAD of inferring semantic
|
|
10550
10646
|
* health from an empty findings array (RV1702):
|
|
10551
10647
|
* {@link claimCoverageOf} over this meta, so `completion:
|
|
@@ -12116,7 +12212,7 @@ interface RunHandle<R> {
|
|
|
12116
12212
|
//#endregion
|
|
12117
12213
|
//#region src/engine/terminal-envelope.d.ts
|
|
12118
12214
|
/** The outcome facts the assembler reads; a structural subset of RunOutcome. */
|
|
12119
|
-
type TerminalOutcomeFacts = Pick<RunOutcome<unknown>, "status" | "error" | "completion"> & {
|
|
12215
|
+
type TerminalOutcomeFacts = Pick<RunOutcome<unknown>, "status" | "error" | "completion" | "deliverableAccepted" | "resultAvailable" | "acceptedArtifactRef" | "claimConsistencyMeta"> & {
|
|
12120
12216
|
usage: RunOutcome<unknown>["usage"];
|
|
12121
12217
|
cost: Pick<RunOutcome<unknown>["cost"], "totalUsd" | "grossUsd" | "byModel"> & {
|
|
12122
12218
|
usageApprox?: boolean;
|
|
@@ -12144,7 +12240,8 @@ declare function terminalEnvelopeOf(input: {
|
|
|
12144
12240
|
settlement?: {
|
|
12145
12241
|
settledReason?: "superseded";
|
|
12146
12242
|
};
|
|
12147
|
-
provenance?: "journal";
|
|
12243
|
+
provenance?: "journal"; /** The run's declared config identity (RV3210), echoed onto the envelope (RV3304). */
|
|
12244
|
+
configFingerprint?: string;
|
|
12148
12245
|
}): TerminalEnvelope;
|
|
12149
12246
|
//#endregion
|
|
12150
12247
|
//#region src/l0/decision-chain.d.ts
|
|
@@ -13036,6 +13133,18 @@ declare function lastRunSettle(entries: readonly JournalEntry[]): {
|
|
|
13036
13133
|
* recorded" rather than as a claim.
|
|
13037
13134
|
*/
|
|
13038
13135
|
rejectedFinishCandidates?: RejectedFinishCandidate[];
|
|
13136
|
+
/**
|
|
13137
|
+
* The semantic outcome the settle recorded (RV3304), read back
|
|
13138
|
+
* the same defensive way: the acceptance verdict, the
|
|
13139
|
+
* deliverable presence, the acceptance ref and the judge meta,
|
|
13140
|
+
* so a restarted reader recovers the facts a live consumer
|
|
13141
|
+
* gated on. Absent on journals written before the lift carried
|
|
13142
|
+
* them; absence means NOT RECORDED, never a verdict.
|
|
13143
|
+
*/
|
|
13144
|
+
deliverableAccepted?: boolean;
|
|
13145
|
+
resultAvailable?: boolean;
|
|
13146
|
+
acceptedArtifactRef?: number;
|
|
13147
|
+
claimConsistencyMeta?: Record<string, unknown>;
|
|
13039
13148
|
} | undefined;
|
|
13040
13149
|
/**
|
|
13041
13150
|
* Whether a terminal figure counts THIS segment's work or the whole
|
|
@@ -14016,6 +14125,17 @@ interface StatementReconciliation {
|
|
|
14016
14125
|
componentToleranceUsd: number;
|
|
14017
14126
|
verdict: "match" | "divergence" | "partial-coverage" | "no-overlap";
|
|
14018
14127
|
/**
|
|
14128
|
+
* How much of the MATCHED statement claims money (RV3306):
|
|
14129
|
+
* 'complete' when every matched export row (requests mode) or every
|
|
14130
|
+
* component line (categories mode) carries a dollar claim, a row
|
|
14131
|
+
* total or a component split; 'partial' when some do; 'none' when
|
|
14132
|
+
* the statement matched on identity and usage alone, or matched
|
|
14133
|
+
* nothing. Kept apart from row coverage on purpose: coverage says
|
|
14134
|
+
* the records line up, this says whether the provider actually
|
|
14135
|
+
* stated dollars over them.
|
|
14136
|
+
*/
|
|
14137
|
+
dollarCoverage: "complete" | "partial" | "none";
|
|
14138
|
+
/**
|
|
14019
14139
|
* The settlement-grade composite, first class (RV1006): true exactly
|
|
14020
14140
|
* when the verdict is 'match' AND coverage is complete AND no row's
|
|
14021
14141
|
* usage is unknown AND no model went unpriced. A 'match' alone is
|
|
@@ -14024,9 +14144,22 @@ interface StatementReconciliation {
|
|
|
14024
14144
|
* consumer must not assemble this predicate by hand. The last two
|
|
14025
14145
|
* conditions overlap today's verdict semantics deliberately: the
|
|
14026
14146
|
* predicate states the full contract so it cannot drift apart from
|
|
14027
|
-
* a future verdict refinement.
|
|
14147
|
+
* a future verdict refinement. Note what it does NOT require: a
|
|
14148
|
+
* dollar claim. A usage-only export that matches on identity and
|
|
14149
|
+
* tokens reads `settleable: true`; gate MONETARY closure on
|
|
14150
|
+
* `monetarySettleable` below.
|
|
14028
14151
|
*/
|
|
14029
14152
|
settleable: boolean;
|
|
14153
|
+
/**
|
|
14154
|
+
* The MONETARY settlement predicate (RV3306): `settleable` AND
|
|
14155
|
+
* complete dollar coverage. `settleable` answers "do the records
|
|
14156
|
+
* agree"; this answers "may money close against this statement".
|
|
14157
|
+
* The 2026-08-12 audit named the difference on this exact module: a
|
|
14158
|
+
* usage-only request export settled 'match' without one dollar of
|
|
14159
|
+
* provider evidence, and a finance pipeline gating on `settleable`
|
|
14160
|
+
* alone would have closed money against it.
|
|
14161
|
+
*/
|
|
14162
|
+
monetarySettleable: boolean;
|
|
14030
14163
|
}
|
|
14031
14164
|
/**
|
|
14032
14165
|
* Reconciles the invoice against a normalized provider export. Pure and
|
|
@@ -14304,6 +14437,17 @@ interface PreflightOrchestratorSpec {
|
|
|
14304
14437
|
* the finding entirely. Default 2.
|
|
14305
14438
|
*/
|
|
14306
14439
|
headroomTurns?: number;
|
|
14440
|
+
/**
|
|
14441
|
+
* The `ceiling-headroom-thin` threshold as a fraction of the ceiling
|
|
14442
|
+
* (RV3208, the 2026-08-11 experiment's admission cliff: a $7.00
|
|
14443
|
+
* ceiling over a $6.80 required minimum left 2.86 percent headroom,
|
|
14444
|
+
* and a small pricing or context drift would have refused the whole
|
|
14445
|
+
* workflow at admission). The finding warns when
|
|
14446
|
+
* `ceilingHeadroomShare` sits below this fraction. A number in
|
|
14447
|
+
* [0, 1]; 0 (the default) keeps the finding silent, so declared
|
|
14448
|
+
* configs are byte identical until a host opts in.
|
|
14449
|
+
*/
|
|
14450
|
+
minCeilingHeadroomShare?: number;
|
|
14307
14451
|
}
|
|
14308
14452
|
/** The full input: engine surface, run surface, and the declared wave. */
|
|
14309
14453
|
interface PreflightInput {
|
|
@@ -14531,6 +14675,20 @@ interface PreflightReport {
|
|
|
14531
14675
|
*/
|
|
14532
14676
|
requiredMinimumCeilingUsd?: number;
|
|
14533
14677
|
/**
|
|
14678
|
+
* The ceiling minus the required minimum (RV3208): the absolute
|
|
14679
|
+
* dollars of drift the admission survives before the wave stops
|
|
14680
|
+
* seating. Present beside requiredMinimumCeilingUsd whenever a
|
|
14681
|
+
* ceiling is declared.
|
|
14682
|
+
*/
|
|
14683
|
+
ceilingHeadroomUsd?: number;
|
|
14684
|
+
/**
|
|
14685
|
+
* The same headroom as a fraction of the ceiling (RV3208): the
|
|
14686
|
+
* one-field read of the admission cliff (the 2026-08-11 experiment
|
|
14687
|
+
* ran at 0.0286). Present beside ceilingHeadroomUsd on positive
|
|
14688
|
+
* ceilings.
|
|
14689
|
+
*/
|
|
14690
|
+
ceilingHeadroomShare?: number;
|
|
14691
|
+
/**
|
|
14534
14692
|
* The live-root-exposure term of the wave projection (RV2004): the
|
|
14535
14693
|
* orchestrator's own worst-case turn floor, the money coordination
|
|
14536
14694
|
* has ALWAYS already spent (and holds in flight) by the time any
|
package/dist/index.js
CHANGED
|
@@ -1327,6 +1327,20 @@ function detachedError(error) {
|
|
|
1327
1327
|
}
|
|
1328
1328
|
}
|
|
1329
1329
|
/**
|
|
1330
|
+
* A detached copy of the judge meta (RV3304), the `detachedError`
|
|
1331
|
+
* posture: Json shaped by construction, so a structured clone
|
|
1332
|
+
* reproduces it exactly, and a host that smuggled something exotic
|
|
1333
|
+
* past the type falls back to a shallow copy rather than throwing at
|
|
1334
|
+
* the settlement chokepoint.
|
|
1335
|
+
*/
|
|
1336
|
+
function detachedMeta(meta) {
|
|
1337
|
+
try {
|
|
1338
|
+
return structuredClone(meta);
|
|
1339
|
+
} catch {
|
|
1340
|
+
return { ...meta };
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
/**
|
|
1330
1344
|
* Assembles one terminal envelope (RV1105). `settlement` present means
|
|
1331
1345
|
* nothing durable records the terminal: `settled` reads false, and the
|
|
1332
1346
|
* optional `settledReason: 'superseded'` names the fenced-out segment
|
|
@@ -1356,6 +1370,11 @@ function terminalEnvelopeOf(input) {
|
|
|
1356
1370
|
};
|
|
1357
1371
|
if (outcome.error !== void 0) envelope.error = detachedError(outcome.error);
|
|
1358
1372
|
if (outcome.completion !== void 0) envelope.completion = outcome.completion;
|
|
1373
|
+
if (outcome.deliverableAccepted !== void 0) envelope.deliverableAccepted = outcome.deliverableAccepted;
|
|
1374
|
+
if (outcome.resultAvailable !== void 0) envelope.resultAvailable = outcome.resultAvailable;
|
|
1375
|
+
if (outcome.acceptedArtifactRef !== void 0) envelope.acceptedArtifactRef = outcome.acceptedArtifactRef;
|
|
1376
|
+
if (outcome.claimConsistencyMeta !== void 0) envelope.claimConsistencyMeta = detachedMeta(outcome.claimConsistencyMeta);
|
|
1377
|
+
if (input.configFingerprint !== void 0) envelope.configFingerprint = input.configFingerprint;
|
|
1359
1378
|
if (outcome.cost.wireRequests !== void 0) envelope.wireRequests = outcome.cost.wireRequests;
|
|
1360
1379
|
if (input.settlement?.settledReason !== void 0) envelope.settledReason = input.settlement.settledReason;
|
|
1361
1380
|
if (input.provenance !== void 0) envelope.provenance = input.provenance;
|
|
@@ -8806,17 +8825,36 @@ function lastRunSettle(entries) {
|
|
|
8806
8825
|
if (value?.decisionType === "run_settle" && typeof value.runStatus === "string" && RUN_STATUSES.has(value.runStatus)) {
|
|
8807
8826
|
const completion = value.completion;
|
|
8808
8827
|
const rejected = readRejectedFinishCandidates(value.rejectedFinishCandidates);
|
|
8828
|
+
const judgeMeta = readClaimConsistencyMeta(value.claimConsistencyMeta);
|
|
8809
8829
|
return {
|
|
8810
8830
|
runStatus: value.runStatus,
|
|
8811
8831
|
seq: entry.seq,
|
|
8812
8832
|
...typeof value.outputHash === "string" ? { outputHash: value.outputHash } : {},
|
|
8813
8833
|
...completion === "complete" || completion === "partial" || completion === "rejected" ? { completion } : {},
|
|
8814
|
-
...rejected === void 0 ? {} : { rejectedFinishCandidates: rejected }
|
|
8834
|
+
...rejected === void 0 ? {} : { rejectedFinishCandidates: rejected },
|
|
8835
|
+
...typeof value.deliverableAccepted === "boolean" ? { deliverableAccepted: value.deliverableAccepted } : {},
|
|
8836
|
+
...typeof value.resultAvailable === "boolean" ? { resultAvailable: value.resultAvailable } : {},
|
|
8837
|
+
...typeof value.acceptedArtifactRef === "number" && Number.isSafeInteger(value.acceptedArtifactRef) && value.acceptedArtifactRef >= 0 ? { acceptedArtifactRef: value.acceptedArtifactRef } : {},
|
|
8838
|
+
...judgeMeta === void 0 ? {} : { claimConsistencyMeta: judgeMeta }
|
|
8815
8839
|
};
|
|
8816
8840
|
}
|
|
8817
8841
|
}
|
|
8818
8842
|
}
|
|
8819
8843
|
/**
|
|
8844
|
+
* The judge meta of a persisted settle, or `undefined` (RV3304). The
|
|
8845
|
+
* whole object drops unless its load bearing fields are shaped as the
|
|
8846
|
+
* live producer writes them (`judgeInvoked`, the coverage grade, the
|
|
8847
|
+
* judged stage and hash): a partially shaped meta read as a verdict
|
|
8848
|
+
* would claim semantic ground the journal does not hold, the same
|
|
8849
|
+
* posture as `readRejectedFinishCandidates`.
|
|
8850
|
+
*/
|
|
8851
|
+
function readClaimConsistencyMeta(raw) {
|
|
8852
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return;
|
|
8853
|
+
const meta = raw;
|
|
8854
|
+
if (typeof meta.judgeInvoked !== "boolean" || typeof meta.coverage !== "string" || meta.judgedStage !== "draft" && meta.judgedStage !== "final" || typeof meta.judgedHash !== "string") return;
|
|
8855
|
+
return { ...raw };
|
|
8856
|
+
}
|
|
8857
|
+
/**
|
|
8820
8858
|
* The rejected finish candidates of a persisted settle, or `undefined`
|
|
8821
8859
|
* (RV2605). The WHOLE list drops on any malformed row, the same posture
|
|
8822
8860
|
* the live lift takes (RV2507): a partial history read as complete
|
|
@@ -9286,6 +9324,21 @@ function reduceInvocationTable(events) {
|
|
|
9286
9324
|
*/
|
|
9287
9325
|
const CLAIM_JUDGE_LABEL = "claim-consistency-judge";
|
|
9288
9326
|
/**
|
|
9327
|
+
* Whether a synthesize span's label names a claim-consistency judge
|
|
9328
|
+
* invocation: the exact {@link CLAIM_JUDGE_LABEL}, or a suffixed
|
|
9329
|
+
* variant of it (the final pass dispatches under
|
|
9330
|
+
* `claim-consistency-judge-final` since RV2509 so the two passes of
|
|
9331
|
+
* `stage: 'both'` stay separable). BOTH reducers must classify through
|
|
9332
|
+
* this one predicate (RV3302): the live fold compared the label for
|
|
9333
|
+
* exact equality while the journal fold accepted the suffix, and the
|
|
9334
|
+
* 2026-08-12 comparison run reported semanticJudgeMs 0 with the whole
|
|
9335
|
+
* 272923 ms window read as final composition on the live surface
|
|
9336
|
+
* while the journal fold correctly split 224864 against 48059.
|
|
9337
|
+
*/
|
|
9338
|
+
function isClaimJudgeLabel(label) {
|
|
9339
|
+
return label === "claim-consistency-judge" || (label?.startsWith(`claim-consistency-judge-`) ?? false);
|
|
9340
|
+
}
|
|
9341
|
+
/**
|
|
9289
9342
|
* The label the final synthesis (composition) invocation dispatches
|
|
9290
9343
|
* under (RV2901). The engine labelling its OWN dispatches is what lets
|
|
9291
9344
|
* `criticalPathFromJournal` split the synthesize bucket offline: the
|
|
@@ -9366,7 +9419,7 @@ function reduceCriticalPath(events) {
|
|
|
9366
9419
|
if (started === void 0) break;
|
|
9367
9420
|
if (started.role === "synthesize") {
|
|
9368
9421
|
const wall = Math.max(0, at - started.at);
|
|
9369
|
-
const judge = started.label
|
|
9422
|
+
const judge = isClaimJudgeLabel(started.label);
|
|
9370
9423
|
synthesisMs += wall;
|
|
9371
9424
|
if (judge) semanticJudgeMs += wall;
|
|
9372
9425
|
else finalCompositionMs += wall;
|
|
@@ -9510,7 +9563,7 @@ function criticalPathFromJournal(entries) {
|
|
|
9510
9563
|
continue;
|
|
9511
9564
|
}
|
|
9512
9565
|
labelledSynthesis = true;
|
|
9513
|
-
if (label
|
|
9566
|
+
if (isClaimJudgeLabel(label)) semanticJudgeMs += wall;
|
|
9514
9567
|
else finalCompositionMs += wall;
|
|
9515
9568
|
}
|
|
9516
9569
|
const segments = logicalRunTelemetry(ordered).segments;
|
|
@@ -16111,6 +16164,7 @@ function reconcileStatement(invoice, statement, options) {
|
|
|
16111
16164
|
let statementComponents;
|
|
16112
16165
|
let matchedStatementRows = 0;
|
|
16113
16166
|
let matchedUsdRows = 0;
|
|
16167
|
+
let matchedDollarRows = 0;
|
|
16114
16168
|
let tokenMismatches = 0;
|
|
16115
16169
|
let partialOverlap = false;
|
|
16116
16170
|
const tokenMismatchSample = [];
|
|
@@ -16215,6 +16269,7 @@ function reconcileStatement(invoice, statement, options) {
|
|
|
16215
16269
|
for (const row of statement.rows) {
|
|
16216
16270
|
if (!matchedStatement.has(row.responseId)) continue;
|
|
16217
16271
|
matchedStatementRows += 1;
|
|
16272
|
+
if (row.usd !== void 0 || row.componentsUsd !== void 0) matchedDollarRows += 1;
|
|
16218
16273
|
if (row.usd !== void 0) {
|
|
16219
16274
|
matchedUsdRows += 1;
|
|
16220
16275
|
totalSeen = true;
|
|
@@ -16320,6 +16375,10 @@ function reconcileStatement(invoice, statement, options) {
|
|
|
16320
16375
|
else if (matchedRows === 0 && !partialOverlap) verdict = "no-overlap";
|
|
16321
16376
|
else if (!coverageComplete) verdict = "partial-coverage";
|
|
16322
16377
|
else verdict = "match";
|
|
16378
|
+
const dollarClaims = statement.kind === "requests" ? matchedDollarRows : components.filter((line) => line.statementUsd !== void 0).length;
|
|
16379
|
+
const dollarSlots = statement.kind === "requests" ? matchedStatementRows : components.length;
|
|
16380
|
+
const dollarCoverage = dollarSlots > 0 && dollarClaims === dollarSlots ? "complete" : dollarClaims > 0 ? "partial" : "none";
|
|
16381
|
+
const settleable = verdict === "match" && coverageComplete && usageUnknownRows === 0 && unpricedModels.size === 0;
|
|
16323
16382
|
return {
|
|
16324
16383
|
mode: statement.kind,
|
|
16325
16384
|
coverage: {
|
|
@@ -16345,7 +16404,9 @@ function reconcileStatement(invoice, statement, options) {
|
|
|
16345
16404
|
usageUnknownRows,
|
|
16346
16405
|
componentToleranceUsd,
|
|
16347
16406
|
verdict,
|
|
16348
|
-
|
|
16407
|
+
dollarCoverage,
|
|
16408
|
+
settleable,
|
|
16409
|
+
monetarySettleable: settleable && dollarCoverage === "complete"
|
|
16349
16410
|
};
|
|
16350
16411
|
}
|
|
16351
16412
|
/** A cell that is absent by export convention: missing, null, or ''. */
|
|
@@ -16587,10 +16648,15 @@ function persistedTerminalEnvelope(input) {
|
|
|
16587
16648
|
outcome: {
|
|
16588
16649
|
status: settle.runStatus,
|
|
16589
16650
|
...settle.completion === void 0 ? {} : { completion: settle.completion },
|
|
16651
|
+
...settle.deliverableAccepted === void 0 ? {} : { deliverableAccepted: settle.deliverableAccepted },
|
|
16652
|
+
...settle.resultAvailable === void 0 ? {} : { resultAvailable: settle.resultAvailable },
|
|
16653
|
+
...settle.acceptedArtifactRef === void 0 ? {} : { acceptedArtifactRef: settle.acceptedArtifactRef },
|
|
16654
|
+
...settle.claimConsistencyMeta === void 0 ? {} : { claimConsistencyMeta: settle.claimConsistencyMeta },
|
|
16590
16655
|
usage: ledger.usage,
|
|
16591
16656
|
cost: costReportFromJournal(input.entries, input.priceUsd)
|
|
16592
16657
|
},
|
|
16593
16658
|
agentsSpawned: ledger.agentsSpawned,
|
|
16659
|
+
...input.meta?.configFingerprint === void 0 ? {} : { configFingerprint: input.meta.configFingerprint },
|
|
16594
16660
|
provenance: "journal"
|
|
16595
16661
|
})
|
|
16596
16662
|
};
|
|
@@ -22549,6 +22615,7 @@ function validateOrchestrateOptions(opts) {
|
|
|
22549
22615
|
const stage = consistency.stage ?? "draft";
|
|
22550
22616
|
if (stage !== "draft" && stage !== "final" && stage !== "both") throw new ConfigError("orchestrate claimConsistency.stage must be 'draft', 'final' or 'both'; got " + JSON.stringify(consistency.stage));
|
|
22551
22617
|
if (stage !== "draft" && opts.synthesis === void 0) throw new ConfigError(`orchestrate claimConsistency.stage '${stage}' requires synthesis: without the post-fan-in invocation the coordination draft IS the final artifact, and the default 'draft' already judges it`);
|
|
22618
|
+
if (stage === "final" && onFound === "carry") throw new ConfigError("orchestrate claimConsistency.onFound 'carry' cannot pair with stage 'final': the final pass runs after the synthesis, so there is no prompt left to carry the findings into; use 'report' or 'fail', or keep a carried draft pass with stage 'both'");
|
|
22552
22619
|
if (consistency.pattern !== void 0) {
|
|
22553
22620
|
if (typeof consistency.pattern !== "string") throw new ConfigError(`orchestrate claimConsistency.pattern must be a string; got ${typeof consistency.pattern}`);
|
|
22554
22621
|
let probe;
|
|
@@ -24848,7 +24915,10 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
24848
24915
|
reason
|
|
24849
24916
|
}));
|
|
24850
24917
|
claimFindingsFound = findings;
|
|
24851
|
-
claimConsistencyMeta = finishMeta({
|
|
24918
|
+
claimConsistencyMeta = finishMeta({
|
|
24919
|
+
judgeInvoked: true,
|
|
24920
|
+
findings: findings.length
|
|
24921
|
+
});
|
|
24852
24922
|
announce();
|
|
24853
24923
|
if (onFound !== "fail" || findings.length === 0) return;
|
|
24854
24924
|
throw new FailRunError(`the claim-consistency judge found ${String(findings.length)} contradiction${findings.length === 1 ? "" : "s"} between the draft and the settled child pool: ` + findings.map((finding) => `${finding.anchor} (${finding.reason})`).join("; "), { data: {
|
|
@@ -26769,6 +26839,14 @@ function preflightEstimate(input) {
|
|
|
26769
26839
|
code: "reserve-line-headroom",
|
|
26770
26840
|
message: `the admitted wave's steady state sits ${reserveLineHeadroomUsd.toFixed(4)} USD under the reserve line ${reserveLineUsd.toFixed(4)} USD (the ceiling minus the synthesis reserve), less than ${String(headroomTurns)} coordination turn floors of headroom (${liveRootExposureTermUsd.toFixed(4)} USD each): child spend past the declared estimates eats that headroom, the coordination loop is then refused at the line, and the run settles partial with the synthesis redeemed from its reserve (RV2101); size the wave below the line or raise the ceiling to keep coordinating past it`
|
|
26771
26841
|
});
|
|
26842
|
+
const ceilingHeadroomUsd = ceilingUsd === void 0 || requiredMinimumCeilingUsd === void 0 ? void 0 : ceilingUsd - requiredMinimumCeilingUsd;
|
|
26843
|
+
const ceilingHeadroomShare = ceilingHeadroomUsd === void 0 || ceilingUsd === void 0 || ceilingUsd <= 0 ? void 0 : ceilingHeadroomUsd / ceilingUsd;
|
|
26844
|
+
const minCeilingHeadroomShare = input.orchestrator?.minCeilingHeadroomShare ?? 0;
|
|
26845
|
+
if (ceilingHeadroomShare !== void 0 && minCeilingHeadroomShare > 0 && ceilingHeadroomShare < minCeilingHeadroomShare) say({
|
|
26846
|
+
severity: "warning",
|
|
26847
|
+
code: "ceiling-headroom-thin",
|
|
26848
|
+
message: `the ceiling headroom is ${(ceilingHeadroomShare * 100).toFixed(2)} percent of the ceiling (${(ceilingHeadroomUsd ?? 0).toFixed(4)} USD over the required minimum ${(requiredMinimumCeilingUsd ?? 0).toFixed(4)} USD), below the declared ${(minCeilingHeadroomShare * 100).toFixed(2)} percent floor: a small pricing or context drift refuses the whole wave at admission; raise the ceiling or slim the wave`
|
|
26849
|
+
});
|
|
26772
26850
|
{
|
|
26773
26851
|
const judgeEstUsd = input.orchestrator?.claimConsistency?.judge?.estCost;
|
|
26774
26852
|
if (judgeEstUsd !== void 0 && effectiveCapUsd !== void 0 && synthesisHoldUsd > 0) {
|
|
@@ -27052,6 +27130,8 @@ function preflightEstimate(input) {
|
|
|
27052
27130
|
reservedForFinalizationUsd,
|
|
27053
27131
|
synthesisReserveUsd: synthesisHoldUsd,
|
|
27054
27132
|
...requiredMinimumCeilingUsd === void 0 ? {} : { requiredMinimumCeilingUsd },
|
|
27133
|
+
...ceilingHeadroomUsd === void 0 ? {} : { ceilingHeadroomUsd },
|
|
27134
|
+
...ceilingHeadroomShare === void 0 ? {} : { ceilingHeadroomShare },
|
|
27055
27135
|
...liveRootExposureTermUsd > 0 ? { liveRootExposureTermUsd } : {},
|
|
27056
27136
|
...reserveLineUsd === void 0 ? {} : { reserveLineUsd },
|
|
27057
27137
|
...reserveLineHeadroomUsd === void 0 ? {} : { reserveLineHeadroomUsd },
|
|
@@ -27588,6 +27668,10 @@ function parseDeadlineAt(value) {
|
|
|
27588
27668
|
if (month < 1 || month > 12 || day < 1 || day > daysInMonth) refuse();
|
|
27589
27669
|
return parsed;
|
|
27590
27670
|
}
|
|
27671
|
+
/** Validates a declared config fingerprint (RV3210): a non-empty string of at most 512 chars. */
|
|
27672
|
+
function requireConfigFingerprint(value, site) {
|
|
27673
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 512) throw new ConfigError(`${site} must be a non-empty string of at most 512 characters; got ` + (typeof value === "string" ? `${String(value.length)} characters` : JSON.stringify(value)));
|
|
27674
|
+
}
|
|
27591
27675
|
/** Content hash of an in-process workflow body (run-to-definition binding). */
|
|
27592
27676
|
function hashWorkflowBody(wf) {
|
|
27593
27677
|
return createHash("sha256").update(wf.body.toString(), "utf8").digest("hex");
|
|
@@ -27894,6 +27978,7 @@ function createEngine(options) {
|
|
|
27894
27978
|
if (wf.kind !== "workflow" && wf.kind !== "compiled-workflow") throw new ConfigError("engine.run accepts in-process Workflow values or compileScript CompiledWorkflow values");
|
|
27895
27979
|
if (opts?.budgetUsd !== void 0) requireNonNegativeNumber(opts.budgetUsd, "RunOptions.budgetUsd");
|
|
27896
27980
|
if (opts?.maxInFlightExposureUsd !== void 0) requireNonNegativeNumber(opts.maxInFlightExposureUsd, "RunOptions.maxInFlightExposureUsd");
|
|
27981
|
+
if (opts?.configFingerprint !== void 0) requireConfigFingerprint(opts.configFingerprint, "RunOptions.configFingerprint");
|
|
27897
27982
|
if (opts?.clampTurnToExposure !== void 0 && typeof opts.clampTurnToExposure !== "boolean") throw new ConfigError("RunOptions.clampTurnToExposure must be a boolean; got " + JSON.stringify(opts.clampTurnToExposure));
|
|
27898
27983
|
if (opts?.strictPricing !== void 0 && typeof opts.strictPricing !== "boolean" && (typeof opts.strictPricing !== "object" || opts.strictPricing === null || Array.isArray(opts.strictPricing))) throw new ConfigError("RunOptions.strictPricing must be a boolean or an options object; got " + JSON.stringify(opts.strictPricing));
|
|
27899
27984
|
if (opts?.limits !== void 0) validateUsageLimits(opts.limits, "RunOptions.limits");
|
|
@@ -27929,6 +28014,7 @@ function createEngine(options) {
|
|
|
27929
28014
|
...opts.strictPricing.maxRatesAgeDays === void 0 ? {} : { maxRatesAgeDays: opts.strictPricing.maxRatesAgeDays },
|
|
27930
28015
|
...opts.strictPricing.allowUnpriced === void 0 ? {} : { allowUnpriced: [...opts.strictPricing.allowUnpriced] }
|
|
27931
28016
|
};
|
|
28017
|
+
const configFingerprint = opts?.configFingerprint ?? resumeCtx?.configFingerprint;
|
|
27932
28018
|
const makeBudget = () => new RunBudget({
|
|
27933
28019
|
...ceilingUsd === void 0 ? {} : { ceilingUsd },
|
|
27934
28020
|
...exposureCapUsd === void 0 ? {} : { maxInFlightExposureUsd: exposureCapUsd },
|
|
@@ -28109,6 +28195,7 @@ function createEngine(options) {
|
|
|
28109
28195
|
...ceilingUsd === void 0 ? {} : { budgetUsd: ceilingUsd },
|
|
28110
28196
|
...exposureCapUsd === void 0 ? {} : { maxInFlightExposureUsd: exposureCapUsd },
|
|
28111
28197
|
...strictPricing === void 0 ? {} : { strictPricing },
|
|
28198
|
+
...configFingerprint === void 0 ? {} : { configFingerprint },
|
|
28112
28199
|
...argsBinding.argsProvided === void 0 ? {} : { argsProvided: argsBinding.argsProvided },
|
|
28113
28200
|
...argsBinding.argsHash === void 0 ? {} : { argsHash: argsBinding.argsHash },
|
|
28114
28201
|
...genesis === void 0 ? {} : { genesis },
|
|
@@ -28402,6 +28489,7 @@ function createEngine(options) {
|
|
|
28402
28489
|
workflow: wf.name,
|
|
28403
28490
|
outcome: outcomeFacts,
|
|
28404
28491
|
agentsSpawned: budget.spent().agentsSpawned,
|
|
28492
|
+
...configFingerprint === void 0 ? {} : { configFingerprint },
|
|
28405
28493
|
...settlementFailure !== void 0 ? { settlement: {} } : supersededBy !== void 0 ? { settlement: { settledReason: "superseded" } } : {}
|
|
28406
28494
|
});
|
|
28407
28495
|
const outcome = {
|
|
@@ -28508,6 +28596,20 @@ function createEngine(options) {
|
|
|
28508
28596
|
}
|
|
28509
28597
|
bound = supplied;
|
|
28510
28598
|
}
|
|
28599
|
+
{
|
|
28600
|
+
const supplied = resumeOptions?.configFingerprint;
|
|
28601
|
+
if (supplied !== void 0) requireConfigFingerprint(supplied, "ResumeOptions.configFingerprint");
|
|
28602
|
+
const recorded = typeof meta?.configFingerprint === "string" ? meta.configFingerprint : void 0;
|
|
28603
|
+
if (supplied !== void 0 && recorded !== void 0 && supplied !== recorded) throw new ConfigError(`resume: the supplied configFingerprint does not match the one run '${runId}' recorded at genesis; the config the workflow closes over changed, and the host declared exactly this check. Resume under the original config, or drop the option to proceed under the loud warning`);
|
|
28604
|
+
if (supplied !== void 0 && recorded === void 0) process.emitWarning(`resume: a configFingerprint was supplied but run '${runId}' never recorded one; the assertion cannot be verified (absence means NOT RECORDED)`, {
|
|
28605
|
+
code: "RULVAR_RESUME_FINGERPRINT_UNRECORDED",
|
|
28606
|
+
type: "RulvarWarning"
|
|
28607
|
+
});
|
|
28608
|
+
if (supplied === void 0 && recorded !== void 0) process.emitWarning(`resume: run '${runId}' recorded a configFingerprint at genesis and this resume did not supply one; the declared config identity goes unchecked`, {
|
|
28609
|
+
code: "RULVAR_RESUME_FINGERPRINT_UNCHECKED",
|
|
28610
|
+
type: "RulvarWarning"
|
|
28611
|
+
});
|
|
28612
|
+
}
|
|
28511
28613
|
const priorEntries = (await journal.load(runId)).map((entry) => normalizeEntry(entry));
|
|
28512
28614
|
scanJournalCompatibility(runId, priorEntries, buildDeriverRegistry(options.extraDerivers));
|
|
28513
28615
|
if (priorEntries.some((entry) => entry.usageSemantics === void 0 && (entry.servedBy?.startsWith("openai:") === true && (entry.usage?.cacheWriteTokens ?? 0) > 0 || (entry.usageByModel?.some((slice) => slice.servedBy.startsWith("openai:") && slice.usage.cacheWriteTokens > 0) ?? false)))) process.emitWarning(`resume: run '${runId}' contains OpenAI cache-write usage recorded without a usage-semantics stamp. Entries written by rulvar v1.19.0 double-counted cache writes into inputTokens, so their recorded cost and budget debits are OVERSTATED; unstamped entries from v1.20.0 are correct. Resuming keeps the recorded debits. Audit procedure: https://docs.rulvar.com/guide/providers#openai-legacy-cache-journals`, {
|
|
@@ -28534,6 +28636,7 @@ function createEngine(options) {
|
|
|
28534
28636
|
...typeof meta?.argsHash === "string" ? { argsHash: meta.argsHash } : {},
|
|
28535
28637
|
...typeof meta?.genesis === "string" ? { genesis: meta.genesis } : {},
|
|
28536
28638
|
...typeof meta?.execKeyDerivation === "number" ? { execKeyDerivation: meta.execKeyDerivation } : {},
|
|
28639
|
+
...typeof meta?.configFingerprint === "string" ? { configFingerprint: meta.configFingerprint } : {},
|
|
28537
28640
|
previewResolve
|
|
28538
28641
|
});
|
|
28539
28642
|
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.237.0",
|
|
4
4
|
"description": "Rulvar core: L0 contracts, journal kernel, ctx primitives, agent runtime, model router, tool system, dynamic orchestrator, InMemory and JSONL stores, event stream.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|