@rulvar/evals 1.240.0 → 1.241.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.js +104 -1
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import { ConfigError, InMemoryStore, JsonlFileStore, KnowledgeCasError, LeaseHeldError, SettlementError, SupersededError, citedValueValidator, claimCoverageOf, claimExpiry, compareRates, compileVerifiedLayer, createEngine, defineWorkflow, evidenceGradeValidator, hashRunOutput, invoiceFromJournal, journalPricingSnapshot, lastRunSettle, makeOrchestratorWorkflow, memoryQuotaLimiter, pairDraftClaims, pairRunFactClaims, preflightEstimate, priceComponentsOf } from "@rulvar/core";
|
|
2
|
+
import { ConfigError, InMemoryStore, JsonlFileStore, KnowledgeCasError, LeaseHeldError, SettlementError, SupersededError, citedValueValidator, claimCoverageOf, claimExpiry, compareRates, compileVerifiedLayer, createEngine, defineWorkflow, evidenceGradeValidator, hashRunOutput, invoiceFromJournal, journalPricingSnapshot, lastRunSettle, makeOrchestratorWorkflow, memoryQuotaLimiter, minMatchesValidator, pairDraftClaims, pairRunFactClaims, preflightEstimate, priceComponentsOf } from "@rulvar/core";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { appendFileSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
@@ -3492,6 +3492,8 @@ const TAIL_DRAFT_INVERTED = "draft: an audit-write failure does not turn success
|
|
|
3492
3492
|
const TAIL_FINAL_INVERTED = "final: an audit-write failure does not turn success into failure [src/exec.ts:256-296].";
|
|
3493
3493
|
const TAIL_FINAL_STILL_INVERTED = "final: the repaired text still flips the recorded outcome [src/exec.ts:256-296].";
|
|
3494
3494
|
const TAIL_FINAL_CLEAN = "final: a failed audit write does not mask success [src/exec.ts:256-296].";
|
|
3495
|
+
const TAIL_FINAL_UNGROUNDED = "final: repaired wording with the provenance stripped.";
|
|
3496
|
+
const TAIL_FINAL_UNGROUNDED_INITIAL = "final: the initial wording arrived without any anchor.";
|
|
3495
3497
|
const TAIL_FINDS = { contradictions: [{
|
|
3496
3498
|
pair: 0,
|
|
3497
3499
|
reason: "the draft inverts the recorded reading"
|
|
@@ -3671,6 +3673,107 @@ const SCENARIOS = [
|
|
|
3671
3673
|
};
|
|
3672
3674
|
}
|
|
3673
3675
|
},
|
|
3676
|
+
{
|
|
3677
|
+
name: "repair-round-host-rejection",
|
|
3678
|
+
doctrine: "a repair round that dispatched and lost its candidate to the finish contract fails typed as a host rejection (RV3601): the message names the dispatch, never 'could not dispatch'; data carries roundDispatched true, repairsUsed 1, the judge meta beside the findings, and the finish verdict verbatim (failed validators, candidateHash, candidateChars); the outcome lifts the findings beside the meta",
|
|
3679
|
+
async run() {
|
|
3680
|
+
const { engine, store } = tailEngine(tailAdapter({
|
|
3681
|
+
judge: () => TAIL_FINDS,
|
|
3682
|
+
finals: [
|
|
3683
|
+
TAIL_FINAL_INVERTED,
|
|
3684
|
+
TAIL_FINAL_UNGROUNDED,
|
|
3685
|
+
TAIL_FINAL_UNGROUNDED
|
|
3686
|
+
]
|
|
3687
|
+
}));
|
|
3688
|
+
const outcome = await engine.run(makeOrchestratorWorkflow("audit the executor", {
|
|
3689
|
+
...TAIL_OPTS,
|
|
3690
|
+
claimConsistency: {
|
|
3691
|
+
stage: "final",
|
|
3692
|
+
onFound: "repair"
|
|
3693
|
+
},
|
|
3694
|
+
finishValidation: {
|
|
3695
|
+
validators: [minMatchesValidator({
|
|
3696
|
+
pattern: "src/[a-z]+\\.ts:\\d+",
|
|
3697
|
+
min: 1,
|
|
3698
|
+
name: "provenance-anchor"
|
|
3699
|
+
})],
|
|
3700
|
+
maxRepairs: 1
|
|
3701
|
+
}
|
|
3702
|
+
}), void 0, {
|
|
3703
|
+
runId: "fault-repair-host-rejection",
|
|
3704
|
+
budgetUsd: 10
|
|
3705
|
+
}).result;
|
|
3706
|
+
const data = outcome.error?.data ?? {};
|
|
3707
|
+
const entries = await store.load("fault-repair-host-rejection");
|
|
3708
|
+
const { compositions, judges } = tailSpans(entries);
|
|
3709
|
+
const liftedFindings = outcome.claimContradictions;
|
|
3710
|
+
const message = outcome.error?.message ?? "";
|
|
3711
|
+
return {
|
|
3712
|
+
observation: {
|
|
3713
|
+
matched: outcome.status === "error" && message.includes("dispatched and its repaired candidate failed host validation") && !message.includes("could not dispatch") && data.source === "orchestrator_claim_consistency" && data.roundDispatched === true && data.repairsUsed === 1 && data.claimConsistencyMeta?.findings === 1 && Array.isArray(data.claimContradictions) && data.claimContradictions.length === 1 && typeof data.finishValidation?.callId === "string" && data.finishValidation.repairsUsed === 1 && data.finishValidation.maxRepairs === 1 && typeof data.finishValidation.candidateHash === "string" && typeof data.finishValidation.candidateChars === "number" && JSON.stringify(data.finishValidation.failed ?? null).includes("provenance-anchor") && Array.isArray(liftedFindings) && liftedFindings.length === 1 && compositions.length === 2 && judges.length === 1,
|
|
3714
|
+
detail: `run '${outcome.status}': roundDispatched=${String(data.roundDispatched)}, repairsUsed=${String(data.repairsUsed)}, meta findings=${String(data.claimConsistencyMeta?.findings)}, finish verdict carries hash=${String(typeof data.finishValidation?.candidateHash === "string")} chars=${String(data.finishValidation?.candidateChars)}, outcome lifts findings=${String(Array.isArray(liftedFindings))}; ${String(compositions.length)} composition(s), ${String(judges.length)} final judge pass(es)`
|
|
3715
|
+
},
|
|
3716
|
+
artifacts: [jsonArtifact("outcome.json", {
|
|
3717
|
+
status: outcome.status,
|
|
3718
|
+
error: outcome.error ?? null
|
|
3719
|
+
}), jsonArtifact("journal.json", entries)]
|
|
3720
|
+
};
|
|
3721
|
+
}
|
|
3722
|
+
},
|
|
3723
|
+
{
|
|
3724
|
+
name: "repair-round-own-pool",
|
|
3725
|
+
doctrine: "the mechanical repair pool belongs to one composition invocation (RV3602): the bounded claim repair round enters with the full maxRepairs even after the initial composition spent its own, so the frozen third comparison sequence converges to ok/complete with verdicts repair/accepted twice and repairsUsed restarting at the invocation boundary, never a host rejection born of an inherited spent pool; the round's prompt also carries the HOST VALIDATION LESSONS block naming the failure the run already paid for (RV3603), while the initial composition carries none",
|
|
3726
|
+
async run() {
|
|
3727
|
+
let judgeCalls = 0;
|
|
3728
|
+
const adapter = tailAdapter({
|
|
3729
|
+
judge: () => (judgeCalls += 1) === 1 ? TAIL_FINDS : TAIL_AGREES,
|
|
3730
|
+
finals: [
|
|
3731
|
+
TAIL_FINAL_UNGROUNDED_INITIAL,
|
|
3732
|
+
TAIL_FINAL_INVERTED,
|
|
3733
|
+
TAIL_FINAL_UNGROUNDED,
|
|
3734
|
+
TAIL_FINAL_CLEAN
|
|
3735
|
+
]
|
|
3736
|
+
});
|
|
3737
|
+
const { engine, store } = tailEngine(adapter);
|
|
3738
|
+
const outcome = await engine.run(makeOrchestratorWorkflow("audit the executor", {
|
|
3739
|
+
...TAIL_OPTS,
|
|
3740
|
+
claimConsistency: {
|
|
3741
|
+
stage: "final",
|
|
3742
|
+
onFound: "repair"
|
|
3743
|
+
},
|
|
3744
|
+
finishValidation: {
|
|
3745
|
+
validators: [minMatchesValidator({
|
|
3746
|
+
pattern: "src/[a-z]+\\.ts:\\d+",
|
|
3747
|
+
min: 1,
|
|
3748
|
+
name: "provenance-anchor"
|
|
3749
|
+
})],
|
|
3750
|
+
maxRepairs: 1
|
|
3751
|
+
}
|
|
3752
|
+
}), void 0, {
|
|
3753
|
+
runId: "fault-repair-own-pool",
|
|
3754
|
+
budgetUsd: 10
|
|
3755
|
+
}).result;
|
|
3756
|
+
const value = outcome.value;
|
|
3757
|
+
const entries = await store.load("fault-repair-own-pool");
|
|
3758
|
+
const { compositions, judges } = tailSpans(entries);
|
|
3759
|
+
const verdictRows = entries.filter((entry) => entry.kind === "decision" && entry.value?.decisionType === "orchestrator_finish_validation").map((entry) => entry.value);
|
|
3760
|
+
const verdicts = verdictRows.map((row) => row.verdict).join(",");
|
|
3761
|
+
const pools = verdictRows.map((row) => String(row.repairsUsed)).join(",");
|
|
3762
|
+
const compositionPrompts = adapter.calls.filter((call) => call.label === "final-composition").map((call) => call.prompt);
|
|
3763
|
+
const lessonCarried = compositionPrompts.length === 4 && compositionPrompts[0]?.includes("HOST VALIDATION LESSONS") === false && compositionPrompts[2]?.includes("HOST VALIDATION LESSONS") === true && compositionPrompts[2]?.includes("provenance-anchor") === true;
|
|
3764
|
+
return {
|
|
3765
|
+
observation: {
|
|
3766
|
+
matched: outcome.status === "ok" && value?.result === TAIL_FINAL_CLEAN && value.claimConsistencyMeta?.findings === 0 && verdicts === "repair,accepted,repair,accepted" && pools === "0,1,0,1" && (value.rejectedFinishCandidates?.length ?? 0) === 2 && value.rejectedFinishCandidates?.every((row) => row.verdict === "repair") === true && lessonCarried && compositions.length === 2 && judges.length === 2,
|
|
3767
|
+
detail: `run '${outcome.status}' shipped ${value?.result === TAIL_FINAL_CLEAN ? "the repaired document" : "an unexpected document"}; verdicts [${verdicts}], repairsUsed [${pools}] (fresh pool at the invocation boundary); lesson carried=${String(lessonCarried)}; meta findings=${String(value?.claimConsistencyMeta?.findings)}; ${String(compositions.length)} composition(s), ${String(judges.length)} final judge pass(es)`
|
|
3768
|
+
},
|
|
3769
|
+
artifacts: [jsonArtifact("outcome.json", {
|
|
3770
|
+
status: outcome.status,
|
|
3771
|
+
value: outcome.value ?? null,
|
|
3772
|
+
envelope: outcome.envelope
|
|
3773
|
+
}), jsonArtifact("journal.json", entries)]
|
|
3774
|
+
};
|
|
3775
|
+
}
|
|
3776
|
+
},
|
|
3674
3777
|
{
|
|
3675
3778
|
name: "claim-judge-dead-armed-refusal",
|
|
3676
3779
|
doctrine: "a final stage judge that dies on the wire under an armed posture fails the run typed for both 'fail' and 'repair' (RV3307), each message naming its armed posture, with exactly one composition paid and no repair round dispatched, never a silent settle over findings nobody ruled on",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/evals",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.241.0",
|
|
4
4
|
"description": "Rulvar evals: eval cases, golden outputs, rubric and judge graders, matrix sweeps, canary fingerprint.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@rulvar/anthropic": "1.
|
|
26
|
-
"@rulvar/
|
|
27
|
-
"@rulvar/core": "1.
|
|
28
|
-
"@rulvar/
|
|
29
|
-
"@rulvar/
|
|
25
|
+
"@rulvar/anthropic": "1.241.0",
|
|
26
|
+
"@rulvar/plan": "1.241.0",
|
|
27
|
+
"@rulvar/core": "1.241.0",
|
|
28
|
+
"@rulvar/testing": "1.241.0",
|
|
29
|
+
"@rulvar/openai": "1.241.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.20.1",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"build": "tsdown",
|
|
47
47
|
"typecheck": "tsc --noEmit",
|
|
48
48
|
"lint": "eslint .",
|
|
49
|
+
"test": "pnpm -w exec vitest run --project @rulvar/evals",
|
|
49
50
|
"pack-check": "publint --pack pnpm && attw --pack . --profile esm-only"
|
|
50
51
|
}
|
|
51
52
|
}
|