@rulvar/evals 1.195.0 → 1.197.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 +198 -1
- package/package.json +6 -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, claimCoverageOf, claimExpiry, compareRates, compileVerifiedLayer, createEngine, defineWorkflow, hashRunOutput, invoiceFromJournal, journalPricingSnapshot, lastRunSettle, memoryQuotaLimiter, pairDraftClaims, pairRunFactClaims, priceComponentsOf } from "@rulvar/core";
|
|
2
|
+
import { ConfigError, InMemoryStore, JsonlFileStore, KnowledgeCasError, LeaseHeldError, SettlementError, SupersededError, claimCoverageOf, claimExpiry, compareRates, compileVerifiedLayer, createEngine, defineWorkflow, hashRunOutput, invoiceFromJournal, journalPricingSnapshot, lastRunSettle, makeOrchestratorWorkflow, memoryQuotaLimiter, 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";
|
|
@@ -2607,6 +2607,203 @@ const SCENARIOS = [
|
|
|
2607
2607
|
})]
|
|
2608
2608
|
};
|
|
2609
2609
|
}
|
|
2610
|
+
},
|
|
2611
|
+
{
|
|
2612
|
+
name: "benchmark-primary-preflight-parity",
|
|
2613
|
+
doctrine: "the admission projection holds the synthesis reserve exactly like the live gates (RV1901): the benchmark primary configuration projects 2 of 4 seats with the equation terms exposed and the roster shortfall named admission-below-roster-floor, never the 5/5 green wave the live gate is bound to refuse",
|
|
2614
|
+
run() {
|
|
2615
|
+
const report = preflightEstimate({
|
|
2616
|
+
engine: {
|
|
2617
|
+
adapters: [new FakeAdapter({ agents: { "*": "unused" } })],
|
|
2618
|
+
defaults: { routing: {
|
|
2619
|
+
loop: FAKE_MODEL_REF,
|
|
2620
|
+
orchestrate: FAKE_MODEL_REF,
|
|
2621
|
+
synthesize: FAKE_MODEL_REF
|
|
2622
|
+
} }
|
|
2623
|
+
},
|
|
2624
|
+
run: { budgetUsd: 6 },
|
|
2625
|
+
orchestrator: {
|
|
2626
|
+
budget: {
|
|
2627
|
+
capUsd: 4.5,
|
|
2628
|
+
capFraction: 1,
|
|
2629
|
+
synthesisReserveUsd: 1
|
|
2630
|
+
},
|
|
2631
|
+
synthesis: { limits: { maxTurns: 2 } },
|
|
2632
|
+
acceptance: { minSpawnedChildren: 4 }
|
|
2633
|
+
},
|
|
2634
|
+
spawns: [
|
|
2635
|
+
"product",
|
|
2636
|
+
"finops",
|
|
2637
|
+
"durability",
|
|
2638
|
+
"adversarial"
|
|
2639
|
+
].map((label) => ({
|
|
2640
|
+
label,
|
|
2641
|
+
estCost: .62
|
|
2642
|
+
}))
|
|
2643
|
+
});
|
|
2644
|
+
const denied = report.admission.wave.filter((row) => !row.admitted);
|
|
2645
|
+
const floorFinding = report.findings.find((finding) => finding.code === "admission-below-roster-floor");
|
|
2646
|
+
const matched = report.admission.admitted === 3 && report.admission.denied === 2 && denied.every((row) => row.deniedBy === "budget") && report.admission.synthesisReserveUsd === 1 && Math.abs((report.admission.wave[0]?.reserveUsd ?? 0) - 3.5) < 1e-9 && Math.abs((report.admission.wave[0]?.heldAtEvaluationUsd ?? 0) - 1) < 1e-9 && floorFinding?.severity === "error";
|
|
2647
|
+
return Promise.resolve({
|
|
2648
|
+
observation: {
|
|
2649
|
+
matched,
|
|
2650
|
+
detail: `the wave seats ${String(report.admission.admitted)} of 5 rows (${String(report.admission.denied)} denied by budget), synthesis hold ${String(report.admission.synthesisReserveUsd)} USD, roster finding '${String(floorFinding?.code)}' at severity '${String(floorFinding?.severity)}'`
|
|
2651
|
+
},
|
|
2652
|
+
artifacts: [jsonArtifact("preflight.json", report)]
|
|
2653
|
+
});
|
|
2654
|
+
}
|
|
2655
|
+
},
|
|
2656
|
+
{
|
|
2657
|
+
name: "benchmark-recovery-root-exposure",
|
|
2658
|
+
doctrine: "a root turn refused by the in-flight exposure cap beside live children parks and completes after a hold releases (RV1902), every child terminal precedes run_settle (RV1903), and the terminal envelope and the invoice cardinality agree on the wire count (RV1904): the recovery arm terminal-failed on every one of these",
|
|
2659
|
+
async run() {
|
|
2660
|
+
let releaseChildren = () => {};
|
|
2661
|
+
const childrenGate = new Promise((resolve) => {
|
|
2662
|
+
releaseChildren = resolve;
|
|
2663
|
+
});
|
|
2664
|
+
const agentTypeOfReq = (req) => req.providerOptions?.rulvar?.agentType ?? "";
|
|
2665
|
+
let orchTurn = 0;
|
|
2666
|
+
const calls = [];
|
|
2667
|
+
const toolEvents = (name, args, call) => [
|
|
2668
|
+
{
|
|
2669
|
+
type: "tool-call-start",
|
|
2670
|
+
id: `id-${String(call)}-0`,
|
|
2671
|
+
name
|
|
2672
|
+
},
|
|
2673
|
+
{
|
|
2674
|
+
type: "tool-call-delta",
|
|
2675
|
+
id: `id-${String(call)}-0`,
|
|
2676
|
+
argsTextDelta: JSON.stringify(args)
|
|
2677
|
+
},
|
|
2678
|
+
{
|
|
2679
|
+
type: "tool-call-end",
|
|
2680
|
+
id: `id-${String(call)}-0`,
|
|
2681
|
+
args
|
|
2682
|
+
}
|
|
2683
|
+
];
|
|
2684
|
+
const handlesIn = (req) => {
|
|
2685
|
+
const found = [];
|
|
2686
|
+
for (const msg of req.messages) for (const part of msg.parts) if (part.type === "tool-result") {
|
|
2687
|
+
const result = part.result;
|
|
2688
|
+
if (typeof result.handle === "number") found.push(result.handle);
|
|
2689
|
+
}
|
|
2690
|
+
return found;
|
|
2691
|
+
};
|
|
2692
|
+
const adapter = {
|
|
2693
|
+
id: "fake",
|
|
2694
|
+
calls,
|
|
2695
|
+
caps: () => ({
|
|
2696
|
+
contextWindow: 2e5,
|
|
2697
|
+
maxOutputTokens: 4096,
|
|
2698
|
+
structuredOutput: "native",
|
|
2699
|
+
supportsTemperature: true,
|
|
2700
|
+
supportsParallelTools: true,
|
|
2701
|
+
reasoningEfforts: [],
|
|
2702
|
+
pricing: {
|
|
2703
|
+
inputUsdPerMTok: 1,
|
|
2704
|
+
outputUsdPerMTok: 10
|
|
2705
|
+
}
|
|
2706
|
+
}),
|
|
2707
|
+
async *stream(req, signal) {
|
|
2708
|
+
const call = calls.length;
|
|
2709
|
+
calls.push(req);
|
|
2710
|
+
if (agentTypeOfReq(req) !== "") {
|
|
2711
|
+
await Promise.race([childrenGate, new Promise((resolve) => {
|
|
2712
|
+
signal?.addEventListener("abort", () => resolve(), { once: true });
|
|
2713
|
+
})]);
|
|
2714
|
+
if (signal?.aborted === true) return;
|
|
2715
|
+
yield {
|
|
2716
|
+
type: "text-delta",
|
|
2717
|
+
text: "worked"
|
|
2718
|
+
};
|
|
2719
|
+
yield {
|
|
2720
|
+
type: "finish",
|
|
2721
|
+
finish: { reason: "stop" },
|
|
2722
|
+
usage: {
|
|
2723
|
+
inputTokens: 10,
|
|
2724
|
+
outputTokens: 5,
|
|
2725
|
+
cacheReadTokens: 0,
|
|
2726
|
+
cacheWriteTokens: 0
|
|
2727
|
+
}
|
|
2728
|
+
};
|
|
2729
|
+
return;
|
|
2730
|
+
}
|
|
2731
|
+
orchTurn += 1;
|
|
2732
|
+
const turn = orchTurn === 1 ? toolEvents("spawn_agent", {
|
|
2733
|
+
agentType: "worker",
|
|
2734
|
+
prompt: "task A"
|
|
2735
|
+
}, call).concat(toolEvents("spawn_agent", {
|
|
2736
|
+
agentType: "worker",
|
|
2737
|
+
prompt: "task B"
|
|
2738
|
+
}, call + 1e3)) : orchTurn === 2 ? toolEvents("await_all", { handles: handlesIn(req) }, call) : toolEvents("finish", { result: "joined after the wait" }, call);
|
|
2739
|
+
for (const event of turn) yield event;
|
|
2740
|
+
yield {
|
|
2741
|
+
type: "finish",
|
|
2742
|
+
finish: { reason: "tool-calls" },
|
|
2743
|
+
usage: {
|
|
2744
|
+
inputTokens: 10,
|
|
2745
|
+
outputTokens: 5,
|
|
2746
|
+
cacheReadTokens: 0,
|
|
2747
|
+
cacheWriteTokens: 0
|
|
2748
|
+
}
|
|
2749
|
+
};
|
|
2750
|
+
}
|
|
2751
|
+
};
|
|
2752
|
+
const store = new InMemoryStore();
|
|
2753
|
+
const engine = createEngine({
|
|
2754
|
+
adapters: [adapter],
|
|
2755
|
+
stores: { journal: store },
|
|
2756
|
+
defaults: {
|
|
2757
|
+
routing: {
|
|
2758
|
+
loop: "fake:model",
|
|
2759
|
+
orchestrate: "fake:model"
|
|
2760
|
+
},
|
|
2761
|
+
profiles: { worker: {
|
|
2762
|
+
description: "the gated worker",
|
|
2763
|
+
limits: { maxOutputTokensPerTurn: 2500 }
|
|
2764
|
+
} }
|
|
2765
|
+
}
|
|
2766
|
+
});
|
|
2767
|
+
const wf = makeOrchestratorWorkflow("join the gated wave", { limits: { maxOutputTokensPerTurn: 4e3 } });
|
|
2768
|
+
const handle = engine.run(wf, void 0, {
|
|
2769
|
+
runId: "fault-recovery-exposure",
|
|
2770
|
+
budgetUsd: 10,
|
|
2771
|
+
maxInFlightExposureUsd: .08
|
|
2772
|
+
});
|
|
2773
|
+
const waits = [];
|
|
2774
|
+
const errors = [];
|
|
2775
|
+
handle.on("budget:exposure-wait", (event) => {
|
|
2776
|
+
waits.push(event);
|
|
2777
|
+
releaseChildren();
|
|
2778
|
+
});
|
|
2779
|
+
handle.on("agent:error", (event) => errors.push(event));
|
|
2780
|
+
setTimeout(() => releaseChildren(), 4e3).unref?.();
|
|
2781
|
+
const outcome = await handle.result;
|
|
2782
|
+
const entries = await store.load("fault-recovery-exposure");
|
|
2783
|
+
const settle = entries.find((entry) => entry.kind === "decision" && entry.value?.decisionType === "run_settle");
|
|
2784
|
+
const childTerminals = entries.filter((entry) => entry.kind === "agent" && entry.scope.startsWith("agent:") && entry.status !== "running");
|
|
2785
|
+
const invoice = invoiceFromJournal(entries, (servedBy, usage) => {
|
|
2786
|
+
return usage.inputTokens / 1e6 * 1 + usage.outputTokens / 1e6 * 10;
|
|
2787
|
+
});
|
|
2788
|
+
return {
|
|
2789
|
+
observation: {
|
|
2790
|
+
matched: outcome.status === "ok" && outcome.value === "joined after the wait" && waits.length >= 1 && waits[0]?.willWait === true && errors.length === 0 && settle !== void 0 && childTerminals.length === 2 && childTerminals.every((entry) => entry.seq < settle.seq) && typeof outcome.envelope.wireRequests === "number" && outcome.envelope.wireRequests === invoice.cardinality.wireRequests,
|
|
2791
|
+
detail: `run '${outcome.status}' with ${String(waits.length)} exposure wait(s) (first willWait=${String(waits[0]?.willWait)}), ${String(errors.length)} agent:error, ${String(childTerminals.length)} child terminals before settle seq ${String(settle?.seq)}, wires ${String(outcome.envelope.wireRequests)} == invoice ${String(invoice.cardinality.wireRequests)}`
|
|
2792
|
+
},
|
|
2793
|
+
artifacts: [
|
|
2794
|
+
jsonArtifact("outcome.json", {
|
|
2795
|
+
status: outcome.status,
|
|
2796
|
+
value: outcome.value ?? null,
|
|
2797
|
+
envelope: outcome.envelope
|
|
2798
|
+
}),
|
|
2799
|
+
jsonArtifact("events.json", {
|
|
2800
|
+
waits,
|
|
2801
|
+
errors
|
|
2802
|
+
}),
|
|
2803
|
+
jsonArtifact("journal.json", entries)
|
|
2804
|
+
]
|
|
2805
|
+
};
|
|
2806
|
+
}
|
|
2610
2807
|
}
|
|
2611
2808
|
];
|
|
2612
2809
|
/** The scenario names in run order. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/evals",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.197.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/
|
|
26
|
-
"@rulvar/
|
|
27
|
-
"@rulvar/
|
|
28
|
-
"@rulvar/
|
|
29
|
-
"@rulvar/
|
|
25
|
+
"@rulvar/core": "1.197.0",
|
|
26
|
+
"@rulvar/anthropic": "1.197.0",
|
|
27
|
+
"@rulvar/openai": "1.197.0",
|
|
28
|
+
"@rulvar/plan": "1.197.0",
|
|
29
|
+
"@rulvar/testing": "1.197.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.20.1",
|