@remnic/bench 9.6.20 → 9.6.22

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 CHANGED
@@ -5497,17 +5497,473 @@ var BENCHMARK_RESULT_SCHEMA = {
5497
5497
 
5498
5498
  // src/repro-manifest.ts
5499
5499
  import { execFileSync } from "child_process";
5500
- import { createHash as createHash3 } from "crypto";
5500
+ import { createHash as createHash4 } from "crypto";
5501
5501
  import { createReadStream } from "fs";
5502
- import { lstat as lstat3, mkdir as mkdir3, readFile as readFile4, readdir as readdir4, readlink, realpath as realpath3, stat as stat2, writeFile as writeFile3 } from "fs/promises";
5503
- import os2 from "os";
5504
- import path4 from "path";
5502
+ import { lstat as lstat3, mkdir as mkdir4, readFile as readFile5, readdir as readdir4, readlink, realpath as realpath3, stat as stat2, writeFile as writeFile4 } from "fs/promises";
5503
+ import os3 from "os";
5504
+ import path5 from "path";
5505
5505
 
5506
- // src/results-store.ts
5507
- import { mkdir as mkdir2, readdir as readdir3, readFile as readFile3, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
5508
- import fs from "fs";
5506
+ // src/providers/codex-credit-budget.ts
5507
+ import { createHash as createHash3 } from "crypto";
5508
+ import { mkdir as mkdir2, open, readFile as readFile3, rename as rename2, rmdir, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
5509
5509
  import os from "os";
5510
5510
  import path3 from "path";
5511
+ var ONE_MILLION = 1e6;
5512
+ var MAX_BOUNDED_CALL_CREDITS = 300;
5513
+ var SOL_MODEL = /^gpt-5\.6-sol$/i;
5514
+ var CREDIT_RATES = [
5515
+ [/^gpt-5\.6-sol$/i, { input: 125, cachedInput: 12.5, output: 750 }],
5516
+ [/^gpt-5\.6-terra$/i, { input: 62.5, cachedInput: 6.25, output: 375 }],
5517
+ [/^gpt-5\.6-luna$/i, { input: 25, cachedInput: 2.5, output: 150 }],
5518
+ [/^gpt-5\.5$/i, { input: 125, cachedInput: 12.5, output: 750 }],
5519
+ [/^gpt-5\.4-mini$/i, { input: 18.75, cachedInput: 1.875, output: 113 }],
5520
+ [/^gpt-5\.4$/i, { input: 62.5, cachedInput: 6.25, output: 375 }],
5521
+ [/^gpt-5\.3-codex$/i, { input: 43.75, cachedInput: 4.375, output: 350 }],
5522
+ [/^gpt-5\.2$/i, { input: 43.75, cachedInput: 4.375, output: 350 }]
5523
+ ];
5524
+ var completionQueue = Promise.resolve();
5525
+ var CodexCreditAccountingError = class extends Error {
5526
+ constructor(message) {
5527
+ super(message);
5528
+ this.name = "CodexCreditAccountingError";
5529
+ }
5530
+ };
5531
+ var CodexCreditDispatchError = class extends Error {
5532
+ constructor(message, options) {
5533
+ super(message, options);
5534
+ this.name = "CodexCreditDispatchError";
5535
+ }
5536
+ };
5537
+ function resolveCodexCreditBudgetConfig(env = process.env, fallbackRunId) {
5538
+ const rawBudget = env.REMNIC_BENCH_CODEX_CREDIT_BUDGET?.trim();
5539
+ if (!rawBudget) return void 0;
5540
+ const budgetCredits = parsePositiveNumber(
5541
+ rawBudget,
5542
+ "REMNIC_BENCH_CODEX_CREDIT_BUDGET"
5543
+ );
5544
+ const reserveCredits = parseNonNegativeNumber(
5545
+ env.REMNIC_BENCH_CODEX_CREDIT_RESERVE?.trim() ?? "473",
5546
+ "REMNIC_BENCH_CODEX_CREDIT_RESERVE"
5547
+ );
5548
+ if (reserveCredits >= budgetCredits) {
5549
+ throw new Error(
5550
+ "REMNIC_BENCH_CODEX_CREDIT_RESERVE must be smaller than REMNIC_BENCH_CODEX_CREDIT_BUDGET"
5551
+ );
5552
+ }
5553
+ if (reserveCredits < MAX_BOUNDED_CALL_CREDITS) {
5554
+ throw new Error(
5555
+ `REMNIC_BENCH_CODEX_CREDIT_RESERVE must be at least ${MAX_BOUNDED_CALL_CREDITS} credits to cover the conservative maximum cost of the one serialized in-flight call`
5556
+ );
5557
+ }
5558
+ const ledgerPath = path3.resolve(
5559
+ expandHomeRelativePath(
5560
+ env.REMNIC_BENCH_CODEX_CREDIT_LEDGER?.trim() || ".remnic/bench/codex-credit-ledger.json"
5561
+ )
5562
+ );
5563
+ const runId = parseOptionalRunId(env.REMNIC_BENCH_RUN_ID) ?? parseOptionalRunId(fallbackRunId);
5564
+ return {
5565
+ budgetCredits,
5566
+ reserveCredits,
5567
+ ledgerPath,
5568
+ allowSol: /^(?:1|true|yes|on)$/i.test(
5569
+ env.REMNIC_BENCH_CODEX_ALLOW_SOL?.trim() ?? ""
5570
+ ),
5571
+ ...runId ? { runId } : {}
5572
+ };
5573
+ }
5574
+ async function runWithinCodexCreditBudget(args) {
5575
+ if (!args.config) {
5576
+ return (await args.run()).value;
5577
+ }
5578
+ const previous = completionQueue;
5579
+ let release;
5580
+ completionQueue = new Promise((resolve) => {
5581
+ release = resolve;
5582
+ });
5583
+ await previous;
5584
+ const lockPath = `${args.config.ledgerPath}.lock`;
5585
+ let lock;
5586
+ let dispatchStarted = false;
5587
+ let accountingSettled = false;
5588
+ try {
5589
+ await mkdir2(path3.dirname(lockPath), { recursive: true, mode: 448 });
5590
+ lock = await acquireLedgerLock(lockPath);
5591
+ assertModelAllowed(args.model, args.config);
5592
+ const ledger = await readLedger(args.config);
5593
+ if (ledger.blockedReason) {
5594
+ throw new Error(
5595
+ `Codex credit ledger is blocked pending manual reconciliation: ${ledger.blockedReason}`
5596
+ );
5597
+ }
5598
+ const usableCredits = args.config.budgetCredits - args.config.reserveCredits;
5599
+ const dispatchHeadroom = usableCredits - ledger.spentCredits;
5600
+ if (dispatchHeadroom < MAX_BOUNDED_CALL_CREDITS) {
5601
+ throw new Error(
5602
+ `Codex credit budget cannot safely dispatch another call: ${ledger.spentCredits.toFixed(3)} spent; ${dispatchHeadroom.toFixed(3)} remains below the ${usableCredits.toFixed(3)} planned-spend ceiling, but ${MAX_BOUNDED_CALL_CREDITS.toFixed(3)} credits of worst-case call headroom are required.`
5603
+ );
5604
+ }
5605
+ await writeLockState(lock, "in-flight");
5606
+ dispatchStarted = true;
5607
+ let result;
5608
+ try {
5609
+ result = await args.run();
5610
+ } catch (error) {
5611
+ if (error instanceof CodexCreditDispatchError) {
5612
+ await writeLockState(lock, "settled");
5613
+ accountingSettled = true;
5614
+ } else {
5615
+ const blockedLedger = {
5616
+ ...ledger,
5617
+ blockedReason: error instanceof CodexCreditAccountingError ? error.message : `Codex dispatch outcome is unknown after an unexpected error: ${safeErrorMessage(error)}`
5618
+ };
5619
+ await writeLedger(args.config.ledgerPath, blockedLedger);
5620
+ await writeLockState(lock, "settled");
5621
+ accountingSettled = true;
5622
+ }
5623
+ throw error;
5624
+ }
5625
+ const credits = calculateCodexCredits(args.model, result.usage);
5626
+ const nextSpent = ledger.spentCredits + credits;
5627
+ const nextLedger = {
5628
+ ...ledger,
5629
+ spentCredits: nextSpent,
5630
+ entries: [
5631
+ ...ledger.entries,
5632
+ {
5633
+ at: (/* @__PURE__ */ new Date()).toISOString(),
5634
+ model: args.model,
5635
+ credits,
5636
+ ...args.config.runId ? { runId: args.config.runId } : {},
5637
+ ...result.usage
5638
+ }
5639
+ ]
5640
+ };
5641
+ await writeLedger(args.config.ledgerPath, nextLedger);
5642
+ await writeLockState(lock, "settled");
5643
+ accountingSettled = true;
5644
+ args.onUsagePersisted?.(result.usage);
5645
+ if (nextSpent > usableCredits) {
5646
+ throw new Error(
5647
+ `Codex planned-spend ceiling exceeded by completed call: ${nextSpent.toFixed(3)} > ${usableCredits.toFixed(3)} credits. Usage was persisted; stop the benchmark immediately.`
5648
+ );
5649
+ }
5650
+ return result.value;
5651
+ } finally {
5652
+ try {
5653
+ if (lock) {
5654
+ try {
5655
+ await lock.close();
5656
+ } finally {
5657
+ if (!dispatchStarted || accountingSettled) {
5658
+ await removeOwnedLedgerLock(lockPath);
5659
+ }
5660
+ }
5661
+ }
5662
+ } finally {
5663
+ release();
5664
+ }
5665
+ }
5666
+ }
5667
+ async function acquireLedgerLock(lockPath) {
5668
+ for (let attempt = 0; attempt < 2; attempt += 1) {
5669
+ try {
5670
+ await mkdir2(lockPath, { mode: 448 });
5671
+ } catch (error) {
5672
+ if (error.code !== "EEXIST") throw error;
5673
+ const owner = await readLockOwner(lockPath);
5674
+ if (!owner || isProcessAlive(owner.pid) || owner.phase === "in-flight") {
5675
+ throw new Error(
5676
+ `Codex credit ledger is locked${owner?.phase === "in-flight" ? " with unreconciled in-flight usage" : " by another benchmark process"} (${lockPath}); refusing credit spend.`
5677
+ );
5678
+ }
5679
+ await reclaimStaleLedgerLock(lockPath, owner);
5680
+ continue;
5681
+ }
5682
+ let createdLock;
5683
+ try {
5684
+ await mkdir2(lockHeldPath(lockPath));
5685
+ createdLock = await open(lockOwnerPath(lockPath), "wx", 384);
5686
+ await writeLockState(createdLock, "preflight");
5687
+ return createdLock;
5688
+ } catch (error) {
5689
+ await createdLock?.close().catch(() => void 0);
5690
+ await unlink2(lockOwnerPath(lockPath)).catch(() => void 0);
5691
+ await rmdir(lockHeldPath(lockPath)).catch(() => void 0);
5692
+ await rmdir(lockPath).catch(() => void 0);
5693
+ throw error;
5694
+ }
5695
+ }
5696
+ throw new Error(`Unable to acquire Codex credit ledger lock (${lockPath})`);
5697
+ }
5698
+ async function readLockOwner(lockPath) {
5699
+ try {
5700
+ const parsed = JSON.parse(await readFile3(lockOwnerPath(lockPath), "utf8"));
5701
+ if (!Number.isSafeInteger(parsed.pid) || parsed.pid <= 0 || parsed.phase !== "preflight" && parsed.phase !== "in-flight" && parsed.phase !== "settled") {
5702
+ return void 0;
5703
+ }
5704
+ return { pid: parsed.pid, phase: parsed.phase };
5705
+ } catch {
5706
+ return void 0;
5707
+ }
5708
+ }
5709
+ async function reclaimStaleLedgerLock(lockPath, expectedOwner) {
5710
+ try {
5711
+ await rmdir(lockHeldPath(lockPath));
5712
+ } catch (error) {
5713
+ throw new Error(
5714
+ `Codex credit ledger stale-lock reclamation is already claimed or incomplete (${lockPath}); refusing credit spend: ${safeErrorMessage(error)}`
5715
+ );
5716
+ }
5717
+ const currentOwner = await readLockOwner(lockPath);
5718
+ if (!currentOwner || currentOwner.pid !== expectedOwner.pid || currentOwner.phase !== expectedOwner.phase || isProcessAlive(currentOwner.pid) || currentOwner.phase === "in-flight") {
5719
+ throw new Error(
5720
+ `Codex credit ledger owner changed during stale-lock reclamation (${lockPath}); refusing credit spend.`
5721
+ );
5722
+ }
5723
+ await unlink2(lockOwnerPath(lockPath));
5724
+ await rmdir(lockPath);
5725
+ }
5726
+ async function removeOwnedLedgerLock(lockPath) {
5727
+ await rmdir(lockHeldPath(lockPath));
5728
+ await unlink2(lockOwnerPath(lockPath));
5729
+ await rmdir(lockPath);
5730
+ }
5731
+ function lockOwnerPath(lockPath) {
5732
+ return path3.join(lockPath, "owner.json");
5733
+ }
5734
+ function lockHeldPath(lockPath) {
5735
+ return path3.join(lockPath, "held");
5736
+ }
5737
+ async function writeLockState(lock, phase) {
5738
+ const contents = `${JSON.stringify({
5739
+ pid: process.pid,
5740
+ phase,
5741
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
5742
+ })}
5743
+ `;
5744
+ await lock.truncate(0);
5745
+ await lock.write(contents, 0, "utf8");
5746
+ await lock.sync();
5747
+ }
5748
+ function isProcessAlive(pid) {
5749
+ try {
5750
+ process.kill(pid, 0);
5751
+ return true;
5752
+ } catch (error) {
5753
+ return error.code === "EPERM";
5754
+ }
5755
+ }
5756
+ function parseCodexJsonlUsage(output) {
5757
+ let usage;
5758
+ for (const line of output.split(/\r?\n/)) {
5759
+ const trimmed = line.trim();
5760
+ if (!trimmed.startsWith("{")) continue;
5761
+ try {
5762
+ const event = JSON.parse(trimmed);
5763
+ if (event.type !== "turn.completed" || !event.usage) continue;
5764
+ const inputTokens = readCounter(event.usage.input_tokens);
5765
+ const outputTokens = readCounter(event.usage.output_tokens);
5766
+ const cachedInputTokens = readOptionalCounter(
5767
+ event.usage.cached_input_tokens
5768
+ );
5769
+ const reasoningOutputTokens = readOptionalCounter(
5770
+ event.usage.reasoning_output_tokens
5771
+ );
5772
+ if (inputTokens !== void 0 && outputTokens !== void 0 && cachedInputTokens !== void 0 && reasoningOutputTokens !== void 0) {
5773
+ usage = {
5774
+ inputTokens,
5775
+ cachedInputTokens,
5776
+ outputTokens,
5777
+ reasoningOutputTokens
5778
+ };
5779
+ }
5780
+ } catch {
5781
+ }
5782
+ }
5783
+ return usage;
5784
+ }
5785
+ function calculateCodexCredits(model, usage) {
5786
+ const rate = resolveRate(model);
5787
+ const cached = Math.min(usage.inputTokens, usage.cachedInputTokens);
5788
+ const uncached = usage.inputTokens - cached;
5789
+ return (uncached * rate.input + cached * rate.cachedInput + usage.outputTokens * rate.output) / ONE_MILLION;
5790
+ }
5791
+ async function buildCodexCreditReceipt(ledgerPath, runId) {
5792
+ const resolvedPath = path3.resolve(expandHomeRelativePath(ledgerPath));
5793
+ const contents = await readFile3(resolvedPath);
5794
+ const ledger = parseLedger(JSON.parse(contents.toString("utf8")));
5795
+ const normalizedRunId = parseOptionalRunId(runId);
5796
+ const cumulative = summarizeLedgerEntries(ledger.entries);
5797
+ const runEntries = normalizedRunId ? ledger.entries.filter((entry) => entry.runId === normalizedRunId) : [];
5798
+ return {
5799
+ schemaVersion: 1,
5800
+ ledgerSha256: createHash3("sha256").update(contents).digest("hex"),
5801
+ budgetCredits: ledger.budgetCredits,
5802
+ reserveCredits: ledger.reserveCredits,
5803
+ plannedSpendCeilingCredits: ledger.budgetCredits - ledger.reserveCredits,
5804
+ totalSpentCredits: ledger.spentCredits,
5805
+ totalRemainingCredits: ledger.budgetCredits - ledger.spentCredits,
5806
+ blocked: ledger.blockedReason !== void 0,
5807
+ cumulative,
5808
+ ...normalizedRunId ? { run: { id: normalizedRunId, ...summarizeLedgerEntries(runEntries) } } : {}
5809
+ };
5810
+ }
5811
+ function resolveRate(model) {
5812
+ const match = CREDIT_RATES.find(([pattern]) => pattern.test(model));
5813
+ if (!match) {
5814
+ throw new Error(
5815
+ `No Codex credit rate is configured for model ${JSON.stringify(model)}; refusing to run under a bounded credit budget.`
5816
+ );
5817
+ }
5818
+ return match[1];
5819
+ }
5820
+ function assertModelAllowed(model, config) {
5821
+ resolveRate(model);
5822
+ if (SOL_MODEL.test(model) && !config.allowSol) {
5823
+ throw new Error(
5824
+ "gpt-5.6-sol is disabled for bounded benchmark runs because it is the most expensive GPT-5.6 tier. Use gpt-5.6-terra or gpt-5.6-luna, or explicitly set REMNIC_BENCH_CODEX_ALLOW_SOL=1."
5825
+ );
5826
+ }
5827
+ }
5828
+ async function readLedger(config) {
5829
+ try {
5830
+ const parsed = parseLedger(
5831
+ JSON.parse(await readFile3(config.ledgerPath, "utf8"))
5832
+ );
5833
+ if (parsed.budgetCredits !== config.budgetCredits || parsed.reserveCredits !== config.reserveCredits) {
5834
+ throw new Error("ledger schema or budget does not match this run");
5835
+ }
5836
+ return parsed;
5837
+ } catch (error) {
5838
+ if (error.code !== "ENOENT") {
5839
+ throw new Error(`Invalid Codex credit ledger at ${config.ledgerPath}: ${String(error)}`);
5840
+ }
5841
+ return {
5842
+ schemaVersion: 1,
5843
+ budgetCredits: config.budgetCredits,
5844
+ reserveCredits: config.reserveCredits,
5845
+ spentCredits: 0,
5846
+ entries: []
5847
+ };
5848
+ }
5849
+ }
5850
+ function parseLedger(parsed) {
5851
+ const entryCredits = Array.isArray(parsed.entries) ? parsed.entries.reduce(
5852
+ (sum, entry) => sum + (typeof entry?.credits === "number" ? entry.credits ?? 0 : 0),
5853
+ 0
5854
+ ) : Number.NaN;
5855
+ if (parsed.schemaVersion !== 1 || typeof parsed.budgetCredits !== "number" || !Number.isFinite(parsed.budgetCredits) || parsed.budgetCredits <= 0 || typeof parsed.reserveCredits !== "number" || !Number.isFinite(parsed.reserveCredits) || parsed.reserveCredits < 0 || parsed.reserveCredits >= parsed.budgetCredits || typeof parsed.spentCredits !== "number" || !Number.isFinite(parsed.spentCredits) || parsed.spentCredits < 0 || !Array.isArray(parsed.entries) || !parsed.entries.every(isLedgerEntry) || Math.abs(entryCredits - parsed.spentCredits) > 1e-9 || parsed.blockedReason !== void 0 && typeof parsed.blockedReason !== "string") {
5856
+ throw new Error("ledger schema is invalid");
5857
+ }
5858
+ return parsed;
5859
+ }
5860
+ function isLedgerEntry(entry) {
5861
+ if (!entry || typeof entry !== "object") return false;
5862
+ const candidate = entry;
5863
+ return typeof candidate.at === "string" && typeof candidate.model === "string" && candidate.model.length > 0 && typeof candidate.credits === "number" && Number.isFinite(candidate.credits) && candidate.credits >= 0 && (candidate.runId === void 0 || isValidStoredRunId(candidate.runId)) && readCounter(candidate.inputTokens) !== void 0 && readCounter(candidate.cachedInputTokens) !== void 0 && readCounter(candidate.outputTokens) !== void 0 && readCounter(candidate.reasoningOutputTokens) !== void 0 && (candidate.cachedInputTokens ?? 0) <= (candidate.inputTokens ?? 0) && isEntryCreditConsistent(candidate);
5864
+ }
5865
+ function isEntryCreditConsistent(entry) {
5866
+ try {
5867
+ return Math.abs(calculateCodexCredits(entry.model, entry) - entry.credits) <= 1e-9;
5868
+ } catch {
5869
+ return false;
5870
+ }
5871
+ }
5872
+ function summarizeLedgerEntries(entries) {
5873
+ const byModel = /* @__PURE__ */ new Map();
5874
+ for (const entry of entries) {
5875
+ const modelEntries = byModel.get(entry.model) ?? [];
5876
+ modelEntries.push(entry);
5877
+ byModel.set(entry.model, modelEntries);
5878
+ }
5879
+ const totals = summarizeUsage(entries);
5880
+ return {
5881
+ calls: entries.length,
5882
+ credits: entries.reduce((sum, entry) => sum + entry.credits, 0),
5883
+ ...totals,
5884
+ models: [...byModel.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([model, modelEntries]) => ({
5885
+ model,
5886
+ calls: modelEntries.length,
5887
+ credits: modelEntries.reduce((sum, entry) => sum + entry.credits, 0),
5888
+ ...summarizeUsage(modelEntries)
5889
+ }))
5890
+ };
5891
+ }
5892
+ function summarizeUsage(entries) {
5893
+ return entries.reduce(
5894
+ (totals, entry) => ({
5895
+ inputTokens: totals.inputTokens + entry.inputTokens,
5896
+ cachedInputTokens: totals.cachedInputTokens + entry.cachedInputTokens,
5897
+ outputTokens: totals.outputTokens + entry.outputTokens,
5898
+ reasoningOutputTokens: totals.reasoningOutputTokens + entry.reasoningOutputTokens
5899
+ }),
5900
+ { inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, reasoningOutputTokens: 0 }
5901
+ );
5902
+ }
5903
+ async function writeLedger(filePath, ledger) {
5904
+ await mkdir2(path3.dirname(filePath), { recursive: true, mode: 448 });
5905
+ const tempPath = `${filePath}.${process.pid}.tmp`;
5906
+ await writeFile2(tempPath, `${JSON.stringify(ledger, null, 2)}
5907
+ `, {
5908
+ encoding: "utf8",
5909
+ mode: 384
5910
+ });
5911
+ await rename2(tempPath, filePath);
5912
+ }
5913
+ function readCounter(value) {
5914
+ return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
5915
+ }
5916
+ function readOptionalCounter(value) {
5917
+ return value === void 0 ? 0 : readCounter(value);
5918
+ }
5919
+ function safeErrorMessage(error) {
5920
+ return error instanceof Error ? error.message : String(error);
5921
+ }
5922
+ function expandHomeRelativePath(value) {
5923
+ if (value === "~") return os.homedir();
5924
+ if (value.startsWith("~/") || value.startsWith("~\\")) {
5925
+ return path3.join(os.homedir(), value.slice(2));
5926
+ }
5927
+ return value;
5928
+ }
5929
+ function parsePositiveNumber(value, name) {
5930
+ const parsed = Number(value);
5931
+ if (!Number.isFinite(parsed) || parsed <= 0) {
5932
+ throw new Error(`${name} must be a finite number greater than zero`);
5933
+ }
5934
+ return parsed;
5935
+ }
5936
+ function parseNonNegativeNumber(value, name) {
5937
+ const parsed = Number(value);
5938
+ if (!Number.isFinite(parsed) || parsed < 0) {
5939
+ throw new Error(`${name} must be a finite non-negative number`);
5940
+ }
5941
+ return parsed;
5942
+ }
5943
+ function parseOptionalRunId(value) {
5944
+ const runId = value?.trim();
5945
+ if (!runId) return void 0;
5946
+ if (runId.length > 128 || hasControlCharacters(runId)) {
5947
+ throw new Error("REMNIC_BENCH_RUN_ID must be at most 128 characters without control characters");
5948
+ }
5949
+ return runId;
5950
+ }
5951
+ function isValidStoredRunId(value) {
5952
+ return typeof value === "string" && value.length > 0 && value.length <= 128 && value === value.trim() && !hasControlCharacters(value);
5953
+ }
5954
+ function hasControlCharacters(value) {
5955
+ for (const character of value) {
5956
+ const codePoint = character.codePointAt(0) ?? 0;
5957
+ if (codePoint <= 31 || codePoint === 127) return true;
5958
+ }
5959
+ return false;
5960
+ }
5961
+
5962
+ // src/results-store.ts
5963
+ import { mkdir as mkdir3, readdir as readdir3, readFile as readFile4, unlink as unlink3, writeFile as writeFile3 } from "fs/promises";
5964
+ import fs from "fs";
5965
+ import os2 from "os";
5966
+ import path4 from "path";
5511
5967
 
5512
5968
  // src/integrity/contamination.ts
5513
5969
  var EMPTY_CONTAMINATION_MANIFEST = {
@@ -5972,14 +6428,14 @@ ${renderProvenance(result, provenance)}
5972
6428
  var BASELINE_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
5973
6429
  var REPRO_MANIFEST_FILENAME = "MANIFEST.json";
5974
6430
  function defaultBenchmarkBaselineDir() {
5975
- const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? os.homedir();
5976
- return path3.join(homeDir, ".remnic", "bench", "baselines");
6431
+ const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? os2.homedir();
6432
+ return path4.join(homeDir, ".remnic", "bench", "baselines");
5977
6433
  }
5978
6434
  function defaultBenchmarkPublishPath(target) {
5979
- const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? os.homedir();
6435
+ const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? os2.homedir();
5980
6436
  switch (target) {
5981
6437
  case "remnic-ai":
5982
- return path3.join(homeDir, ".remnic", "published", "benchmarks.json");
6438
+ return path4.join(homeDir, ".remnic", "published", "benchmarks.json");
5983
6439
  }
5984
6440
  }
5985
6441
  function compareResultSummaries(left, right) {
@@ -6004,10 +6460,10 @@ function isFiniteNumber(value) {
6004
6460
  return typeof value === "number" && Number.isFinite(value);
6005
6461
  }
6006
6462
  async function loadBenchmarkReportCardProvenance(outputDir, resultId) {
6007
- const manifestPath = path3.join(outputDir, REPRO_MANIFEST_FILENAME);
6463
+ const manifestPath = path4.join(outputDir, REPRO_MANIFEST_FILENAME);
6008
6464
  let parsed;
6009
6465
  try {
6010
- parsed = JSON.parse(await readFile3(manifestPath, "utf8"));
6466
+ parsed = JSON.parse(await readFile4(manifestPath, "utf8"));
6011
6467
  } catch {
6012
6468
  return {};
6013
6469
  }
@@ -6114,7 +6570,7 @@ function toBaselineSummary(baseline, filePath) {
6114
6570
  };
6115
6571
  }
6116
6572
  async function loadBenchmarkResult(filePath) {
6117
- const content = await readFile3(filePath, "utf8");
6573
+ const content = await readFile4(filePath, "utf8");
6118
6574
  const parsed = JSON.parse(content);
6119
6575
  if (!isBenchmarkResult(parsed)) {
6120
6576
  throw new Error(`Invalid benchmark result file: ${filePath}`);
@@ -6131,7 +6587,7 @@ async function listBenchmarkResults(outputDir) {
6131
6587
  if (!entry.isFile() || !entry.name.endsWith(".json")) {
6132
6588
  continue;
6133
6589
  }
6134
- const filePath = path3.join(outputDir, entry.name);
6590
+ const filePath = path4.join(outputDir, entry.name);
6135
6591
  try {
6136
6592
  const result = await loadBenchmarkResult(filePath);
6137
6593
  results.push(toSummary(result, filePath));
@@ -6144,20 +6600,20 @@ async function listBenchmarkResults(outputDir) {
6144
6600
  async function saveBenchmarkBaseline(baselineDir, name, result, source) {
6145
6601
  assertValidBaselineName(name);
6146
6602
  assertUsableBaselineDir(baselineDir);
6147
- await mkdir2(baselineDir, { recursive: true });
6148
- const filePath = path3.join(baselineDir, `${name}.json`);
6603
+ await mkdir3(baselineDir, { recursive: true });
6604
+ const filePath = path4.join(baselineDir, `${name}.json`);
6149
6605
  const payload = {
6150
6606
  name,
6151
6607
  savedAt: (/* @__PURE__ */ new Date()).toISOString(),
6152
6608
  result,
6153
6609
  source
6154
6610
  };
6155
- await writeFile2(filePath, `${JSON.stringify(payload, null, 2)}
6611
+ await writeFile3(filePath, `${JSON.stringify(payload, null, 2)}
6156
6612
  `);
6157
6613
  return filePath;
6158
6614
  }
6159
6615
  async function loadBenchmarkBaseline(filePath) {
6160
- const content = await readFile3(filePath, "utf8");
6616
+ const content = await readFile4(filePath, "utf8");
6161
6617
  const parsed = JSON.parse(content);
6162
6618
  if (!isStoredBenchmarkBaseline(parsed)) {
6163
6619
  throw new Error(`Invalid benchmark baseline file: ${filePath}`);
@@ -6175,7 +6631,7 @@ async function listBenchmarkBaselines(baselineDir) {
6175
6631
  if (!entry.isFile() || !entry.name.endsWith(".json")) {
6176
6632
  continue;
6177
6633
  }
6178
- const filePath = path3.join(baselineDir, entry.name);
6634
+ const filePath = path4.join(baselineDir, entry.name);
6179
6635
  try {
6180
6636
  const baseline = await loadBenchmarkBaseline(filePath);
6181
6637
  baselines.push(toBaselineSummary(baseline, filePath));
@@ -6192,7 +6648,7 @@ async function resolveBenchmarkResultReference(outputDir, reference) {
6192
6648
  return exactIdMatch;
6193
6649
  }
6194
6650
  const basenameMatch = summaries.find(
6195
- (summary) => path3.basename(summary.path) === reference
6651
+ (summary) => path4.basename(summary.path) === reference
6196
6652
  );
6197
6653
  if (basenameMatch) {
6198
6654
  return basenameMatch;
@@ -6208,7 +6664,7 @@ async function resolveBenchmarkResultReference(outputDir, reference) {
6208
6664
  return void 0;
6209
6665
  }
6210
6666
  function looksLikeFilesystemPath(reference) {
6211
- return path3.isAbsolute(reference) || reference.includes("/") || reference.includes(path3.sep) || reference.endsWith(".json");
6667
+ return path4.isAbsolute(reference) || reference.includes("/") || reference.includes(path4.sep) || reference.endsWith(".json");
6212
6668
  }
6213
6669
  async function deleteBenchmarkResults(outputDir, references) {
6214
6670
  const summaries = await listBenchmarkResults(outputDir);
@@ -6216,9 +6672,9 @@ async function deleteBenchmarkResults(outputDir, references) {
6216
6672
  const missing = [];
6217
6673
  const seenPaths = /* @__PURE__ */ new Set();
6218
6674
  for (const reference of references) {
6219
- let summary = summaries.find((entry) => entry.id === reference) ?? summaries.find((entry) => path3.basename(entry.path) === reference);
6675
+ let summary = summaries.find((entry) => entry.id === reference) ?? summaries.find((entry) => path4.basename(entry.path) === reference);
6220
6676
  if (!summary && looksLikeFilesystemPath(reference)) {
6221
- const canonicalRef = path3.resolve(reference);
6677
+ const canonicalRef = path4.resolve(reference);
6222
6678
  if (seenPaths.has(canonicalRef)) {
6223
6679
  continue;
6224
6680
  }
@@ -6235,13 +6691,13 @@ async function deleteBenchmarkResults(outputDir, references) {
6235
6691
  missing.push(reference);
6236
6692
  continue;
6237
6693
  }
6238
- const canonicalPath = path3.resolve(summary.path);
6694
+ const canonicalPath = path4.resolve(summary.path);
6239
6695
  if (seenPaths.has(canonicalPath)) {
6240
6696
  continue;
6241
6697
  }
6242
6698
  seenPaths.add(canonicalPath);
6243
6699
  try {
6244
- await unlink2(summary.path);
6700
+ await unlink3(summary.path);
6245
6701
  } catch (error) {
6246
6702
  if (error.code === "ENOENT") {
6247
6703
  } else {
@@ -6366,8 +6822,8 @@ async function buildBenchmarkPublishFeed(outputDir, target, options = {}) {
6366
6822
  };
6367
6823
  }
6368
6824
  async function writeBenchmarkPublishFeed(feed, outputPath) {
6369
- await mkdir2(path3.dirname(outputPath), { recursive: true });
6370
- await writeFile2(outputPath, `${JSON.stringify(feed, null, 2)}
6825
+ await mkdir3(path4.dirname(outputPath), { recursive: true });
6826
+ await writeFile3(outputPath, `${JSON.stringify(feed, null, 2)}
6371
6827
  `);
6372
6828
  return outputPath;
6373
6829
  }
@@ -6422,8 +6878,8 @@ function renderBenchmarkResultExport(result, format, options = {}) {
6422
6878
  // src/run-identity.ts
6423
6879
  var BENCHMARK_RUN_ID_ENV = "REMNIC_BENCH_RUN_ID";
6424
6880
  var generatedBenchmarkRunId;
6425
- function resolveBenchmarkRunId() {
6426
- const explicit = process.env[BENCHMARK_RUN_ID_ENV]?.trim();
6881
+ function resolveBenchmarkRunId(env = process.env) {
6882
+ const explicit = env[BENCHMARK_RUN_ID_ENV]?.trim();
6427
6883
  if (explicit) {
6428
6884
  return explicit;
6429
6885
  }
@@ -6627,14 +7083,22 @@ var BENCH_OPTION_BOUNDARY_FLAGS = /* @__PURE__ */ new Set([
6627
7083
  ]);
6628
7084
  var SECRET_KEY_PATTERN = /(^|[-_])(?:api[-_]?key|secret[-_]?access[-_]?key|secret[-_]?key|client[-_]?secret(?:[-_]?key)?|app[-_]?secret(?:[-_]?key)?|provider[-_]?secret(?:[-_]?key)?|access[-_]?key|private[-_]?key|secret|password|authorization|credential|access[-_]?token|auth[-_]?token|refresh[-_]?token|id[-_]?token|token)$/i;
6629
7085
  var REDACTED_ARG_VALUE = "[redacted]";
7086
+ var CODEX_CREDIT_REPRO_ENV_KEYS = [
7087
+ "REMNIC_BENCH_CODEX_ALLOW_SOL",
7088
+ "REMNIC_BENCH_CODEX_CREDIT_BUDGET",
7089
+ "REMNIC_BENCH_CODEX_CREDIT_LEDGER",
7090
+ "REMNIC_BENCH_CODEX_CREDIT_RESERVE",
7091
+ "REMNIC_BENCH_CODEX_CLI_DIAGNOSTICS_MODE",
7092
+ "REMNIC_BENCH_RUN_ID"
7093
+ ];
6630
7094
  function sha256String(value) {
6631
- return createHash3("sha256").update(value).digest("hex");
7095
+ return createHash4("sha256").update(value).digest("hex");
6632
7096
  }
6633
7097
  function sha256Buffer(value) {
6634
- return createHash3("sha256").update(value).digest("hex");
7098
+ return createHash4("sha256").update(value).digest("hex");
6635
7099
  }
6636
7100
  async function sha256File(filePath) {
6637
- const hash = createHash3("sha256");
7101
+ const hash = createHash4("sha256");
6638
7102
  await new Promise((resolve, reject) => {
6639
7103
  const stream = createReadStream(filePath);
6640
7104
  stream.on("data", (chunk) => hash.update(chunk));
@@ -7137,7 +7601,10 @@ function isAsciiAlnum2(char) {
7137
7601
  return isUppercaseAscii(char) || isLowercaseAscii(char) || char >= "0" && char <= "9";
7138
7602
  }
7139
7603
  function sanitizeEnvKeys(env, explicitKeys) {
7140
- const sourceKeys = explicitKeys ?? Object.keys(env ?? {});
7604
+ const sourceKeys = [
7605
+ ...explicitKeys ?? Object.keys(env ?? {}),
7606
+ ...CODEX_CREDIT_REPRO_ENV_KEYS.filter((key) => env?.[key] !== void 0)
7607
+ ];
7141
7608
  return [...new Set(sourceKeys)].filter((key) => typeof key === "string" && key.length > 0).sort((left, right) => left.localeCompare(right));
7142
7609
  }
7143
7610
  function gitOutput(args, cwd) {
@@ -7191,7 +7658,8 @@ function buildArtifactHashIdentity(manifest) {
7191
7658
  ...manifest.qmd ? { qmd: manifest.qmd } : {},
7192
7659
  configFiles: manifest.configFiles,
7193
7660
  datasets: manifest.datasets,
7194
- results: manifest.results
7661
+ results: manifest.results,
7662
+ ...manifest.codexCredit ? { codexCredit: manifest.codexCredit } : {}
7195
7663
  };
7196
7664
  }
7197
7665
  async function scanDatasetFiles(root) {
@@ -7200,18 +7668,18 @@ async function scanDatasetFiles(root) {
7200
7668
  const entries = await readdir4(directory, { withFileTypes: true });
7201
7669
  entries.sort((left, right) => left.name.localeCompare(right.name));
7202
7670
  for (const entry of entries) {
7203
- const entryPath = path4.join(directory, entry.name);
7671
+ const entryPath = path5.join(directory, entry.name);
7204
7672
  const entryStat = await lstat3(entryPath);
7205
- const relativePath = path4.relative(root, entryPath).split(path4.sep).join("/");
7673
+ const relativePath = path5.relative(root, entryPath).split(path5.sep).join("/");
7206
7674
  if (entryStat.isSymbolicLink()) {
7207
7675
  const target = await readlink(entryPath);
7208
- const resolvedTarget = path4.resolve(directory, target);
7676
+ const resolvedTarget = path5.resolve(directory, target);
7209
7677
  const realTarget = await realpath3(resolvedTarget);
7210
- const targetRelativePath = path4.relative(root, realTarget);
7211
- if (targetRelativePath.length === 0 || targetRelativePath === ".." || targetRelativePath.startsWith(`..${path4.sep}`) || path4.isAbsolute(targetRelativePath)) {
7678
+ const targetRelativePath = path5.relative(root, realTarget);
7679
+ if (targetRelativePath.length === 0 || targetRelativePath === ".." || targetRelativePath.startsWith(`..${path5.sep}`) || path5.isAbsolute(targetRelativePath)) {
7212
7680
  throw new Error(`dataset symlink target must be inside ${root}: ${entryPath}`);
7213
7681
  }
7214
- const manifestTarget = path4.isAbsolute(target) ? targetRelativePath.split(path4.sep).join("/") : target;
7682
+ const manifestTarget = path5.isAbsolute(target) ? targetRelativePath.split(path5.sep).join("/") : target;
7215
7683
  files.push({
7216
7684
  path: relativePath,
7217
7685
  kind: "symlink",
@@ -7239,9 +7707,9 @@ async function scanDatasetFiles(root) {
7239
7707
  return files.sort((left, right) => left.path.localeCompare(right.path));
7240
7708
  }
7241
7709
  async function lstatPathWithoutSymlinkComponents(targetPath) {
7242
- const parsed = path4.parse(targetPath);
7243
- const relativePath = path4.relative(parsed.root, targetPath);
7244
- const parts = relativePath.length > 0 ? relativePath.split(path4.sep) : [];
7710
+ const parsed = path5.parse(targetPath);
7711
+ const relativePath = path5.relative(parsed.root, targetPath);
7712
+ const parts = relativePath.length > 0 ? relativePath.split(path5.sep) : [];
7245
7713
  let currentPath = parsed.root;
7246
7714
  let currentStat;
7247
7715
  try {
@@ -7249,7 +7717,7 @@ async function lstatPathWithoutSymlinkComponents(targetPath) {
7249
7717
  currentStat = await lstat3(currentPath);
7250
7718
  }
7251
7719
  for (const part of parts) {
7252
- currentPath = path4.join(currentPath, part);
7720
+ currentPath = path5.join(currentPath, part);
7253
7721
  currentStat = await lstat3(currentPath);
7254
7722
  if (currentStat.isSymbolicLink()) {
7255
7723
  return void 0;
@@ -7270,7 +7738,7 @@ async function buildDatasetManifest(benchmark, datasetDir) {
7270
7738
  files: []
7271
7739
  };
7272
7740
  }
7273
- const datasetRoot = path4.resolve(datasetDir);
7741
+ const datasetRoot = path5.resolve(datasetDir);
7274
7742
  const datasetStat = await lstatPathWithoutSymlinkComponents(datasetRoot);
7275
7743
  if (!datasetStat) {
7276
7744
  return {
@@ -7312,7 +7780,7 @@ async function buildResultManifest(resultsDir, resultPath, result) {
7312
7780
  await assertRegularFileWithoutSymlinkComponents(resultPath, "result path");
7313
7781
  const fileStats = await stat2(resultPath);
7314
7782
  return {
7315
- path: path4.relative(resultsDir, resultPath).split(path4.sep).join("/"),
7783
+ path: path5.relative(resultsDir, resultPath).split(path5.sep).join("/"),
7316
7784
  sha256: await sha256File(resultPath),
7317
7785
  sizeBytes: fileStats.size,
7318
7786
  resultId: result.meta.id,
@@ -7334,7 +7802,7 @@ async function resolveResultPaths(resultsDir, explicitPaths) {
7334
7802
  if (explicitPaths !== void 0) {
7335
7803
  const resolvedPaths = await Promise.all(
7336
7804
  explicitPaths.map(async (entry) => {
7337
- const resultPath = path4.resolve(entry);
7805
+ const resultPath = path5.resolve(entry);
7338
7806
  assertPathInsideRoot(resultsDir, resultPath, "result path");
7339
7807
  await assertRegularFileWithoutSymlinkComponents(resultPath, "result path");
7340
7808
  return resultPath;
@@ -7343,20 +7811,20 @@ async function resolveResultPaths(resultsDir, explicitPaths) {
7343
7811
  return [...new Set(resolvedPaths)].sort((left, right) => left.localeCompare(right));
7344
7812
  }
7345
7813
  const summaries = await listBenchmarkResults(resultsDir);
7346
- return summaries.map((summary) => path4.resolve(summary.path));
7814
+ return summaries.map((summary) => path5.resolve(summary.path));
7347
7815
  }
7348
7816
  function assertPathInsideRoot(root, targetPath, label) {
7349
- const resolvedRoot = path4.resolve(root);
7350
- const resolvedTargetPath = path4.resolve(targetPath);
7351
- const relativePath = path4.relative(resolvedRoot, resolvedTargetPath);
7352
- if (relativePath.length === 0 || relativePath === ".." || relativePath.startsWith(`..${path4.sep}`) || path4.isAbsolute(relativePath)) {
7817
+ const resolvedRoot = path5.resolve(root);
7818
+ const resolvedTargetPath = path5.resolve(targetPath);
7819
+ const relativePath = path5.relative(resolvedRoot, resolvedTargetPath);
7820
+ if (relativePath.length === 0 || relativePath === ".." || relativePath.startsWith(`..${path5.sep}`) || path5.isAbsolute(relativePath)) {
7353
7821
  throw new Error(`${label} must be inside ${resolvedRoot}: ${resolvedTargetPath}`);
7354
7822
  }
7355
7823
  }
7356
7824
  async function assertRegularFileWithoutSymlinkComponents(targetPath, label) {
7357
- const targetStat = await lstatPathWithoutSymlinkComponents(path4.resolve(targetPath));
7825
+ const targetStat = await lstatPathWithoutSymlinkComponents(path5.resolve(targetPath));
7358
7826
  if (!targetStat?.isFile()) {
7359
- throw new Error(`${label} must be a regular file without symlink components: ${path4.resolve(targetPath)}`);
7827
+ throw new Error(`${label} must be a regular file without symlink components: ${path5.resolve(targetPath)}`);
7360
7828
  }
7361
7829
  }
7362
7830
  function isKnownNonSecretOptionFlag(arg) {
@@ -7402,7 +7870,7 @@ async function buildConfigFileEntries(configFiles = []) {
7402
7870
  entries.push({ label: configFile.label, path: configFile.path, missing: true });
7403
7871
  continue;
7404
7872
  }
7405
- const content = await readFile4(configFile.path);
7873
+ const content = await readFile5(configFile.path);
7406
7874
  const sanitizedConfig = sanitizeConfigFileContent(content);
7407
7875
  entries.push({
7408
7876
  label: configFile.label,
@@ -7469,7 +7937,7 @@ function resolvePackageManager(cwd) {
7469
7937
  }
7470
7938
  }
7471
7939
  async function buildBenchmarkReproManifest(resultsDir, options = {}) {
7472
- const resolvedResultsDir = path4.resolve(resultsDir);
7940
+ const resolvedResultsDir = path5.resolve(resultsDir);
7473
7941
  const cwd = options.command?.cwd ?? process.cwd();
7474
7942
  const resultPaths = await resolveResultPaths(resolvedResultsDir, options.resultPaths);
7475
7943
  const loadedResults = await Promise.all(resultPaths.map((resultPath) => loadBenchmarkResult(resultPath)));
@@ -7487,11 +7955,23 @@ async function buildBenchmarkReproManifest(resultsDir, options = {}) {
7487
7955
  );
7488
7956
  const qmdCollections = collectQmdCollections(options.qmd?.collections, loadedResults);
7489
7957
  const pnpmVersion = resolvePackageManager(cwd);
7958
+ const commandEnv = options.command?.env ?? process.env;
7959
+ const runId = options.runId ?? resolveBenchmarkRunId(commandEnv);
7960
+ const resolvedCreditConfig = resolveCodexCreditBudgetConfig(commandEnv, runId);
7961
+ const creditConfig = resolvedCreditConfig ? { ...resolvedCreditConfig, runId } : void 0;
7962
+ let codexCredit;
7963
+ if (creditConfig) {
7964
+ try {
7965
+ codexCredit = await buildCodexCreditReceipt(creditConfig.ledgerPath, creditConfig.runId);
7966
+ } catch (error) {
7967
+ if (error.code !== "ENOENT") throw error;
7968
+ }
7969
+ }
7490
7970
  const manifestWithoutHash = {
7491
7971
  schemaVersion: BENCHMARK_REPRO_MANIFEST_SCHEMA_VERSION,
7492
7972
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
7493
7973
  run: {
7494
- id: options.runId ?? resolveBenchmarkRunId(),
7974
+ id: runId,
7495
7975
  ...options.mode ? { mode: options.mode } : {},
7496
7976
  selectedBenchmarks,
7497
7977
  runtimeProfiles: options.runtimeProfiles ?? [],
@@ -7503,13 +7983,13 @@ async function buildBenchmarkReproManifest(resultsDir, options = {}) {
7503
7983
  command: {
7504
7984
  cwd,
7505
7985
  argv: sanitizeArgv(options.command?.argv ?? process.argv.slice(2)),
7506
- envKeys: sanitizeEnvKeys(options.command?.env, options.command?.envKeys)
7986
+ envKeys: sanitizeEnvKeys(commandEnv, options.command?.envKeys)
7507
7987
  },
7508
7988
  environment: {
7509
7989
  platform: process.platform,
7510
7990
  arch: process.arch,
7511
7991
  nodeVersion: process.version,
7512
- hostname: os2.hostname(),
7992
+ hostname: os3.hostname(),
7513
7993
  ...pnpmVersion ? { packageManager: `pnpm@${pnpmVersion}` } : {}
7514
7994
  },
7515
7995
  ...options.qmd || qmdCollections.length > 0 ? {
@@ -7521,7 +8001,8 @@ async function buildBenchmarkReproManifest(resultsDir, options = {}) {
7521
8001
  } : {},
7522
8002
  configFiles: await buildConfigFileEntries(options.configFiles),
7523
8003
  datasets,
7524
- results: resultEntries.sort((left, right) => left.path.localeCompare(right.path))
8004
+ results: resultEntries.sort((left, right) => left.path.localeCompare(right.path)),
8005
+ ...codexCredit ? { codexCredit } : {}
7525
8006
  };
7526
8007
  return {
7527
8008
  ...manifestWithoutHash,
@@ -7529,18 +8010,18 @@ async function buildBenchmarkReproManifest(resultsDir, options = {}) {
7529
8010
  };
7530
8011
  }
7531
8012
  async function writeBenchmarkReproManifest(resultsDir, options = {}) {
7532
- await mkdir3(resultsDir, { recursive: true });
8013
+ await mkdir4(resultsDir, { recursive: true });
7533
8014
  const manifest = await buildBenchmarkReproManifest(resultsDir, options);
7534
- const manifestPath = path4.join(resultsDir, BENCHMARK_REPRO_MANIFEST_FILENAME);
7535
- await writeFile3(manifestPath, `${JSON.stringify(manifest, null, 2)}
8015
+ const manifestPath = path5.join(resultsDir, BENCHMARK_REPRO_MANIFEST_FILENAME);
8016
+ await writeFile4(manifestPath, `${JSON.stringify(manifest, null, 2)}
7536
8017
  `);
7537
8018
  return manifestPath;
7538
8019
  }
7539
8020
 
7540
8021
  // src/published-artifact.ts
7541
- import { createHash as createHash4 } from "crypto";
7542
- import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
7543
- import path5 from "path";
8022
+ import { createHash as createHash5 } from "crypto";
8023
+ import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
8024
+ import path6 from "path";
7544
8025
  var BENCHMARK_ARTIFACT_SCHEMA_VERSION = 1;
7545
8026
  var PUBLISHED_BENCHMARK_ARTIFACT_IDS = Object.freeze([
7546
8027
  "ama-bench",
@@ -7681,25 +8162,25 @@ function serializeBenchmarkArtifact(artifact) {
7681
8162
  `;
7682
8163
  }
7683
8164
  function hashBenchmarkArtifact(artifact) {
7684
- return createHash4("sha256").update(serializeBenchmarkArtifact(artifact)).digest("hex");
8165
+ return createHash5("sha256").update(serializeBenchmarkArtifact(artifact)).digest("hex");
7685
8166
  }
7686
8167
  async function writeBenchmarkArtifact(artifact, outputDir) {
7687
- await mkdir4(outputDir, { recursive: true });
8168
+ await mkdir5(outputDir, { recursive: true });
7688
8169
  const filename = buildBenchmarkArtifactFilename(artifact);
7689
8170
  const body = serializeBenchmarkArtifact(artifact);
7690
- const resolvedDir = path5.resolve(outputDir);
7691
- const abs = path5.resolve(resolvedDir, filename);
7692
- const relative = path5.relative(resolvedDir, abs);
7693
- if (relative.length === 0 || relative.startsWith("..") || path5.isAbsolute(relative) || relative.includes(path5.sep)) {
8171
+ const resolvedDir = path6.resolve(outputDir);
8172
+ const abs = path6.resolve(resolvedDir, filename);
8173
+ const relative = path6.relative(resolvedDir, abs);
8174
+ if (relative.length === 0 || relative.startsWith("..") || path6.isAbsolute(relative) || relative.includes(path6.sep)) {
7694
8175
  throw new Error(
7695
8176
  `writeBenchmarkArtifact: refusing to write outside outputDir (filename="${filename}", resolved="${abs}").`
7696
8177
  );
7697
8178
  }
7698
- await writeFile4(abs, body);
8179
+ await writeFile5(abs, body);
7699
8180
  return {
7700
8181
  path: abs,
7701
8182
  filename,
7702
- sha256: createHash4("sha256").update(body).digest("hex"),
8183
+ sha256: createHash5("sha256").update(body).digest("hex"),
7703
8184
  bytes: Buffer.byteLength(body, "utf8")
7704
8185
  };
7705
8186
  }
@@ -7804,11 +8285,11 @@ function parseBenchmarkArtifact(raw) {
7804
8285
  return parsed;
7805
8286
  }
7806
8287
  async function loadBenchmarkArtifact(filePath) {
7807
- const raw = await readFile5(filePath, "utf8");
8288
+ const raw = await readFile6(filePath, "utf8");
7808
8289
  const artifact = parseBenchmarkArtifact(raw);
7809
8290
  return {
7810
8291
  artifact,
7811
- sha256: createHash4("sha256").update(raw).digest("hex"),
8292
+ sha256: createHash5("sha256").update(raw).digest("hex"),
7812
8293
  bytes: Buffer.byteLength(raw, "utf8")
7813
8294
  };
7814
8295
  }
@@ -8211,8 +8692,8 @@ function createAnthropicProvider(config) {
8211
8692
  // src/providers/claude-cli.ts
8212
8693
  import { spawn } from "child_process";
8213
8694
  import { mkdtemp as mkdtemp2, rm as rm2 } from "fs/promises";
8214
- import os3 from "os";
8215
- import path6 from "path";
8695
+ import os4 from "os";
8696
+ import path7 from "path";
8216
8697
  var CLAUDE_CLI_STDIO_LIMIT = 64e3;
8217
8698
  var CLAUDE_CLI_PARENT_SIGNALS = ["SIGHUP", "SIGINT", "SIGTERM"];
8218
8699
  var CLAUDE_CLI_FORCED_PARENT_EXIT_MS = 1e3;
@@ -8365,7 +8846,7 @@ var ClaudeCliProvider = class {
8365
8846
  let transientAttempt = 1;
8366
8847
  let usageLimitAttempt = 1;
8367
8848
  while (true) {
8368
- const tempDir = await mkdtemp2(path6.join(os3.tmpdir(), "remnic-claude-cli-"));
8849
+ const tempDir = await mkdtemp2(path7.join(os4.tmpdir(), "remnic-claude-cli-"));
8369
8850
  try {
8370
8851
  const request = this.buildRunRequest(prompt, opts, tempDir);
8371
8852
  const result = await this.runClaudeCli(request);
@@ -8577,14 +9058,14 @@ function resolveClaudeCliExecutable(config) {
8577
9058
  if (trimmed.length === 0) {
8578
9059
  throw new Error(`${CLAUDE_CLI_EXECUTABLE_ENV} / claude-cli executable must not be empty`);
8579
9060
  }
8580
- return expandHomeRelativePath(trimmed);
9061
+ return expandHomeRelativePath2(trimmed);
8581
9062
  }
8582
- function expandHomeRelativePath(value) {
9063
+ function expandHomeRelativePath2(value) {
8583
9064
  if (value === "~") {
8584
- return os3.homedir();
9065
+ return os4.homedir();
8585
9066
  }
8586
9067
  if (value.startsWith("~/") || value.startsWith("~\\")) {
8587
- return path6.join(os3.homedir(), value.slice(2));
9068
+ return path7.join(os4.homedir(), value.slice(2));
8588
9069
  }
8589
9070
  return value;
8590
9071
  }
@@ -8971,7 +9452,7 @@ function createClaudeCliProvider(config, deps) {
8971
9452
 
8972
9453
  // src/providers/codex-cli.ts
8973
9454
  import { spawn as spawn2 } from "child_process";
8974
- import { createHash as createHash5, randomUUID } from "crypto";
9455
+ import { createHash as createHash6, randomUUID } from "crypto";
8975
9456
  import { mkdir as mkdir6, mkdtemp as mkdtemp3, readFile as readFile7, rm as rm3, writeFile as writeFile6 } from "fs/promises";
8976
9457
  import os5 from "os";
8977
9458
  import path8 from "path";
@@ -9165,364 +9646,6 @@ function throwJudgeFailure(provider, failure) {
9165
9646
  throw provider.createJudgeError?.(failure) ?? new StructuredJudgeError(failure);
9166
9647
  }
9167
9648
 
9168
- // src/providers/codex-credit-budget.ts
9169
- import { mkdir as mkdir5, open, readFile as readFile6, rename as rename2, rmdir, unlink as unlink3, writeFile as writeFile5 } from "fs/promises";
9170
- import os4 from "os";
9171
- import path7 from "path";
9172
- var ONE_MILLION = 1e6;
9173
- var MAX_BOUNDED_CALL_CREDITS = 300;
9174
- var SOL_MODEL = /^gpt-5\.6-sol$/i;
9175
- var CREDIT_RATES = [
9176
- [/^gpt-5\.6-sol$/i, { input: 125, cachedInput: 12.5, output: 750 }],
9177
- [/^gpt-5\.6-terra$/i, { input: 62.5, cachedInput: 6.25, output: 375 }],
9178
- [/^gpt-5\.6-luna$/i, { input: 25, cachedInput: 2.5, output: 150 }],
9179
- [/^gpt-5\.5$/i, { input: 125, cachedInput: 12.5, output: 750 }],
9180
- [/^gpt-5\.4-mini$/i, { input: 18.75, cachedInput: 1.875, output: 113 }],
9181
- [/^gpt-5\.4$/i, { input: 62.5, cachedInput: 6.25, output: 375 }],
9182
- [/^gpt-5\.3-codex$/i, { input: 43.75, cachedInput: 4.375, output: 350 }],
9183
- [/^gpt-5\.2$/i, { input: 43.75, cachedInput: 4.375, output: 350 }]
9184
- ];
9185
- var completionQueue = Promise.resolve();
9186
- var CodexCreditAccountingError = class extends Error {
9187
- constructor(message) {
9188
- super(message);
9189
- this.name = "CodexCreditAccountingError";
9190
- }
9191
- };
9192
- var CodexCreditDispatchError = class extends Error {
9193
- constructor(message, options) {
9194
- super(message, options);
9195
- this.name = "CodexCreditDispatchError";
9196
- }
9197
- };
9198
- function resolveCodexCreditBudgetConfig(env = process.env) {
9199
- const rawBudget = env.REMNIC_BENCH_CODEX_CREDIT_BUDGET?.trim();
9200
- if (!rawBudget) return void 0;
9201
- const budgetCredits = parsePositiveNumber(
9202
- rawBudget,
9203
- "REMNIC_BENCH_CODEX_CREDIT_BUDGET"
9204
- );
9205
- const reserveCredits = parseNonNegativeNumber(
9206
- env.REMNIC_BENCH_CODEX_CREDIT_RESERVE?.trim() ?? "473",
9207
- "REMNIC_BENCH_CODEX_CREDIT_RESERVE"
9208
- );
9209
- if (reserveCredits >= budgetCredits) {
9210
- throw new Error(
9211
- "REMNIC_BENCH_CODEX_CREDIT_RESERVE must be smaller than REMNIC_BENCH_CODEX_CREDIT_BUDGET"
9212
- );
9213
- }
9214
- if (reserveCredits < MAX_BOUNDED_CALL_CREDITS) {
9215
- throw new Error(
9216
- `REMNIC_BENCH_CODEX_CREDIT_RESERVE must be at least ${MAX_BOUNDED_CALL_CREDITS} credits to cover the conservative maximum cost of the one serialized in-flight call`
9217
- );
9218
- }
9219
- const ledgerPath = path7.resolve(
9220
- expandHomeRelativePath2(
9221
- env.REMNIC_BENCH_CODEX_CREDIT_LEDGER?.trim() || ".remnic/bench/codex-credit-ledger.json"
9222
- )
9223
- );
9224
- return {
9225
- budgetCredits,
9226
- reserveCredits,
9227
- ledgerPath,
9228
- allowSol: /^(?:1|true|yes|on)$/i.test(
9229
- env.REMNIC_BENCH_CODEX_ALLOW_SOL?.trim() ?? ""
9230
- )
9231
- };
9232
- }
9233
- async function runWithinCodexCreditBudget(args) {
9234
- if (!args.config) {
9235
- return (await args.run()).value;
9236
- }
9237
- const previous = completionQueue;
9238
- let release;
9239
- completionQueue = new Promise((resolve) => {
9240
- release = resolve;
9241
- });
9242
- await previous;
9243
- const lockPath = `${args.config.ledgerPath}.lock`;
9244
- let lock;
9245
- let dispatchStarted = false;
9246
- let accountingSettled = false;
9247
- try {
9248
- await mkdir5(path7.dirname(lockPath), { recursive: true, mode: 448 });
9249
- lock = await acquireLedgerLock(lockPath);
9250
- assertModelAllowed(args.model, args.config);
9251
- const ledger = await readLedger(args.config);
9252
- if (ledger.blockedReason) {
9253
- throw new Error(
9254
- `Codex credit ledger is blocked pending manual reconciliation: ${ledger.blockedReason}`
9255
- );
9256
- }
9257
- const usableCredits = args.config.budgetCredits - args.config.reserveCredits;
9258
- if (ledger.spentCredits >= usableCredits) {
9259
- throw new Error(
9260
- `Codex credit budget exhausted: ${ledger.spentCredits.toFixed(3)} spent; ${usableCredits.toFixed(3)} usable after the ${args.config.reserveCredits.toFixed(3)} safety reserve.`
9261
- );
9262
- }
9263
- await writeLockState(lock, "in-flight");
9264
- dispatchStarted = true;
9265
- let result;
9266
- try {
9267
- result = await args.run();
9268
- } catch (error) {
9269
- if (error instanceof CodexCreditDispatchError) {
9270
- await writeLockState(lock, "settled");
9271
- accountingSettled = true;
9272
- } else {
9273
- const blockedLedger = {
9274
- ...ledger,
9275
- blockedReason: error instanceof CodexCreditAccountingError ? error.message : `Codex dispatch outcome is unknown after an unexpected error: ${safeErrorMessage(error)}`
9276
- };
9277
- await writeLedger(args.config.ledgerPath, blockedLedger);
9278
- await writeLockState(lock, "settled");
9279
- accountingSettled = true;
9280
- }
9281
- throw error;
9282
- }
9283
- const credits = calculateCodexCredits(args.model, result.usage);
9284
- const nextSpent = ledger.spentCredits + credits;
9285
- const nextLedger = {
9286
- ...ledger,
9287
- spentCredits: nextSpent,
9288
- entries: [
9289
- ...ledger.entries,
9290
- {
9291
- at: (/* @__PURE__ */ new Date()).toISOString(),
9292
- model: args.model,
9293
- credits,
9294
- ...result.usage
9295
- }
9296
- ]
9297
- };
9298
- await writeLedger(args.config.ledgerPath, nextLedger);
9299
- await writeLockState(lock, "settled");
9300
- accountingSettled = true;
9301
- args.onUsagePersisted?.(result.usage);
9302
- if (nextSpent > args.config.budgetCredits) {
9303
- throw new Error(
9304
- `Codex credit budget exceeded by completed call: ${nextSpent.toFixed(3)} > ${args.config.budgetCredits.toFixed(3)} credits. Usage was persisted; stop the benchmark immediately.`
9305
- );
9306
- }
9307
- return result.value;
9308
- } finally {
9309
- try {
9310
- if (lock) {
9311
- try {
9312
- await lock.close();
9313
- } finally {
9314
- if (!dispatchStarted || accountingSettled) {
9315
- await removeOwnedLedgerLock(lockPath);
9316
- }
9317
- }
9318
- }
9319
- } finally {
9320
- release();
9321
- }
9322
- }
9323
- }
9324
- async function acquireLedgerLock(lockPath) {
9325
- for (let attempt = 0; attempt < 2; attempt += 1) {
9326
- try {
9327
- await mkdir5(lockPath, { mode: 448 });
9328
- } catch (error) {
9329
- if (error.code !== "EEXIST") throw error;
9330
- const owner = await readLockOwner(lockPath);
9331
- if (!owner || isProcessAlive(owner.pid) || owner.phase === "in-flight") {
9332
- throw new Error(
9333
- `Codex credit ledger is locked${owner?.phase === "in-flight" ? " with unreconciled in-flight usage" : " by another benchmark process"} (${lockPath}); refusing credit spend.`
9334
- );
9335
- }
9336
- await reclaimStaleLedgerLock(lockPath, owner);
9337
- continue;
9338
- }
9339
- let createdLock;
9340
- try {
9341
- await mkdir5(lockHeldPath(lockPath));
9342
- createdLock = await open(lockOwnerPath(lockPath), "wx", 384);
9343
- await writeLockState(createdLock, "preflight");
9344
- return createdLock;
9345
- } catch (error) {
9346
- await createdLock?.close().catch(() => void 0);
9347
- await unlink3(lockOwnerPath(lockPath)).catch(() => void 0);
9348
- await rmdir(lockHeldPath(lockPath)).catch(() => void 0);
9349
- await rmdir(lockPath).catch(() => void 0);
9350
- throw error;
9351
- }
9352
- }
9353
- throw new Error(`Unable to acquire Codex credit ledger lock (${lockPath})`);
9354
- }
9355
- async function readLockOwner(lockPath) {
9356
- try {
9357
- const parsed = JSON.parse(await readFile6(lockOwnerPath(lockPath), "utf8"));
9358
- if (!Number.isSafeInteger(parsed.pid) || parsed.pid <= 0 || parsed.phase !== "preflight" && parsed.phase !== "in-flight" && parsed.phase !== "settled") {
9359
- return void 0;
9360
- }
9361
- return { pid: parsed.pid, phase: parsed.phase };
9362
- } catch {
9363
- return void 0;
9364
- }
9365
- }
9366
- async function reclaimStaleLedgerLock(lockPath, expectedOwner) {
9367
- try {
9368
- await rmdir(lockHeldPath(lockPath));
9369
- } catch (error) {
9370
- throw new Error(
9371
- `Codex credit ledger stale-lock reclamation is already claimed or incomplete (${lockPath}); refusing credit spend: ${safeErrorMessage(error)}`
9372
- );
9373
- }
9374
- const currentOwner = await readLockOwner(lockPath);
9375
- if (!currentOwner || currentOwner.pid !== expectedOwner.pid || currentOwner.phase !== expectedOwner.phase || isProcessAlive(currentOwner.pid) || currentOwner.phase === "in-flight") {
9376
- throw new Error(
9377
- `Codex credit ledger owner changed during stale-lock reclamation (${lockPath}); refusing credit spend.`
9378
- );
9379
- }
9380
- await unlink3(lockOwnerPath(lockPath));
9381
- await rmdir(lockPath);
9382
- }
9383
- async function removeOwnedLedgerLock(lockPath) {
9384
- await rmdir(lockHeldPath(lockPath));
9385
- await unlink3(lockOwnerPath(lockPath));
9386
- await rmdir(lockPath);
9387
- }
9388
- function lockOwnerPath(lockPath) {
9389
- return path7.join(lockPath, "owner.json");
9390
- }
9391
- function lockHeldPath(lockPath) {
9392
- return path7.join(lockPath, "held");
9393
- }
9394
- async function writeLockState(lock, phase) {
9395
- const contents = `${JSON.stringify({
9396
- pid: process.pid,
9397
- phase,
9398
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
9399
- })}
9400
- `;
9401
- await lock.truncate(0);
9402
- await lock.write(contents, 0, "utf8");
9403
- await lock.sync();
9404
- }
9405
- function isProcessAlive(pid) {
9406
- try {
9407
- process.kill(pid, 0);
9408
- return true;
9409
- } catch (error) {
9410
- return error.code === "EPERM";
9411
- }
9412
- }
9413
- function parseCodexJsonlUsage(output) {
9414
- let usage;
9415
- for (const line of output.split(/\r?\n/)) {
9416
- const trimmed = line.trim();
9417
- if (!trimmed.startsWith("{")) continue;
9418
- try {
9419
- const event = JSON.parse(trimmed);
9420
- if (event.type !== "turn.completed" || !event.usage) continue;
9421
- const inputTokens = readCounter(event.usage.input_tokens);
9422
- const outputTokens = readCounter(event.usage.output_tokens);
9423
- const cachedInputTokens = readOptionalCounter(
9424
- event.usage.cached_input_tokens
9425
- );
9426
- const reasoningOutputTokens = readOptionalCounter(
9427
- event.usage.reasoning_output_tokens
9428
- );
9429
- if (inputTokens !== void 0 && outputTokens !== void 0 && cachedInputTokens !== void 0 && reasoningOutputTokens !== void 0) {
9430
- usage = {
9431
- inputTokens,
9432
- cachedInputTokens,
9433
- outputTokens,
9434
- reasoningOutputTokens
9435
- };
9436
- }
9437
- } catch {
9438
- }
9439
- }
9440
- return usage;
9441
- }
9442
- function calculateCodexCredits(model, usage) {
9443
- const rate = resolveRate(model);
9444
- const cached = Math.min(usage.inputTokens, usage.cachedInputTokens);
9445
- const uncached = usage.inputTokens - cached;
9446
- return (uncached * rate.input + cached * rate.cachedInput + usage.outputTokens * rate.output) / ONE_MILLION;
9447
- }
9448
- function resolveRate(model) {
9449
- const match = CREDIT_RATES.find(([pattern]) => pattern.test(model));
9450
- if (!match) {
9451
- throw new Error(
9452
- `No Codex credit rate is configured for model ${JSON.stringify(model)}; refusing to run under a bounded credit budget.`
9453
- );
9454
- }
9455
- return match[1];
9456
- }
9457
- function assertModelAllowed(model, config) {
9458
- resolveRate(model);
9459
- if (SOL_MODEL.test(model) && !config.allowSol) {
9460
- throw new Error(
9461
- "gpt-5.6-sol is disabled for bounded benchmark runs because it is the most expensive GPT-5.6 tier. Use gpt-5.6-terra or gpt-5.6-luna, or explicitly set REMNIC_BENCH_CODEX_ALLOW_SOL=1."
9462
- );
9463
- }
9464
- }
9465
- async function readLedger(config) {
9466
- try {
9467
- const parsed = JSON.parse(await readFile6(config.ledgerPath, "utf8"));
9468
- if (parsed.schemaVersion !== 1 || parsed.budgetCredits !== config.budgetCredits || parsed.reserveCredits !== config.reserveCredits || typeof parsed.spentCredits !== "number" || !Number.isFinite(parsed.spentCredits) || parsed.spentCredits < 0 || !Array.isArray(parsed.entries)) {
9469
- throw new Error("ledger schema or budget does not match this run");
9470
- }
9471
- return parsed;
9472
- } catch (error) {
9473
- if (error.code !== "ENOENT") {
9474
- throw new Error(`Invalid Codex credit ledger at ${config.ledgerPath}: ${String(error)}`);
9475
- }
9476
- return {
9477
- schemaVersion: 1,
9478
- budgetCredits: config.budgetCredits,
9479
- reserveCredits: config.reserveCredits,
9480
- spentCredits: 0,
9481
- entries: []
9482
- };
9483
- }
9484
- }
9485
- async function writeLedger(filePath, ledger) {
9486
- await mkdir5(path7.dirname(filePath), { recursive: true, mode: 448 });
9487
- const tempPath = `${filePath}.${process.pid}.tmp`;
9488
- await writeFile5(tempPath, `${JSON.stringify(ledger, null, 2)}
9489
- `, {
9490
- encoding: "utf8",
9491
- mode: 384
9492
- });
9493
- await rename2(tempPath, filePath);
9494
- }
9495
- function readCounter(value) {
9496
- return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
9497
- }
9498
- function readOptionalCounter(value) {
9499
- return value === void 0 ? 0 : readCounter(value);
9500
- }
9501
- function safeErrorMessage(error) {
9502
- return error instanceof Error ? error.message : String(error);
9503
- }
9504
- function expandHomeRelativePath2(value) {
9505
- if (value === "~") return os4.homedir();
9506
- if (value.startsWith("~/") || value.startsWith("~\\")) {
9507
- return path7.join(os4.homedir(), value.slice(2));
9508
- }
9509
- return value;
9510
- }
9511
- function parsePositiveNumber(value, name) {
9512
- const parsed = Number(value);
9513
- if (!Number.isFinite(parsed) || parsed <= 0) {
9514
- throw new Error(`${name} must be a finite number greater than zero`);
9515
- }
9516
- return parsed;
9517
- }
9518
- function parseNonNegativeNumber(value, name) {
9519
- const parsed = Number(value);
9520
- if (!Number.isFinite(parsed) || parsed < 0) {
9521
- throw new Error(`${name} must be a finite non-negative number`);
9522
- }
9523
- return parsed;
9524
- }
9525
-
9526
9649
  // src/providers/codex-cli.ts
9527
9650
  var DEFAULT_REASONING_EFFORT = "xhigh";
9528
9651
  var DEFAULT_SERVICE_TIER = "default";
@@ -9611,7 +9734,10 @@ var CodexCliProvider = class {
9611
9734
  throw codexCliAbortError(opts.signal);
9612
9735
  }
9613
9736
  const startedAt = performance.now();
9614
- const creditBudget = resolveCodexCreditBudgetConfig();
9737
+ const creditBudget = resolveCodexCreditBudgetConfig(
9738
+ process.env,
9739
+ resolveBenchmarkRunId()
9740
+ );
9615
9741
  if (creditBudget) {
9616
9742
  await this.assertChatGptCreditAuth();
9617
9743
  }
@@ -10194,7 +10320,7 @@ function resolveCodexCliDiagnosticsMode(config) {
10194
10320
  }
10195
10321
  function inspectCodexCompletionPrompt(prompt) {
10196
10322
  const stats = {
10197
- sha256: createHash5("sha256").update(prompt).digest("hex"),
10323
+ sha256: createHash6("sha256").update(prompt).digest("hex"),
10198
10324
  chars: prompt.length,
10199
10325
  lines: prompt.length === 0 ? 0 : prompt.split("\n").length
10200
10326
  };
@@ -14427,6 +14553,8 @@ function resolveOpenClawRemnicPluginEntry(raw) {
14427
14553
  }
14428
14554
  var REDACTED_CONFIG_VALUE = "[redacted]";
14429
14555
  var INTERNAL_GATEWAY_AGENT_ID = "remnic-bench-internal";
14556
+ var DEFAULT_CODEX_CLI_REQUEST_TIMEOUT_MS = 18e4;
14557
+ var DEFAULT_CODEX_CLI_DRAIN_TIMEOUT_MS = 6e5;
14430
14558
  var codexCliFallbackRegistered = false;
14431
14559
  var codexCliFallbackChain = Promise.resolve();
14432
14560
  async function resolveBenchRuntimeProfile(options) {
@@ -14480,8 +14608,11 @@ async function resolveBenchRuntimeProfile(options) {
14480
14608
  { disableThinking: options.internalDisableThinking === true }
14481
14609
  );
14482
14610
  const lcmObserveConcurrencyOverrides = buildLcmObserveConcurrencyOverrides(options.lcmObserveConcurrency);
14611
+ const usesImplicitCodexRequestTimeout = options.requestTimeout === void 0 && [systemProvider, judgeProvider, internalProvider].some(
14612
+ (config) => config?.provider === "codex-cli"
14613
+ );
14483
14614
  const drainTimeoutMs = normalizeDrainTimeoutMs2(
14484
- options.drainTimeout ?? options.requestTimeout
14615
+ options.drainTimeout ?? options.requestTimeout ?? (usesImplicitCodexRequestTimeout ? DEFAULT_CODEX_CLI_DRAIN_TIMEOUT_MS : void 0)
14485
14616
  );
14486
14617
  registerCodexCliFallbackRunnerIfNeeded(internalProvider);
14487
14618
  const responderFactoryConfig = systemProvider ? asProviderFactoryConfig(systemProvider) : void 0;
@@ -14693,6 +14824,7 @@ function resolveProviderConfig(kind, provider, model, baseUrl, requestTimeout, d
14693
14824
  `${kind} Codex reasoning effort requires provider "codex-cli"`
14694
14825
  );
14695
14826
  }
14827
+ const providerRequestTimeoutMs = requestTimeout === void 0 && provider === "codex-cli" ? DEFAULT_CODEX_CLI_REQUEST_TIMEOUT_MS : void 0;
14696
14828
  return {
14697
14829
  provider,
14698
14830
  model: resolvedModel.trim(),
@@ -14703,6 +14835,7 @@ function resolveProviderConfig(kind, provider, model, baseUrl, requestTimeout, d
14703
14835
  ...requestTimeout != null ? { timeoutMs: requestTimeout } : {},
14704
14836
  ...max429WaitMs != null ? { max429WaitMs } : {}
14705
14837
  } } : {},
14838
+ ...providerRequestTimeoutMs !== void 0 ? { providerRequestTimeoutMs } : {},
14706
14839
  ...disableThinking ? { disableThinking: true } : {},
14707
14840
  ...provider === "codex-cli" ? { reasoningEffort: reasoningEffort ?? "xhigh" } : {},
14708
14841
  ...responderContextBudgetChars !== void 0 ? { responderContextBudgetChars } : {},
@@ -14758,13 +14891,14 @@ function buildInternalRemnicConfigOverrides(config, options) {
14758
14891
  ...config.retryOptions?.timeoutMs ? { localLlmTimeoutMs: config.retryOptions.timeoutMs } : {}
14759
14892
  };
14760
14893
  }
14894
+ const providerTimeoutMs = config.retryOptions?.timeoutMs ?? config.providerRequestTimeoutMs;
14761
14895
  return {
14762
14896
  ...thinkingOverrides,
14763
14897
  modelSource: "gateway",
14764
14898
  localLlmEnabled: false,
14765
- ...config.retryOptions?.timeoutMs ? {
14766
- localLlmTimeoutMs: config.retryOptions.timeoutMs,
14767
- localLlmFastTimeoutMs: config.retryOptions.timeoutMs
14899
+ ...providerTimeoutMs ? {
14900
+ localLlmTimeoutMs: providerTimeoutMs,
14901
+ localLlmFastTimeoutMs: providerTimeoutMs
14768
14902
  } : {},
14769
14903
  gatewayConfig: buildInternalGatewayConfig(config, options),
14770
14904
  gatewayAgentId: INTERNAL_GATEWAY_AGENT_ID,
@@ -14774,7 +14908,7 @@ function buildInternalRemnicConfigOverrides(config, options) {
14774
14908
  function buildInternalGatewayConfig(config, options) {
14775
14909
  const providerId = INTERNAL_GATEWAY_AGENT_ID;
14776
14910
  const modelRef = `${providerId}/${config.model}`;
14777
- const timeoutMs = config.retryOptions?.timeoutMs;
14911
+ const timeoutMs = config.retryOptions?.timeoutMs ?? config.providerRequestTimeoutMs;
14778
14912
  return {
14779
14913
  agents: {
14780
14914
  defaults: {
@@ -14960,12 +15094,16 @@ function createAssistantAgentFromResponder2(responder) {
14960
15094
  };
14961
15095
  }
14962
15096
  function asProviderFactoryConfig(config) {
15097
+ const retryOptions = config.retryOptions || config.providerRequestTimeoutMs !== void 0 ? {
15098
+ ...config.retryOptions,
15099
+ ...config.retryOptions?.timeoutMs === void 0 && config.providerRequestTimeoutMs !== void 0 ? { timeoutMs: config.providerRequestTimeoutMs } : {}
15100
+ } : void 0;
14963
15101
  return {
14964
15102
  provider: config.provider,
14965
15103
  model: config.model,
14966
15104
  ...config.baseUrl ? { baseUrl: config.baseUrl } : {},
14967
15105
  ...config.apiKey ? { apiKey: config.apiKey } : {},
14968
- ...config.retryOptions ? { retryOptions: config.retryOptions } : {},
15106
+ ...retryOptions ? { retryOptions } : {},
14969
15107
  ...config.disableThinking ? { disableThinking: config.disableThinking } : {},
14970
15108
  ...config.reasoningEffort ? { reasoningEffort: config.reasoningEffort } : {},
14971
15109
  ...config.temperature !== void 0 ? { temperature: config.temperature } : {},
@@ -15061,11 +15199,11 @@ async function resolveLocalLabRuntimeProfile(options) {
15061
15199
  // src/benchmark.ts
15062
15200
  import fs2 from "fs";
15063
15201
  import path35 from "path";
15064
- import { createHash as createHash11 } from "crypto";
15202
+ import { createHash as createHash12 } from "crypto";
15065
15203
  import { expandTildePath as expandTildePath3 } from "@remnic/core";
15066
15204
 
15067
15205
  // src/judges/judge-cache.ts
15068
- import { createHash as createHash6, randomBytes as randomBytes2 } from "crypto";
15206
+ import { createHash as createHash7, randomBytes as randomBytes2 } from "crypto";
15069
15207
  import {
15070
15208
  mkdir as mkdir9,
15071
15209
  readFile as readFile11,
@@ -15108,8 +15246,8 @@ var JudgeCache = class {
15108
15246
  }
15109
15247
  /** Compute the sha256-hex key for a set of parts. Pure, sync, side-effect-free. */
15110
15248
  computeKey(parts) {
15111
- const fieldDigest = (value) => createHash6("sha256").update(value).digest();
15112
- return createHash6("sha256").update(fieldDigest(parts.benchmarkId)).update(fieldDigest(parts.datasetVersion)).update(fieldDigest(parts.questionId)).update(fieldDigest(parts.answerText)).update(fieldDigest(parts.judgePromptHash)).update(fieldDigest(parts.judgeModelId)).update(fieldDigest(parts.judgeParamsHash)).digest("hex");
15249
+ const fieldDigest = (value) => createHash7("sha256").update(value).digest();
15250
+ return createHash7("sha256").update(fieldDigest(parts.benchmarkId)).update(fieldDigest(parts.datasetVersion)).update(fieldDigest(parts.questionId)).update(fieldDigest(parts.answerText)).update(fieldDigest(parts.judgePromptHash)).update(fieldDigest(parts.judgeModelId)).update(fieldDigest(parts.judgeParamsHash)).digest("hex");
15113
15251
  }
15114
15252
  /**
15115
15253
  * Read a previously-stored verdict. Returns `undefined` on miss, corrupted
@@ -15304,7 +15442,7 @@ function runJudgeWithCache(options) {
15304
15442
  // Binary prompts are content-sensitive: two distinct prompts of
15305
15443
  // the same character length would collide on the previous
15306
15444
  // `binary:N` key, so key on a sha256 prefix of the prompt body.
15307
- questionId: `binary:${createHash6("sha256").update(prompt).digest("hex").slice(0, 16)}`,
15445
+ questionId: `binary:${createHash7("sha256").update(prompt).digest("hex").slice(0, 16)}`,
15308
15446
  answerText: prompt,
15309
15447
  judgePromptHash: keyExtras.judgePromptHash ?? "unknown-prompt",
15310
15448
  judgeModelId: keyExtras.judgeModelId ?? "unknown-judge",
@@ -22795,7 +22933,7 @@ var StructuredLiteralParser = class {
22795
22933
  };
22796
22934
 
22797
22935
  // src/benchmarks/published/personamem/runner.ts
22798
- import { createHash as createHash7, randomUUID as randomUUID7 } from "crypto";
22936
+ import { createHash as createHash8, randomUUID as randomUUID7 } from "crypto";
22799
22937
  import { readFile as readFile16, realpath as realpath4 } from "fs/promises";
22800
22938
  import path19 from "path";
22801
22939
 
@@ -23400,7 +23538,7 @@ function buildMcqPrompt(sample, seed) {
23400
23538
  function deterministicShuffle(values, seedMaterial) {
23401
23539
  return values.map((value, index) => ({
23402
23540
  value,
23403
- key: createHash7("sha256").update(`${seedMaterial}:${index}:${value}`).digest("hex"),
23541
+ key: createHash8("sha256").update(`${seedMaterial}:${index}:${value}`).digest("hex"),
23404
23542
  index
23405
23543
  })).sort((left, right) => {
23406
23544
  const byKey = left.key.localeCompare(right.key);
@@ -31859,7 +31997,7 @@ function pairedDeltaConfidenceInterval(candidateValues, baselineValues, options
31859
31997
  }
31860
31998
 
31861
31999
  // src/judges/sealed-rubric.ts
31862
- import { createHash as createHash8 } from "crypto";
32000
+ import { createHash as createHash9 } from "crypto";
31863
32001
  import { appendFileSync, mkdirSync } from "fs";
31864
32002
  import path31 from "path";
31865
32003
 
@@ -31968,9 +32106,9 @@ function loadSealedRubric(id = DEFAULT_ASSISTANT_RUBRIC_ID, options = {}) {
31968
32106
  if (typeof prompt !== "string" || prompt.length === 0) {
31969
32107
  throw new Error(`sealed rubric not found in registry: ${id}`);
31970
32108
  }
31971
- const sha256 = createHash8("sha256").update(prompt, "utf8").digest("hex");
32109
+ const sha2562 = createHash9("sha256").update(prompt, "utf8").digest("hex");
31972
32110
  const version = parseVersionFromId(id);
31973
- return { id, version, prompt, sha256 };
32111
+ return { id, version, prompt, sha256: sha2562 };
31974
32112
  }
31975
32113
  function verifyRubricDigest(expectedSha256, options = {}) {
31976
32114
  const rubric = loadSealedRubric(options.id, { registry: options.registry });
@@ -34171,7 +34309,7 @@ async function runRetentionAgedDatasetBenchmark(options) {
34171
34309
  import { randomUUID as randomUUID31 } from "crypto";
34172
34310
 
34173
34311
  // src/benchmarks/remnic/memcorrect/generator.ts
34174
- import { createHash as createHash9 } from "crypto";
34312
+ import { createHash as createHash10 } from "crypto";
34175
34313
 
34176
34314
  // src/benchmarks/remnic/memcorrect/token-pools.ts
34177
34315
  var PERSONAS = [
@@ -34495,7 +34633,7 @@ function corpusHash(corpus) {
34495
34633
  uptakeLatencyCap: corpus.options.uptakeLatencyCap,
34496
34634
  scenarios: corpus.scenarios
34497
34635
  });
34498
- return createHash9("sha256").update(canonical).digest("hex");
34636
+ return createHash10("sha256").update(canonical).digest("hex");
34499
34637
  }
34500
34638
 
34501
34639
  // src/benchmarks/remnic/memcorrect/schema.ts
@@ -35450,7 +35588,7 @@ import { mkdir as mkdir17, writeFile as writeFile16 } from "fs/promises";
35450
35588
  import path34 from "path";
35451
35589
 
35452
35590
  // src/benchmarks/remnic/bounded-memory-contracts/fixture.ts
35453
- import { createHash as createHash10 } from "crypto";
35591
+ import { createHash as createHash11 } from "crypto";
35454
35592
  var SCOPE_ACME = "project:acme";
35455
35593
  var SCOPE_BETA = "project:beta";
35456
35594
  var SCOPE_ALICE = "user:alice";
@@ -35933,7 +36071,7 @@ var BOUNDED_MEMORY_SMOKE_FIXTURE = [
35933
36071
  function fixtureHash(tasks) {
35934
36072
  const source = tasks ?? BOUNDED_MEMORY_FIXTURE;
35935
36073
  const payload = JSON.stringify(source);
35936
- return createHash10("sha256").update(payload, "utf8").digest("hex");
36074
+ return createHash11("sha256").update(payload, "utf8").digest("hex");
35937
36075
  }
35938
36076
 
35939
36077
  // src/benchmarks/remnic/bounded-memory-contracts/agent.ts
@@ -37193,13 +37331,13 @@ function wrapJudgeWithCache(args) {
37193
37331
  // differentiator is part of the prompt hash. Bumping
37194
37332
  // JUDGE_CACHE_PROTOCOL_VERSION invalidates verdicts when judge
37195
37333
  // prompt/parse semantics change (PR #1591, High).
37196
- judgePromptHash: createHash11("sha256").update(JUDGE_CACHE_PROTOCOL_VERSION).update("").update(args.amaBenchJudgeProtocol).update("").update(args.role).digest("hex"),
37334
+ judgePromptHash: createHash12("sha256").update(JUDGE_CACHE_PROTOCOL_VERSION).update("").update(args.amaBenchJudgeProtocol).update("").update(args.role).digest("hex"),
37197
37335
  judgeModelId: args.provider?.model !== void 0 && args.provider.model.length > 0 ? `${args.provider.model}${crossJudgeIdSuffix}` : `unknown-${args.role}-judge`,
37198
37336
  // Full judge configuration, deterministically serialized (sorted
37199
37337
  // keys) so provider/base-url/retry changes produce fresh cache
37200
37338
  // keys. `role` is included so primary and cross judges never
37201
37339
  // share a paramsHash.
37202
- judgeParamsHash: createHash11("sha256").update(
37340
+ judgeParamsHash: createHash12("sha256").update(
37203
37341
  stableStringify2({
37204
37342
  role: args.role,
37205
37343
  provider: args.provider
@@ -37904,6 +38042,523 @@ function formatSignedScore(value) {
37904
38042
  return `${value >= 0 ? "+" : ""}${formatScore(value)}`;
37905
38043
  }
37906
38044
 
38045
+ // src/stats/locomo-recall-delta.ts
38046
+ import { createHash as createHash13 } from "crypto";
38047
+ import { basename } from "path";
38048
+ var LOCOMO_FULL_TASK_COUNT = 1986;
38049
+ var LOCOMO_RECALL_EXCERPT_CHARS = 240;
38050
+ var LOCOMO_RECALL_DIFF_LINE_LIMIT = 20;
38051
+ var LOCOMO_CATEGORY_ORDER2 = ["single_hop", "multi_hop", "temporal", "open_domain", "adversarial"];
38052
+ var LOCOMO_TASK_CATEGORY_PATTERN2 = /-(single_hop|multi_hop|temporal|open_domain|adversarial)$/;
38053
+ var SOURCE_TURN_PATTERN = /^\[([^,\]\s]+),\s*turn\s+(\d+),\s*([^,\]]+?)(?:,\s*score\s+[^\]]+)?\]/i;
38054
+ var SHA256_PATTERN = /^[a-f0-9]{64}$/;
38055
+ function sanitizeLoComoResultReference(path40) {
38056
+ const reference = basename(path40).replace(/[\u0000-\u001f\u007f`]/g, "_");
38057
+ if (!reference) throw new Error("Result path must identify a file.");
38058
+ return reference;
38059
+ }
38060
+ function diagnoseLoComoRecallDelta(options) {
38061
+ const primaryMetric2 = options.primaryMetric ?? "llm_judge";
38062
+ const maxRegressions = parseNonNegativeInteger(options.maxRegressions ?? 20, "maxRegressions");
38063
+ assertEvidenceEnvelope(options.baseline, "baseline");
38064
+ assertEvidenceEnvelope(options.real, "real");
38065
+ assertCompleteResult(options.baseline.result, "baseline");
38066
+ assertCompleteResult(options.real.result, "real");
38067
+ assertComparableResults(options.baseline.result, options.real.result);
38068
+ const joined = joinTasks2(options.baseline.result, options.real.result);
38069
+ assertMetricSets(joined, primaryMetric2);
38070
+ verifyAggregateMeans(options.baseline.result, joined, "baseline");
38071
+ verifyAggregateMeans(options.real.result, joined, "real");
38072
+ const overall = summarizeMetric(joined, primaryMetric2);
38073
+ const categories = [...new Set(joined.map((task) => task.category))].sort(compareLoComoCategories2).map((category) => {
38074
+ const tasks = joined.filter((task) => task.category === category);
38075
+ return {
38076
+ category,
38077
+ taskCount: tasks.length,
38078
+ ...summarizeMetric(tasks, primaryMetric2)
38079
+ };
38080
+ });
38081
+ const topRegressions = joined.map((task) => buildRegression(task, primaryMetric2, LOCOMO_RECALL_EXCERPT_CHARS, LOCOMO_RECALL_DIFF_LINE_LIMIT)).filter((task) => task.delta < 0).sort((left, right) => left.delta - right.delta || compareStrings(left.taskId, right.taskId)).slice(0, maxRegressions);
38082
+ return {
38083
+ schemaVersion: 1,
38084
+ benchmarkId: "locomo",
38085
+ comparison: {
38086
+ baseline: buildProvenance(options.baseline, "baseline", joined, "baseline"),
38087
+ real: buildProvenance(options.real, "real", joined, "real")
38088
+ },
38089
+ taskCount: joined.length,
38090
+ primaryMetric: primaryMetric2,
38091
+ overall,
38092
+ categories,
38093
+ topRegressions,
38094
+ evidenceBoundary: {
38095
+ finalContextComparison: "complete",
38096
+ retrievalTierAttribution: "unavailable-in-cached-results",
38097
+ hiddenEvidenceUsed: false,
38098
+ explanation: "Cached BenchmarkResult files preserve the final transformed recall context, but not pre-transform candidates, section provenance, filter traces, or served-by tiers."
38099
+ }
38100
+ };
38101
+ }
38102
+ function renderLoComoRecallDeltaMarkdown(report) {
38103
+ const lines = [
38104
+ "# LoCoMo paired final-context diagnosis",
38105
+ "",
38106
+ `Joined ${report.taskCount} complete paired tasks. The primary metric is \`${report.primaryMetric}\` (real minus baseline).`,
38107
+ "",
38108
+ "| Category | Tasks | Baseline | Real | Delta | Wins | Losses | Ties |",
38109
+ "|---|---:|---:|---:|---:|---:|---:|---:|"
38110
+ ];
38111
+ for (const category of report.categories) {
38112
+ lines.push(
38113
+ `| ${escapeMarkdownCell(category.category)} | ${category.taskCount} | ${formatScore2(category.baselineMean)} | ${formatScore2(category.realMean)} | ${formatSignedScore2(category.delta)} | ${category.wins} | ${category.losses} | ${category.ties} |`
38114
+ );
38115
+ }
38116
+ lines.push(
38117
+ `| **Overall** | **${report.taskCount}** | **${formatScore2(report.overall.baselineMean)}** | **${formatScore2(report.overall.realMean)}** | **${formatSignedScore2(report.overall.delta)}** | **${report.overall.wins}** | **${report.overall.losses}** | **${report.overall.ties}** |`,
38118
+ "",
38119
+ "## Highest-priority final-context regressions",
38120
+ ""
38121
+ );
38122
+ for (const task of report.topRegressions) {
38123
+ lines.push(
38124
+ `### ${escapeMarkdownCell(task.taskId)}`,
38125
+ "",
38126
+ `Category: \`${task.category}\`; baseline ${formatScore2(task.baselineScore)}, real ${formatScore2(task.realScore)}, delta ${formatSignedScore2(task.delta)}.`,
38127
+ "",
38128
+ `Recall: baseline ${task.baseline.recall.charCount} chars (expected-token coverage ${formatScore2(task.baseline.recall.expectedTokenCoverage)}), real ${task.real.recall.charCount} chars (coverage ${formatScore2(task.real.recall.expectedTokenCoverage)}).`,
38129
+ "",
38130
+ `Displaced lines: ${task.displacedLines.totalCount}; introduced lines: ${task.introducedLines.totalCount}.`,
38131
+ ""
38132
+ );
38133
+ const displaced = task.displacedLines.lines[0];
38134
+ if (displaced) {
38135
+ lines.push(
38136
+ `- Baseline-only evidence: ${escapeMarkdownCell(displaced.excerpt)} (sha256 \`${displaced.sha256}\`)`
38137
+ );
38138
+ }
38139
+ const introduced = task.introducedLines.lines[0];
38140
+ if (introduced) {
38141
+ lines.push(
38142
+ `- Real-only evidence: ${escapeMarkdownCell(introduced.excerpt)} (sha256 \`${introduced.sha256}\`)`
38143
+ );
38144
+ }
38145
+ if (displaced || introduced) lines.push("");
38146
+ }
38147
+ lines.push(
38148
+ "## Evidence boundary",
38149
+ "",
38150
+ "The final responder contexts are compared completely by hash, length, headings, source references, and bounded line-difference receipts. Retrieval-tier attribution is unavailable because the cached results do not preserve served-by or candidate traces. Hidden `details.evidence` metadata is not read or emitted.",
38151
+ "",
38152
+ `Baseline: \`${report.comparison.baseline.reference}\` (sha256 \`${report.comparison.baseline.sha256}\`)`,
38153
+ "",
38154
+ `Real: \`${report.comparison.real.reference}\` (sha256 \`${report.comparison.real.sha256}\`)`,
38155
+ ""
38156
+ );
38157
+ return `${lines.join("\n")}
38158
+ `;
38159
+ }
38160
+ function assertEvidenceEnvelope(evidence, label) {
38161
+ if (!evidence.reference.trim()) {
38162
+ throw new Error(`${label} result reference must not be empty.`);
38163
+ }
38164
+ if (!SHA256_PATTERN.test(evidence.sha256)) {
38165
+ throw new Error(`${label} result sha256 must be 64 lowercase hexadecimal characters.`);
38166
+ }
38167
+ }
38168
+ function assertCompleteResult(result, label) {
38169
+ if (result.meta.benchmark !== "locomo") {
38170
+ throw new Error(`${label} result must be a locomo benchmark result.`);
38171
+ }
38172
+ if (result.meta.mode !== "full" || result.meta.status === "partial") {
38173
+ throw new Error(`${label} result must be a complete full-mode run.`);
38174
+ }
38175
+ if (!result.config.systemProvider || !result.config.judgeProvider) {
38176
+ throw new Error(`${label} result must identify both system and judge providers.`);
38177
+ }
38178
+ const limit = result.config.benchmarkOptions?.limit;
38179
+ const trialLimit = result.config.benchmarkOptions?.trialLimit;
38180
+ if (limit !== void 0 || trialLimit !== void 0) {
38181
+ throw new Error(`${label} result is limited and cannot be used as complete evidence.`);
38182
+ }
38183
+ if (result.results.tasks.length !== LOCOMO_FULL_TASK_COUNT) {
38184
+ throw new Error(
38185
+ `${label} result must contain exactly ${LOCOMO_FULL_TASK_COUNT} tasks; got ${result.results.tasks.length}.`
38186
+ );
38187
+ }
38188
+ for (const task of result.results.tasks) {
38189
+ const details = asRecord(task.details);
38190
+ const failure = details?.benchmarkFailure;
38191
+ const legacyError = details?.error;
38192
+ if (failure !== void 0 && failure !== null || typeof legacyError === "string" && legacyError.length > 0) {
38193
+ throw new Error(`${label} result contains failed task ${JSON.stringify(task.taskId)}.`);
38194
+ }
38195
+ }
38196
+ }
38197
+ function assertComparableResults(baseline, real) {
38198
+ if (baseline.config.runtimeProfile !== "baseline") {
38199
+ throw new Error('baseline result runtimeProfile must be "baseline".');
38200
+ }
38201
+ if (real.config.runtimeProfile !== "real") {
38202
+ throw new Error('real result runtimeProfile must be "real".');
38203
+ }
38204
+ const checks = [
38205
+ ["meta.version", baseline.meta.version, real.meta.version],
38206
+ ["meta.remnicVersion", baseline.meta.remnicVersion, real.meta.remnicVersion],
38207
+ ["meta.gitSha", baseline.meta.gitSha, real.meta.gitSha],
38208
+ ["meta.runCount", baseline.meta.runCount, real.meta.runCount],
38209
+ ["meta.seeds", baseline.meta.seeds, real.meta.seeds],
38210
+ ["meta.datasetHash", baseline.meta.datasetHash ?? null, real.meta.datasetHash ?? null],
38211
+ ["config.adapterMode", baseline.config.adapterMode, real.config.adapterMode],
38212
+ [
38213
+ "config.systemProvider",
38214
+ providerIdentity(baseline.config.systemProvider),
38215
+ providerIdentity(real.config.systemProvider)
38216
+ ],
38217
+ [
38218
+ "config.judgeProvider",
38219
+ providerIdentity(baseline.config.judgeProvider),
38220
+ providerIdentity(real.config.judgeProvider)
38221
+ ],
38222
+ [
38223
+ "config.internalProvider",
38224
+ providerIdentity(baseline.config.internalProvider),
38225
+ providerIdentity(real.config.internalProvider)
38226
+ ]
38227
+ ];
38228
+ for (const [field, baselineValue, realValue] of checks) {
38229
+ if (stableJson(baselineValue) !== stableJson(realValue)) {
38230
+ throw new Error(
38231
+ `Results are not comparable: ${field} differs (${stableJson(baselineValue)} vs ${stableJson(realValue)}).`
38232
+ );
38233
+ }
38234
+ }
38235
+ }
38236
+ function joinTasks2(baseline, real) {
38237
+ const baselineTasks = indexTasks2(baseline.results.tasks, "baseline");
38238
+ const realTasks = indexTasks2(real.results.tasks, "real");
38239
+ const missingFromReal = [...baselineTasks.keys()].filter((id) => !realTasks.has(id)).sort(compareStrings);
38240
+ const missingFromBaseline = [...realTasks.keys()].filter((id) => !baselineTasks.has(id)).sort(compareStrings);
38241
+ if (missingFromReal.length > 0 || missingFromBaseline.length > 0) {
38242
+ throw new Error(
38243
+ `Results do not contain identical task-id sets: ${missingFromReal.length} missing from real, ${missingFromBaseline.length} missing from baseline.`
38244
+ );
38245
+ }
38246
+ return [...baselineTasks.keys()].sort(compareStrings).map((taskId) => {
38247
+ const baselineTask = baselineTasks.get(taskId);
38248
+ const realTask = realTasks.get(taskId);
38249
+ if (!baselineTask || !realTask) {
38250
+ throw new Error(`Task ${JSON.stringify(taskId)} disappeared during the validated join.`);
38251
+ }
38252
+ for (const [field, baselineValue, realValue] of [
38253
+ ["question", baselineTask.question, realTask.question],
38254
+ ["expected", baselineTask.expected, realTask.expected]
38255
+ ]) {
38256
+ if (baselineValue !== realValue) {
38257
+ throw new Error(`Task ${JSON.stringify(taskId)} has mismatched ${field} payloads.`);
38258
+ }
38259
+ }
38260
+ const baselineCategory = resolveCategory2(baselineTask);
38261
+ const realCategory = resolveCategory2(realTask);
38262
+ if (baselineCategory !== realCategory) {
38263
+ throw new Error(`Task ${JSON.stringify(taskId)} has mismatched categories.`);
38264
+ }
38265
+ return { taskId, category: baselineCategory, baseline: baselineTask, real: realTask };
38266
+ });
38267
+ }
38268
+ function indexTasks2(tasks, label) {
38269
+ const result = /* @__PURE__ */ new Map();
38270
+ for (const task of tasks) {
38271
+ if (!task.taskId || result.has(task.taskId)) {
38272
+ throw new Error(`${label} result contains duplicate or empty task id ${JSON.stringify(task.taskId)}.`);
38273
+ }
38274
+ if (!task.question || !task.expected) {
38275
+ throw new Error(`${label} task ${JSON.stringify(task.taskId)} has an empty question or expected answer.`);
38276
+ }
38277
+ const recalledText = asRecord(task.details)?.recalledText;
38278
+ if (typeof recalledText !== "string") {
38279
+ throw new Error(`${label} task ${JSON.stringify(task.taskId)} has no final recalledText.`);
38280
+ }
38281
+ result.set(task.taskId, task);
38282
+ }
38283
+ return result;
38284
+ }
38285
+ function assertMetricSets(joined, primaryMetric2) {
38286
+ const first = joined[0];
38287
+ if (!first) throw new Error("Cannot validate metric sets for an empty paired result.");
38288
+ const expectedMetrics = Object.keys(first.baseline.scores).sort(compareStrings);
38289
+ for (const task of joined) {
38290
+ const baselineMetrics = Object.keys(task.baseline.scores).sort(compareStrings);
38291
+ const realMetrics = Object.keys(task.real.scores).sort(compareStrings);
38292
+ if (stableJson(baselineMetrics) !== stableJson(realMetrics)) {
38293
+ throw new Error(`Task ${JSON.stringify(task.taskId)} has mismatched metric sets.`);
38294
+ }
38295
+ if (stableJson(baselineMetrics) !== stableJson(expectedMetrics)) {
38296
+ throw new Error(`Task ${JSON.stringify(task.taskId)} has an inconsistent metric set.`);
38297
+ }
38298
+ if (!baselineMetrics.includes(primaryMetric2)) {
38299
+ throw new Error(`Task ${JSON.stringify(task.taskId)} is missing metric ${JSON.stringify(primaryMetric2)}.`);
38300
+ }
38301
+ for (const [side, scores] of [
38302
+ ["baseline", task.baseline.scores],
38303
+ ["real", task.real.scores]
38304
+ ]) {
38305
+ for (const [metric, score] of Object.entries(scores)) {
38306
+ if (!Number.isFinite(score)) {
38307
+ throw new Error(`${side} task ${JSON.stringify(task.taskId)} metric ${metric} is not finite.`);
38308
+ }
38309
+ }
38310
+ }
38311
+ }
38312
+ }
38313
+ function buildRegression(task, metric, excerptChars, maxDiffLines) {
38314
+ const baselineRecall = finalRecallText(task.baseline);
38315
+ const realRecall = finalRecallText(task.real);
38316
+ const baselineLines = contentLines(baselineRecall);
38317
+ const realLines = contentLines(realRecall);
38318
+ const displaced = subtractLineMultiset(baselineLines, realLines);
38319
+ const introduced = subtractLineMultiset(realLines, baselineLines);
38320
+ const baselineScore = requireMetricScore(task.baseline, metric, "baseline");
38321
+ const realScore = requireMetricScore(task.real, metric, "real");
38322
+ return {
38323
+ taskId: task.taskId,
38324
+ category: task.category,
38325
+ baselineScore,
38326
+ realScore,
38327
+ delta: realScore - baselineScore,
38328
+ questionSha256: sha256(normalizeText3(task.baseline.question)),
38329
+ expectedAnswerSha256: sha256(normalizeText3(task.baseline.expected)),
38330
+ baseline: {
38331
+ answer: textDigest(task.baseline.actual, excerptChars),
38332
+ recall: recallSummary(baselineRecall, task.baseline.expected)
38333
+ },
38334
+ real: {
38335
+ answer: textDigest(task.real.actual, excerptChars),
38336
+ recall: recallSummary(realRecall, task.real.expected)
38337
+ },
38338
+ displacedLines: lineDelta(displaced, maxDiffLines, excerptChars),
38339
+ introducedLines: lineDelta(introduced, maxDiffLines, excerptChars)
38340
+ };
38341
+ }
38342
+ function buildProvenance(evidence, profile, joined, side) {
38343
+ const system = requireProvider(evidence.result.config.systemProvider, profile, "system");
38344
+ const judge = requireProvider(evidence.result.config.judgeProvider, profile, "judge");
38345
+ const payload = joined.map((task) => ({
38346
+ taskId: task.taskId,
38347
+ category: task.category,
38348
+ question: task[side].question,
38349
+ expected: task[side].expected
38350
+ }));
38351
+ return {
38352
+ reference: evidence.reference,
38353
+ sha256: evidence.sha256,
38354
+ resultId: evidence.result.meta.id,
38355
+ gitSha: evidence.result.meta.gitSha,
38356
+ remnicVersion: evidence.result.meta.remnicVersion,
38357
+ runtimeProfile: profile,
38358
+ systemProvider: system.provider,
38359
+ systemModel: system.model,
38360
+ judgeProvider: judge.provider,
38361
+ judgeModel: judge.model,
38362
+ seeds: [...evidence.result.meta.seeds],
38363
+ taskPayloadSha256: sha256(stableJson(payload))
38364
+ };
38365
+ }
38366
+ function summarizeMetric(tasks, metric) {
38367
+ let baselineSum = 0;
38368
+ let realSum = 0;
38369
+ let wins = 0;
38370
+ let losses = 0;
38371
+ let ties = 0;
38372
+ for (const task of tasks) {
38373
+ const baseline = requireMetricScore(task.baseline, metric, "baseline");
38374
+ const real = requireMetricScore(task.real, metric, "real");
38375
+ baselineSum += baseline;
38376
+ realSum += real;
38377
+ if (real > baseline) wins += 1;
38378
+ else if (real < baseline) losses += 1;
38379
+ else ties += 1;
38380
+ }
38381
+ const baselineMean = baselineSum / tasks.length;
38382
+ const realMean = realSum / tasks.length;
38383
+ return { baselineMean, realMean, delta: realMean - baselineMean, wins, losses, ties };
38384
+ }
38385
+ function lineDelta(lines, maxDiffLines, excerptChars) {
38386
+ return {
38387
+ totalCount: lines.length,
38388
+ shownCount: Math.min(lines.length, maxDiffLines),
38389
+ lines: lines.slice(0, maxDiffLines).map((line) => {
38390
+ const parsedSourceRef = sourceRef(line.text);
38391
+ return {
38392
+ ordinal: line.ordinal,
38393
+ ...textDigest(line.text, excerptChars),
38394
+ ...parsedSourceRef ? { sourceRef: parsedSourceRef } : {}
38395
+ };
38396
+ })
38397
+ };
38398
+ }
38399
+ function recallSummary(text, expected) {
38400
+ const normalized = normalizeText3(text);
38401
+ const lines = normalized.split("\n").map((line) => line.trim()).filter(Boolean);
38402
+ return {
38403
+ sha256: sha256(normalized),
38404
+ charCount: normalized.length,
38405
+ lineCount: lines.length,
38406
+ headings: [...new Set(lines.filter(isHeading))],
38407
+ sourceRefs: [...new Set(lines.map(sourceRef).filter((value) => !!value))].sort(compareStrings),
38408
+ expectedTokenCoverage: tokenCoverage(expected, normalized)
38409
+ };
38410
+ }
38411
+ function textDigest(text, excerptChars) {
38412
+ const normalized = normalizeText3(text);
38413
+ return {
38414
+ sha256: sha256(normalized),
38415
+ charCount: normalized.length,
38416
+ excerpt: normalized.slice(0, excerptChars)
38417
+ };
38418
+ }
38419
+ function contentLines(text) {
38420
+ return normalizeText3(text).split("\n").map((line, ordinal) => ({ text: line.trim(), ordinal })).filter((line) => line.text.length > 0 && !isHeading(line.text));
38421
+ }
38422
+ function subtractLineMultiset(source, comparison) {
38423
+ const remaining = /* @__PURE__ */ new Map();
38424
+ for (const line of comparison) {
38425
+ remaining.set(line.text, (remaining.get(line.text) ?? 0) + 1);
38426
+ }
38427
+ return source.filter((line) => {
38428
+ const count = remaining.get(line.text) ?? 0;
38429
+ if (count === 0) return true;
38430
+ remaining.set(line.text, count - 1);
38431
+ return false;
38432
+ });
38433
+ }
38434
+ function verifyAggregateMeans(result, joined, side) {
38435
+ const first = joined[0];
38436
+ if (!first) throw new Error("Cannot verify aggregates for an empty paired result.");
38437
+ const metrics = Object.keys(first[side].scores).sort(compareStrings);
38438
+ for (const metric of metrics) {
38439
+ const aggregate = result.results.aggregates[metric];
38440
+ if (!aggregate || !Number.isFinite(aggregate.mean)) {
38441
+ throw new Error(`${side} result has no finite aggregate mean for ${JSON.stringify(metric)}.`);
38442
+ }
38443
+ const computed = joined.reduce((sum, task) => sum + requireMetricScore(task[side], metric, side), 0) / joined.length;
38444
+ if (Math.abs(aggregate.mean - computed) > 1e-12) {
38445
+ throw new Error(`${side} aggregate ${metric}=${aggregate.mean} does not match task mean ${computed}.`);
38446
+ }
38447
+ }
38448
+ }
38449
+ function tokenCoverage(expected, recalled) {
38450
+ const expectedTokens = new Set(tokenize6(expected));
38451
+ if (expectedTokens.size === 0) return 0;
38452
+ const recalledTokens = new Set(tokenize6(recalled));
38453
+ let matched = 0;
38454
+ for (const token of expectedTokens) {
38455
+ if (recalledTokens.has(token)) matched += 1;
38456
+ }
38457
+ return matched / expectedTokens.size;
38458
+ }
38459
+ function tokenize6(value) {
38460
+ return normalizeText3(value).toLocaleLowerCase("en-US").match(/[\p{L}\p{N}]+/gu) ?? [];
38461
+ }
38462
+ function resolveCategory2(task) {
38463
+ const categoryName = asRecord(task.details)?.categoryName;
38464
+ if (typeof categoryName === "string" && categoryName.trim()) return categoryName;
38465
+ const match = task.taskId.match(LOCOMO_TASK_CATEGORY_PATTERN2);
38466
+ if (!match?.[1]) {
38467
+ throw new Error(`Cannot derive LoCoMo category from task id ${JSON.stringify(task.taskId)}.`);
38468
+ }
38469
+ return match[1];
38470
+ }
38471
+ function finalRecallText(task) {
38472
+ const recalledText = asRecord(task.details)?.recalledText;
38473
+ if (typeof recalledText !== "string") {
38474
+ throw new Error(`Task ${JSON.stringify(task.taskId)} has no final recalledText.`);
38475
+ }
38476
+ return recalledText;
38477
+ }
38478
+ function providerIdentity(provider) {
38479
+ if (!provider) return null;
38480
+ return {
38481
+ provider: provider.provider,
38482
+ model: provider.model,
38483
+ rubricVersion: provider.rubricVersion ?? null,
38484
+ baseUrl: provider.baseUrl ?? null,
38485
+ providerRequestTimeoutMs: provider.providerRequestTimeoutMs ?? null,
38486
+ retryOptions: provider.retryOptions ? {
38487
+ maxAttempts: provider.retryOptions.maxAttempts ?? null,
38488
+ baseBackoffMs: provider.retryOptions.baseBackoffMs ?? null,
38489
+ timeoutMs: provider.retryOptions.timeoutMs ?? null,
38490
+ retryOnTimeout: provider.retryOptions.retryOnTimeout ?? null,
38491
+ max429WaitMs: provider.retryOptions.max429WaitMs ?? null
38492
+ } : null,
38493
+ disableThinking: provider.disableThinking ?? null,
38494
+ reasoningEffort: provider.reasoningEffort ?? null,
38495
+ responderContextBudgetChars: provider.responderContextBudgetChars ?? null,
38496
+ responderPromptBudgetChars: provider.responderPromptBudgetChars ?? null,
38497
+ temperature: provider.temperature ?? null,
38498
+ seed: provider.seed ?? null
38499
+ };
38500
+ }
38501
+ function sourceRef(line) {
38502
+ const match = line.match(SOURCE_TURN_PATTERN);
38503
+ const sessionId = match?.[1];
38504
+ const turn = match?.[2];
38505
+ const role = match?.[3];
38506
+ if (!sessionId || !turn || !role) return void 0;
38507
+ return `${sessionId}:turn-${turn}:${role.trim().toLowerCase()}`;
38508
+ }
38509
+ function requireMetricScore(task, metric, side) {
38510
+ const score = task.scores[metric];
38511
+ if (typeof score !== "number" || !Number.isFinite(score)) {
38512
+ throw new Error(`${side} task ${JSON.stringify(task.taskId)} metric ${metric} is not finite.`);
38513
+ }
38514
+ return score;
38515
+ }
38516
+ function requireProvider(provider, profile, role) {
38517
+ if (!provider) throw new Error(`${profile} result has no ${role} provider identity.`);
38518
+ return provider;
38519
+ }
38520
+ function isHeading(line) {
38521
+ return /^##\s+/.test(line);
38522
+ }
38523
+ function normalizeText3(value) {
38524
+ return value.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
38525
+ }
38526
+ function sha256(value) {
38527
+ return createHash13("sha256").update(value).digest("hex");
38528
+ }
38529
+ function stableJson(value) {
38530
+ return JSON.stringify(value);
38531
+ }
38532
+ function asRecord(value) {
38533
+ return typeof value === "object" && value !== null ? value : void 0;
38534
+ }
38535
+ function parseNonNegativeInteger(value, label) {
38536
+ if (!Number.isInteger(value) || value < 0) {
38537
+ throw new Error(`${label} must be a non-negative integer.`);
38538
+ }
38539
+ return value;
38540
+ }
38541
+ function compareLoComoCategories2(left, right) {
38542
+ const leftIndex = LOCOMO_CATEGORY_ORDER2.indexOf(left);
38543
+ const rightIndex = LOCOMO_CATEGORY_ORDER2.indexOf(right);
38544
+ if (leftIndex >= 0 && rightIndex >= 0) return leftIndex - rightIndex;
38545
+ if (leftIndex >= 0) return -1;
38546
+ if (rightIndex >= 0) return 1;
38547
+ return compareStrings(left, right);
38548
+ }
38549
+ function compareStrings(left, right) {
38550
+ return left < right ? -1 : left > right ? 1 : 0;
38551
+ }
38552
+ function escapeMarkdownCell(value) {
38553
+ return value.replaceAll("|", "\\|").replaceAll("\n", " ");
38554
+ }
38555
+ function formatScore2(value) {
38556
+ return value.toFixed(4);
38557
+ }
38558
+ function formatSignedScore2(value) {
38559
+ return `${value >= 0 ? "+" : ""}${formatScore2(value)}`;
38560
+ }
38561
+
37907
38562
  // src/integrity/sealed-qrels.ts
37908
38563
  import { readFile as readFile20 } from "fs/promises";
37909
38564
  function isSealedQrelsArtifact(value) {
@@ -39307,7 +39962,7 @@ var chatFixture = {
39307
39962
  };
39308
39963
 
39309
39964
  // src/judges/calibration-slice.ts
39310
- import { createHash as createHash12, randomBytes as randomBytes3 } from "crypto";
39965
+ import { createHash as createHash14, randomBytes as randomBytes3 } from "crypto";
39311
39966
  import { mkdir as mkdir18, readFile as readFile22, rename as rename4, unlink as unlink4, writeFile as writeFile17 } from "fs/promises";
39312
39967
  import path37 from "path";
39313
39968
 
@@ -39454,7 +40109,7 @@ function selectCalibrationSlice(questionIds, size = CALIBRATION_SLICE_SIZE) {
39454
40109
  unique.push(id);
39455
40110
  }
39456
40111
  }
39457
- return unique.map((id) => ({ id, digest: createHash12("sha256").update(id, "utf8").digest("hex") })).sort((a, b) => a.digest < b.digest ? -1 : a.digest > b.digest ? 1 : 0).slice(0, Math.min(size, unique.length)).map((entry) => entry.id);
40112
+ return unique.map((id) => ({ id, digest: createHash14("sha256").update(id, "utf8").digest("hex") })).sort((a, b) => a.digest < b.digest ? -1 : a.digest > b.digest ? 1 : 0).slice(0, Math.min(size, unique.length)).map((entry) => entry.id);
39458
40113
  }
39459
40114
  async function runJudgeCalibration(options) {
39460
40115
  const binScore = options.binScore ?? ((score) => binarizeJudgeScore(score));
@@ -39529,7 +40184,7 @@ function validatePinnedQuestionIds(ids, availableIds) {
39529
40184
  return [...ids];
39530
40185
  }
39531
40186
  function hashCalibrationAnswerSet(answers) {
39532
- return createHash12("sha256").update(JSON.stringify(answers.map((answer) => [
40187
+ return createHash14("sha256").update(JSON.stringify(answers.map((answer) => [
39533
40188
  answer.questionId,
39534
40189
  answer.question,
39535
40190
  answer.predicted,
@@ -40216,7 +40871,7 @@ var PROCEDURAL_REAL_SCENARIOS_SMOKE = [
40216
40871
  ];
40217
40872
 
40218
40873
  // src/security/extraction-attack/tokenize.ts
40219
- function tokenize6(text) {
40874
+ function tokenize7(text) {
40220
40875
  return text.toLowerCase().split(/[^a-z0-9]+/u).filter((t) => t.length > 2);
40221
40876
  }
40222
40877
 
@@ -40258,7 +40913,7 @@ function createSeededRng2(seed) {
40258
40913
  }
40259
40914
  };
40260
40915
  }
40261
- var tokenizeContent = tokenize6;
40916
+ var tokenizeContent = tokenize7;
40262
40917
  function recoveryTokensFor(memory) {
40263
40918
  if (memory.tokens && memory.tokens.length > 0) {
40264
40919
  const seen = /* @__PURE__ */ new Set();
@@ -40737,11 +41392,11 @@ function createSyntheticTarget(options) {
40737
41392
  }
40738
41393
  const normalized = memories.map((m) => ({
40739
41394
  memory: m,
40740
- tokens: new Set((m.tokens ?? tokenize6(m.content)).map((t) => t.toLowerCase()))
41395
+ tokens: new Set((m.tokens ?? tokenize7(m.content)).map((t) => t.toLowerCase()))
40741
41396
  }));
40742
41397
  return {
40743
41398
  async recall(query, recallOptions) {
40744
- const qTokens = tokenize6(query);
41399
+ const qTokens = tokenize7(query);
40745
41400
  if (qTokens.length === 0) return [];
40746
41401
  const requestedNs = recallOptions?.namespace;
40747
41402
  if (enforceNamespaceAcl && requestedNs !== void 0 && requestedNs !== allowedNamespace) {
@@ -40985,7 +41640,7 @@ function createMitigatedTarget(config) {
40985
41640
  }
40986
41641
 
40987
41642
  // src/coding-graph/generator.ts
40988
- import { createHash as createHash13 } from "crypto";
41643
+ import { createHash as createHash15 } from "crypto";
40989
41644
  function createSeededRng3(seed) {
40990
41645
  let state = seed >>> 0;
40991
41646
  return function rng() {
@@ -41014,7 +41669,7 @@ var EDGE_TYPE_WEIGHTS = [
41014
41669
  var PROVENANCE_VALUES = ["heuristic", "heuristic", "heuristic", "trace"];
41015
41670
  var AVG_BYTES_PER_LINE = 40;
41016
41671
  function hashContent(input) {
41017
- return createHash13("sha256").update(input).digest("hex").slice(0, 16);
41672
+ return createHash15("sha256").update(input).digest("hex").slice(0, 16);
41018
41673
  }
41019
41674
  function generateSyntheticRepo(config) {
41020
41675
  const rng = createSeededRng3(config.seed);
@@ -41582,6 +42237,9 @@ export {
41582
42237
  JUDGE_CALIBRATION_KAPPA_THRESHOLD,
41583
42238
  LOCAL_LAB_PROVIDER_KINDS,
41584
42239
  LOCOMO_DATASET_FILENAMES,
42240
+ LOCOMO_FULL_TASK_COUNT,
42241
+ LOCOMO_RECALL_DIFF_LINE_LIMIT,
42242
+ LOCOMO_RECALL_EXCERPT_CHARS,
41585
42243
  LONG_MEM_EVAL_DATASET_FILENAMES,
41586
42244
  LettaMemCorrectAdapter,
41587
42245
  LocalLabPreflightError,
@@ -41692,6 +42350,7 @@ export {
41692
42350
  defaultBenchmarkPublishPath,
41693
42351
  deleteBenchmarkResults,
41694
42352
  diagnoseLoComoProfileDelta,
42353
+ diagnoseLoComoRecallDelta,
41695
42354
  discoverAllProviders,
41696
42355
  discoveryEndpointFor,
41697
42356
  emailFixture,
@@ -41766,6 +42425,7 @@ export {
41766
42425
  renderBaselineMarkdown,
41767
42426
  renderBenchmarkResultExport,
41768
42427
  renderLoComoProfileDeltaMarkdown,
42428
+ renderLoComoRecallDeltaMarkdown,
41769
42429
  renderMemorySummaryForJudge,
41770
42430
  renderMemoryViewForAgent,
41771
42431
  resolveAssistantAgent,
@@ -41801,6 +42461,7 @@ export {
41801
42461
  runSealedJudge,
41802
42462
  runSequentialPhases,
41803
42463
  safeHexEqual,
42464
+ sanitizeLoComoResultReference,
41804
42465
  saveBaseline,
41805
42466
  saveBenchmarkBaseline,
41806
42467
  schemaCompleteness,