@remnic/cli 9.3.700 → 9.3.702

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +187 -3
  2. package/package.json +28 -28
package/dist/index.js CHANGED
@@ -643,6 +643,7 @@ function readBenchOptionValue(argv, flag) {
643
643
  }
644
644
  var BENCH_VALUE_FLAGS = Object.freeze([
645
645
  "--dataset-dir",
646
+ "--benchmark",
646
647
  "--results-dir",
647
648
  "--baselines-dir",
648
649
  "--runtime-profile",
@@ -826,6 +827,18 @@ var BENCH_ACTION_FLAGS = {
826
827
  value: ["--results-dir", "--target", "--output"],
827
828
  boolean: ["--json", "--help", "-h"]
828
829
  },
830
+ "judge-calibrate": {
831
+ value: [
832
+ "--results-dir",
833
+ "--benchmark",
834
+ "--local-lab-manifest",
835
+ "--judge-provider",
836
+ "--judge-model",
837
+ "--judge-base-url",
838
+ "--judge-api-key"
839
+ ],
840
+ boolean: ["--json", "--help", "-h"]
841
+ },
829
842
  published: {
830
843
  value: PUBLISHED_VALUE_FLAGS,
831
844
  boolean: PUBLISHED_BOOLEAN_FLAGS
@@ -915,7 +928,7 @@ function collectBenchmarks(argv) {
915
928
  }
916
929
  function parseBenchActionArgs(argv) {
917
930
  const [first, ...rest] = argv;
918
- const action = first === "list" || first === "run" || first === "datasets" || first === "runs" || first === "compare" || first === "ui" || first === "results" || first === "baseline" || first === "export" || first === "providers" || first === "publish" || first === "published" || first === "check" || first === "report" ? first : first === void 0 || first === "--help" || first === "-h" ? "help" : "run";
931
+ const action = first === "list" || first === "run" || first === "datasets" || first === "runs" || first === "compare" || first === "ui" || first === "results" || first === "baseline" || first === "export" || first === "providers" || first === "publish" || first === "published" || first === "judge-calibrate" || first === "check" || first === "report" ? first : first === void 0 || first === "--help" || first === "-h" ? "help" : "run";
919
932
  return {
920
933
  action,
921
934
  args: action === "run" && action !== first ? argv : rest
@@ -3219,8 +3232,8 @@ async function loadTrainingExportCoreRuntime() {
3219
3232
  return await import("@remnic/core");
3220
3233
  }
3221
3234
  function getBenchUsageText() {
3222
- return `Usage: remnic bench <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers> [options] [benchmark...]
3223
- remnic benchmark <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|check|report> [options] [benchmark...]
3235
+ return `Usage: remnic bench <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate> [options] [benchmark...]
3236
+ remnic benchmark <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|check|report> [options] [benchmark...]
3224
3237
 
3225
3238
  Commands:
3226
3239
  list List published benchmark packs
@@ -3248,6 +3261,11 @@ Commands:
3248
3261
  Generate the Remnic.ai benchmark feed from stored runs
3249
3262
  ui Launch the local benchmark overview UI
3250
3263
  providers discover Auto-detect available local provider backends
3264
+ judge-calibrate --benchmark <id> --local-lab-manifest <path> --judge-provider <p> --judge-model <m>
3265
+ Cross-tier judge calibration (issue #1573): runs the
3266
+ local + frontier judges over a benchmark's cached
3267
+ answers, reports Cohen's kappa, and persists it so
3268
+ subsequent local artifacts carry the kappa + warning.
3251
3269
  check Legacy latency regression gate (compatibility)
3252
3270
  report Legacy latency report generator (compatibility)
3253
3271
  procedural-ablation --out <path> [--fixture <path>]
@@ -4425,6 +4443,144 @@ async function discoverBenchProviders(parsed) {
4425
4443
  }
4426
4444
  }
4427
4445
  }
4446
+ async function calibrateBenchJudges(parsed, rawArgs) {
4447
+ const benchmarkId = readBenchOptionValue(rawArgs, "--benchmark") ?? parsed.benchmarks[0];
4448
+ if (!benchmarkId) {
4449
+ console.error(
4450
+ "ERROR: judge-calibrate requires a benchmark. Usage: remnic bench judge-calibrate --benchmark <id> [--local-lab-manifest <path>] [--judge-provider <p> --judge-model <m>] [--results-dir <path>] [--json]"
4451
+ );
4452
+ process.exit(1);
4453
+ }
4454
+ const knownBenchmarkIds = await resolveKnownBenchmarkIds();
4455
+ if (!knownBenchmarkIds.has(benchmarkId)) {
4456
+ console.error(
4457
+ `ERROR: unknown benchmark "${benchmarkId}". Known: ${[...knownBenchmarkIds].sort().join(", ")}.`
4458
+ );
4459
+ process.exit(1);
4460
+ }
4461
+ const manifestPath = parsed.localLabManifestPath;
4462
+ if (!manifestPath) {
4463
+ console.error(
4464
+ "ERROR: judge-calibrate requires --local-lab-manifest <path> (the Tier L judge source). Provide a local-lab manifest whose judge role names the local model."
4465
+ );
4466
+ process.exit(1);
4467
+ }
4468
+ if (!parsed.judgeProvider || !parsed.judgeModel) {
4469
+ console.error(
4470
+ "ERROR: judge-calibrate requires --judge-provider <p> and --judge-model <m> (the Tier F gold-standard judge)."
4471
+ );
4472
+ process.exit(1);
4473
+ }
4474
+ const bench = await loadBenchModule();
4475
+ const resultsDir = expandTilde(
4476
+ parsed.resultsDir ?? path11.join(resolveHomeDir(), ".remnic", "bench", "results")
4477
+ );
4478
+ const stored = await bench.listBenchmarkResults(resultsDir);
4479
+ const allForBenchmark = stored.filter((entry) => entry.benchmark === benchmarkId);
4480
+ const candidates = allForBenchmark.filter((entry) => entry.mode === "full").sort((a, b) => {
4481
+ if (a.timestamp !== b.timestamp) {
4482
+ return a.timestamp < b.timestamp ? 1 : -1;
4483
+ }
4484
+ return a.id < b.id ? 1 : a.id > b.id ? -1 : 0;
4485
+ });
4486
+ const latest = candidates[0];
4487
+ if (!latest) {
4488
+ const quickCount = allForBenchmark.filter((entry) => entry.mode === "quick").length;
4489
+ console.error(
4490
+ quickCount > 0 ? `ERROR: no full stored results for "${benchmarkId}" in ${resultsDir} (found ${quickCount} quick run(s); a 1-task quick sample cannot calibrate the judge). Run a full benchmark first (remnic bench run ${benchmarkId}).` : `ERROR: no stored benchmark results for "${benchmarkId}" in ${resultsDir}. Run the benchmark first (remnic bench run ${benchmarkId}) so cached answers exist to calibrate against.`
4491
+ );
4492
+ process.exit(1);
4493
+ }
4494
+ let loaded = await bench.loadBenchmarkResult(latest.path);
4495
+ if (loaded.meta.status === "partial") {
4496
+ for (const candidate of candidates.slice(1)) {
4497
+ const candidateResult = await bench.loadBenchmarkResult(candidate.path);
4498
+ if (candidateResult.meta.status !== "partial") {
4499
+ loaded = candidateResult;
4500
+ break;
4501
+ }
4502
+ }
4503
+ }
4504
+ const uniqueTaskIds = new Set(loaded.results.tasks.map((task) => task.taskId));
4505
+ const sourceTaskCount = uniqueTaskIds.size;
4506
+ if (sourceTaskCount < bench.MIN_CALIBRATION_SOURCE_TASKS) {
4507
+ console.error(
4508
+ `ERROR: stored result for "${benchmarkId}" has only ${sourceTaskCount} task(s) \u2014 too few for a meaningful calibration (minimum ${bench.MIN_CALIBRATION_SOURCE_TASKS}). Run a full uncapped benchmark first (remnic bench run ${benchmarkId}).`
4509
+ );
4510
+ process.exit(1);
4511
+ }
4512
+ const answers = loaded.results.tasks.map((task) => ({
4513
+ questionId: task.taskId,
4514
+ question: task.question,
4515
+ predicted: task.actual,
4516
+ expected: task.expected
4517
+ }));
4518
+ const manifest = await bench.loadLocalLabManifest(expandTilde(manifestPath));
4519
+ const resolvedProfile = bench.resolveLocalLabProfile(manifest);
4520
+ const localJudgeConfig = resolvedProfile.judge.providerConfig;
4521
+ const localJudge = bench.createProviderBackedJudge(localJudgeConfig);
4522
+ const frontierJudge = bench.createProviderBackedJudge({
4523
+ provider: parsed.judgeProvider,
4524
+ model: parsed.judgeModel,
4525
+ ...parsed.judgeBaseUrl ? { baseUrl: parsed.judgeBaseUrl } : {},
4526
+ ...parsed.judgeApiKey ? { apiKey: parsed.judgeApiKey } : {}
4527
+ });
4528
+ const result = await bench.runJudgeCalibration({
4529
+ benchmarkId,
4530
+ localJudge,
4531
+ frontierJudge,
4532
+ answers
4533
+ });
4534
+ const calibrationDir = path11.join(resolveHomeDir(), ".remnic", "bench", "calibration");
4535
+ const calibrationIdentities = {
4536
+ localJudgeProvider: String(localJudgeConfig.provider),
4537
+ localJudgeModel: String(localJudgeConfig.model),
4538
+ frontierJudgeProvider: parsed.judgeProvider,
4539
+ frontierJudgeModel: parsed.judgeModel
4540
+ };
4541
+ const statePath = await bench.writeJudgeCalibrationState(result, calibrationDir, calibrationIdentities);
4542
+ const persisted = await bench.loadJudgeCalibrationState(benchmarkId, calibrationDir);
4543
+ if (!persisted || persisted.kappa !== result.kappa || persisted.warning !== result.warning) {
4544
+ console.error(
4545
+ `ERROR: calibration state round-trip failed for ${benchmarkId} (wrote kappa ${result.kappa}, read back ${persisted ? persisted.kappa : "nothing"}). Re-run judge-calibrate.`
4546
+ );
4547
+ process.exit(1);
4548
+ }
4549
+ if (parsed.json) {
4550
+ console.log(
4551
+ JSON.stringify(
4552
+ {
4553
+ benchmarkId: result.benchmarkId,
4554
+ kappa: result.kappa,
4555
+ observedAgreement: result.observedAgreement,
4556
+ expectedAgreement: result.expectedAgreement,
4557
+ sampleSize: result.sampleSize,
4558
+ threshold: result.threshold,
4559
+ warning: result.warning,
4560
+ categories: result.categories,
4561
+ statePath
4562
+ },
4563
+ null,
4564
+ 2
4565
+ )
4566
+ );
4567
+ return;
4568
+ }
4569
+ console.log(`Judge calibration: ${benchmarkId}`);
4570
+ console.log(` Cohen's kappa: ${result.kappa.toFixed(4)} (threshold ${result.threshold})`);
4571
+ console.log(` Sample size: ${result.sampleSize}`);
4572
+ console.log(` Observed agreement: ${result.observedAgreement.toFixed(4)}`);
4573
+ console.log(` Expected agreement: ${result.expectedAgreement.toFixed(4)}`);
4574
+ if (result.warning) {
4575
+ console.log(
4576
+ ` WARNING: local judge unreliable for ${benchmarkId} (kappa ${result.kappa.toFixed(4)} < ${result.threshold}). Tier L numbers for this benchmark should not be trusted for regression until the judge improves.`
4577
+ );
4578
+ } else {
4579
+ console.log(` OK: local judge agrees with frontier above threshold.`);
4580
+ }
4581
+ console.log(` Calibration state written + verified (round-trip ok): ${statePath}`);
4582
+ console.log(` Subsequent local artifacts for ${benchmarkId} will carry kappa ${persisted.kappa.toFixed(4)}.`);
4583
+ }
4428
4584
  async function publishBenchPackageResults(parsed) {
4429
4585
  if (parsed.benchmarks.length > 0) {
4430
4586
  console.error(
@@ -4889,6 +5045,7 @@ async function runBenchViaPackage(parsed, benchmarkId, runtimeProfile, benchStat
4889
5045
  });
4890
5046
  result.config.remnicConfig = plan.runtime.remnicConfig;
4891
5047
  result.config.internalProvider = plan.runtime.internalProvider;
5048
+ await attachPersistedJudgeCalibration(benchModule, benchmarkId, result);
4892
5049
  const writtenPath = await benchModule.writeBenchmarkResult(result, outputDir);
4893
5050
  if (parsed.json) {
4894
5051
  console.log(JSON.stringify(redactBenchResultForStdout(benchModule, result), null, 2));
@@ -4909,6 +5066,7 @@ async function runBenchViaPackage(parsed, benchmarkId, runtimeProfile, benchStat
4909
5066
  err instanceof Error ? err.message : String(err),
4910
5067
  parsed.quick ? "quick" : "full"
4911
5068
  );
5069
+ await attachPersistedJudgeCalibration(benchModule, benchmarkId, partialResult);
4912
5070
  try {
4913
5071
  const partialPath = await benchModule.writeBenchmarkResult(partialResult, outputDir);
4914
5072
  console.error(` Partial results (${partialTasks.length} tasks) written to ${partialPath}`);
@@ -4932,6 +5090,28 @@ async function runBenchViaPackage(parsed, benchmarkId, runtimeProfile, benchStat
4932
5090
  }
4933
5091
  }
4934
5092
  }
5093
+ async function attachPersistedJudgeCalibration(benchModule, benchmarkId, result) {
5094
+ const calibrationDir = path11.join(resolveHomeDir(), ".remnic", "bench", "calibration");
5095
+ const state = await benchModule.loadJudgeCalibrationState?.(benchmarkId, calibrationDir);
5096
+ if (!state) return;
5097
+ if (state.localJudgeModel !== void 0 && state.frontierJudgeModel !== void 0) {
5098
+ const runJudgeProvider = result.config.judgeProvider?.provider;
5099
+ const runJudgeModel = result.config.judgeProvider?.model;
5100
+ const matchesLocal = runJudgeProvider === state.localJudgeProvider && runJudgeModel === state.localJudgeModel;
5101
+ if (!matchesLocal) {
5102
+ return;
5103
+ }
5104
+ }
5105
+ result.config.benchmarkOptions = {
5106
+ ...result.config.benchmarkOptions ?? {},
5107
+ judgeCalibration: {
5108
+ kappa: state.kappa,
5109
+ sampleSize: state.sampleSize,
5110
+ threshold: state.threshold,
5111
+ warning: state.warning
5112
+ }
5113
+ };
5114
+ }
4935
5115
  function restoreOptionalEnv(key, previousValue) {
4936
5116
  if (previousValue === void 0) {
4937
5117
  delete process.env[key];
@@ -9666,6 +9846,10 @@ async function cmdBench(rest) {
9666
9846
  await exportBenchPackageResult(parsed);
9667
9847
  return;
9668
9848
  }
9849
+ if (parsed.action === "judge-calibrate") {
9850
+ await calibrateBenchJudges(parsed, benchAction.args);
9851
+ return;
9852
+ }
9669
9853
  if (parsed.action === "datasets") {
9670
9854
  await manageBenchDatasets(parsed);
9671
9855
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/cli",
3
- "version": "9.3.700",
3
+ "version": "9.3.702",
4
4
  "description": "CLI for Remnic memory — init, query, doctor, daemon management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,23 +26,23 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "yaml": "^2.4.2",
29
- "@remnic/plugin-pi": "^9.3.700",
30
- "@remnic/server": "^9.3.700",
31
- "@remnic/core": "^9.3.700"
29
+ "@remnic/plugin-pi": "^9.3.702",
30
+ "@remnic/core": "^9.3.702",
31
+ "@remnic/server": "^9.3.702"
32
32
  },
33
33
  "peerDependencies": {
34
- "@remnic/bench": "^9.3.700",
35
- "@remnic/export-weclone": "^9.3.700",
36
- "@remnic/import-weclone": "^9.3.700",
37
- "@remnic/import-chatgpt": "^9.3.700",
38
- "@remnic/import-claude": "^9.3.700",
39
- "@remnic/import-gemini": "^9.3.700",
40
- "@remnic/import-lossless-claw": "^9.3.700",
41
- "@remnic/import-mem0": "^9.3.700",
42
- "@remnic/import-supermemory": "^9.3.700",
43
- "@remnic/connector-limitless": "^9.3.700",
44
- "@remnic/connector-bee": "^9.3.700",
45
- "@remnic/connector-omi": "^9.3.700"
34
+ "@remnic/bench": "^9.3.702",
35
+ "@remnic/export-weclone": "^9.3.702",
36
+ "@remnic/import-weclone": "^9.3.702",
37
+ "@remnic/import-chatgpt": "^9.3.702",
38
+ "@remnic/import-claude": "^9.3.702",
39
+ "@remnic/import-gemini": "^9.3.702",
40
+ "@remnic/import-lossless-claw": "^9.3.702",
41
+ "@remnic/import-mem0": "^9.3.702",
42
+ "@remnic/import-supermemory": "^9.3.702",
43
+ "@remnic/connector-limitless": "^9.3.702",
44
+ "@remnic/connector-bee": "^9.3.702",
45
+ "@remnic/connector-omi": "^9.3.702"
46
46
  },
47
47
  "peerDependenciesMeta": {
48
48
  "@remnic/bench": {
@@ -85,18 +85,18 @@
85
85
  "devDependencies": {
86
86
  "tsup": "^8.5.1",
87
87
  "typescript": "^5.9.3",
88
- "@remnic/bench": "9.3.700",
89
- "@remnic/export-weclone": "9.3.700",
90
- "@remnic/import-weclone": "9.3.700",
91
- "@remnic/import-claude": "9.3.700",
92
- "@remnic/import-chatgpt": "9.3.700",
93
- "@remnic/import-gemini": "9.3.700",
94
- "@remnic/import-supermemory": "9.3.700",
95
- "@remnic/import-lossless-claw": "9.3.700",
96
- "@remnic/import-mem0": "9.3.700",
97
- "@remnic/connector-limitless": "9.3.700",
98
- "@remnic/connector-omi": "9.3.700",
99
- "@remnic/connector-bee": "9.3.700"
88
+ "@remnic/bench": "9.3.702",
89
+ "@remnic/export-weclone": "9.3.702",
90
+ "@remnic/import-weclone": "9.3.702",
91
+ "@remnic/import-chatgpt": "9.3.702",
92
+ "@remnic/import-claude": "9.3.702",
93
+ "@remnic/import-gemini": "9.3.702",
94
+ "@remnic/import-mem0": "9.3.702",
95
+ "@remnic/import-lossless-claw": "9.3.702",
96
+ "@remnic/import-supermemory": "9.3.702",
97
+ "@remnic/connector-omi": "9.3.702",
98
+ "@remnic/connector-limitless": "9.3.702",
99
+ "@remnic/connector-bee": "9.3.702"
100
100
  },
101
101
  "license": "MIT",
102
102
  "repository": {