@rulvar/cli 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { r as runCli, t as processIo } from "./io-DUfUn6KG.js";
2
+ import { r as runCli, t as processIo } from "./io-TjsY28AR.js";
3
3
  //#region src/cli.ts
4
4
  /**
5
5
  * The `rulvar` bin entry: thin wrapper over runCli with process io.
@@ -1,4 +1,4 @@
1
- import { KnowledgeCasError, claimExpiry, defineWorkflow } from "@rulvar/core";
1
+ import { KnowledgeCasError, claimExpiry, compileVerifiedLayer, defineWorkflow } from "@rulvar/core";
2
2
  import { createHash } from "node:crypto";
3
3
  //#region ../evals/dist/index.js
4
4
  /**
@@ -381,6 +381,144 @@ async function flipStaleOnCanaryDrift(store, model, freshFingerprint, options) {
381
381
  }
382
382
  throw lastCas ?? /* @__PURE__ */ new Error("flipStaleOnCanaryDrift: unreachable");
383
383
  }
384
+ /**
385
+ * The phases 1-2 measured-value checkpoint (M12-T01; docs/05, section
386
+ * "Phases and placement"; the quantitative criteria of OQ-09,
387
+ * 14-open-questions.md, closed at M11-T06). The M12 gate: kb_propose
388
+ * and the proposal loop ship ONLY if the knowledge card demonstrably
389
+ * improves tier and agentType selection on eval cases.
390
+ *
391
+ * Two experiments, both A/B under identical fixed pools:
392
+ *
393
+ * 1. RUNG SELECTION, per (ladder, taskClass) cell: the baseline arm
394
+ * runs every eval case at the ladder's DEFAULT start tier; the
395
+ * treatment arm runs at the tier recommended by
396
+ * compileVerifiedLayer over the store's claims (default when no
397
+ * recommendation). A cell passes when the treatment reaches a pass
398
+ * rate at least equal to the baseline at no more than 90 percent
399
+ * of its cost, OR at least 5 points above it at no more than its
400
+ * cost. Criterion 1 holds when a MAJORITY of cells pass AND the
401
+ * pooled aggregate passes the same rule.
402
+ *
403
+ * 2. AGENTTYPE SELECTION, pooled: the same orchestrate-role cases run
404
+ * with and without the knowledge store configured (the card docks
405
+ * into the spawn tool description when configured). Criterion 2
406
+ * holds when the card-informed arm matches or beats the baseline
407
+ * pass rate at no more than 105 percent of its cost.
408
+ *
409
+ * The checkpoint PASSES only when both criteria hold. Methodology
410
+ * guard: the claims the treatment consumes MUST come from a seeding
411
+ * sweep over a DISJOINT case set (the seed/eval split is the caller's
412
+ * pool contract), or the measurement is leakage.
413
+ */
414
+ /** IEEE754 guard for the rule boundaries (0.8 + 0.05 exceeds 0.85). */
415
+ const EPSILON = 1e-9;
416
+ /** The OQ-09 cell rule (shared by the per-cell and pooled verdicts). */
417
+ function rungRuleHolds(baseline, treatment) {
418
+ const equalOrBetterCheaper = treatment.passRate >= baseline.passRate - EPSILON && treatment.totalCostUsd <= .9 * baseline.totalCostUsd + EPSILON;
419
+ const clearlyBetterAtCost = treatment.passRate >= baseline.passRate + .05 - EPSILON && treatment.totalCostUsd <= baseline.totalCostUsd + EPSILON;
420
+ return equalOrBetterCheaper || clearlyBetterAtCost;
421
+ }
422
+ function armOf(suite) {
423
+ return {
424
+ passRate: suite.passRate,
425
+ totalCostUsd: suite.totalCostUsd,
426
+ n: suite.results.length
427
+ };
428
+ }
429
+ function pool(arms) {
430
+ const n = arms.reduce((sum, arm) => sum + arm.n, 0);
431
+ const passed = arms.reduce((sum, arm) => sum + arm.passRate * arm.n, 0);
432
+ const cost = arms.reduce((sum, arm) => sum + arm.totalCostUsd, 0);
433
+ return {
434
+ passRate: n === 0 ? 0 : passed / n,
435
+ totalCostUsd: cost,
436
+ n
437
+ };
438
+ }
439
+ /**
440
+ * Runs the checkpoint over the fixed pool. Sequential in declaration
441
+ * order (deterministic cassette consumption when recorded); every cell
442
+ * runs baseline then treatment.
443
+ */
444
+ async function runValueCheckpoint(checkpointPool, options) {
445
+ const recommendations = compileVerifiedLayer(options.snapshot.claims.filter((claim) => claim.status === "active"), checkpointPool.ladders);
446
+ const byTaskClass = /* @__PURE__ */ new Map();
447
+ for (const entry of checkpointPool.evalCases) {
448
+ const bucket = byTaskClass.get(entry.taskClass) ?? [];
449
+ bucket.push(entry.case);
450
+ byTaskClass.set(entry.taskClass, bucket);
451
+ }
452
+ const cells = [];
453
+ for (const ladder of checkpointPool.ladders) for (const [taskClass, cases] of byTaskClass) {
454
+ const recommendation = recommendations.find((row) => row.ladder === ladder.name && row.taskClass === taskClass);
455
+ const treatmentTier = recommendation?.recommendedTier ?? ladder.startTier;
456
+ const baseMember = ladder.rungs[ladder.startTier];
457
+ const treatMember = ladder.rungs[treatmentTier];
458
+ if (baseMember === void 0 || treatMember === void 0) throw new Error(`checkpoint: ladder '${ladder.name}' lacks rung ${String(treatmentTier)}`);
459
+ const baseline = armOf(await runEvalSuite(await options.engineFor(baseMember), cases, options.suite ?? {}));
460
+ const treatment = treatmentTier === ladder.startTier ? baseline : armOf(await runEvalSuite(await options.engineFor(treatMember), cases, options.suite ?? {}));
461
+ cells.push({
462
+ ladder: ladder.name,
463
+ taskClass,
464
+ defaultTier: ladder.startTier,
465
+ treatmentTier,
466
+ recommended: recommendation !== void 0,
467
+ baseline,
468
+ treatment,
469
+ passed: rungRuleHolds(baseline, treatment)
470
+ });
471
+ }
472
+ const recommendedCells = cells.filter((cell) => cell.recommended);
473
+ const cellsPassed = recommendedCells.filter((cell) => cell.passed).length;
474
+ const majorityHolds = recommendedCells.length > 0 && cellsPassed * 2 > recommendedCells.length;
475
+ const pooledBaseline = pool(cells.map((cell) => cell.baseline));
476
+ const pooledTreatment = pool(cells.map((cell) => cell.treatment));
477
+ const pooledHolds = rungRuleHolds(pooledBaseline, pooledTreatment);
478
+ const criterion1 = {
479
+ cells,
480
+ cellsPassed,
481
+ majorityHolds,
482
+ pooledBaseline,
483
+ pooledTreatment,
484
+ pooledHolds,
485
+ passed: majorityHolds && pooledHolds
486
+ };
487
+ let criterion2;
488
+ if (options.orchestrateEngineFor !== void 0 && options.orchestratedCases !== void 0) {
489
+ const cases = options.orchestratedCases.map((entry) => entry.case);
490
+ const orchestratedSuite = options.orchestratedSuite ?? options.suite ?? {};
491
+ const baseline = armOf(await runEvalSuite(await options.orchestrateEngineFor(false), cases, orchestratedSuite));
492
+ const informed = armOf(await runEvalSuite(await options.orchestrateEngineFor(true), cases, orchestratedSuite));
493
+ criterion2 = {
494
+ baseline,
495
+ informed,
496
+ passed: informed.n > 0 && informed.passRate > 0 && informed.passRate >= baseline.passRate && informed.totalCostUsd <= 1.05 * baseline.totalCostUsd + EPSILON
497
+ };
498
+ }
499
+ return {
500
+ observedAt: options.observedAt,
501
+ criterion1,
502
+ ...criterion2 === void 0 ? {} : { criterion2 },
503
+ passed: criterion1.passed && criterion2 !== void 0 && criterion2.passed
504
+ };
505
+ }
506
+ const percent = (rate) => `${(rate * 100).toFixed(1)}%`;
507
+ const usd = (value) => `$${value.toFixed(4)}`;
508
+ /** The deterministic render for the M12 gate docs amendment. */
509
+ function renderCheckpointReport(report) {
510
+ const lines = [
511
+ `Measured-value checkpoint (OQ-09) at ${report.observedAt}: ` + (report.passed ? "PASSED" : "FAILED"),
512
+ "",
513
+ `Criterion 1 (rung selection): ${report.criterion1.passed ? "holds" : "fails"} (${String(report.criterion1.cellsPassed)}/${String(report.criterion1.cells.length)} cells, pooled ${report.criterion1.pooledHolds ? "holds" : "fails"})`
514
+ ];
515
+ for (const cell of report.criterion1.cells) lines.push(`* ${cell.ladder} :: ${cell.taskClass}: baseline tier ${String(cell.defaultTier)} ${percent(cell.baseline.passRate)} at ${usd(cell.baseline.totalCostUsd)}; treatment tier ${String(cell.treatmentTier)}${cell.recommended ? "" : " (no recommendation)"} ${percent(cell.treatment.passRate)} at ${usd(cell.treatment.totalCostUsd)}; ${cell.passed ? "pass" : "fail"} (n=${String(cell.baseline.n)})`);
516
+ if (report.criterion2 !== void 0) {
517
+ const c2 = report.criterion2;
518
+ lines.push("", `Criterion 2 (agentType selection): ${c2.passed ? "holds" : "fails"} (baseline ${percent(c2.baseline.passRate)} at ${usd(c2.baseline.totalCostUsd)}; card-informed ${percent(c2.informed.passRate)} at ${usd(c2.informed.totalCostUsd)}; n=${String(c2.baseline.n)})`);
519
+ } else lines.push("", "Criterion 2 (agentType selection): NOT MEASURED (counts as failed)");
520
+ return lines.join("\n");
521
+ }
384
522
  const SWEEP_THRESHOLD_DEFAULTS = {
385
523
  strength: .9,
386
524
  weakness: .5
@@ -471,4 +609,4 @@ async function runSweepMatrix(pool, options) {
471
609
  return report;
472
610
  }
473
611
  //#endregion
474
- export { EvalJudgeError, JUDGE_VERDICT_SCHEMA, SWEEP_THRESHOLD_DEFAULTS, canaryFingerprint, commitEvalMeasured, evalMeasuredClaim, flipStaleOnCanaryDrift, goldenGrader, judgeGrader, normalizeCanaryOutput, rubricGrader, runEvalCase, runEvalMatrix, runEvalSuite, runSweepMatrix };
612
+ export { EvalJudgeError, JUDGE_VERDICT_SCHEMA, SWEEP_THRESHOLD_DEFAULTS, canaryFingerprint, commitEvalMeasured, evalMeasuredClaim, flipStaleOnCanaryDrift, goldenGrader, judgeGrader, normalizeCanaryOutput, renderCheckpointReport, rubricGrader, runEvalCase, runEvalMatrix, runEvalSuite, runSweepMatrix, runValueCheckpoint, rungRuleHolds };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as resumeCommand, c as driveRun, d as renderEventLine, f as DEFAULT_STORE_DIR, g as looksLikeFile, h as loadWorkflowModule, i as inspectCommand, l as reportOutcome, m as loadCliConfig, n as HELP, o as runCommand, p as assembleEngine, r as runCli, s as runsLsCommand, t as processIo, u as attachProgress } from "./io-DUfUn6KG.js";
1
+ import { a as resumeCommand, c as driveRun, d as renderEventLine, f as DEFAULT_STORE_DIR, g as looksLikeFile, h as loadWorkflowModule, i as inspectCommand, l as reportOutcome, m as loadCliConfig, n as HELP, o as runCommand, p as assembleEngine, r as runCli, s as runsLsCommand, t as processIo, u as attachProgress } from "./io-TjsY28AR.js";
2
2
  import { ConfigError, InvalidResolutionError, JournalCompatibilityError, LeaseHeldError, Replayer, RulvarError, buildDeriverRegistry, costReportFromJournal, maskSecrets, normalizeEntry, scanJournalCompatibility, validateSchemaSpec } from "@rulvar/core";
3
3
  //#region src/server.ts
4
4
  /**
@@ -534,7 +534,7 @@ async function kbSweepCommand(argv, context) {
534
534
  if (sweep === void 0) throw new ConfigError("rulvar kb sweep requires a kbSweep section in rulvar.config.mjs ({ committerId, models, cases }; docs/05, section 'Grounding and decay')");
535
535
  let evals;
536
536
  try {
537
- evals = await import("./dist-4eKFSpyW.js");
537
+ evals = await import("./dist-CU6iYxCW.js");
538
538
  } catch {
539
539
  throw new ConfigError("rulvar kb sweep requires @rulvar/evals (matrix sweeps, the eval-committer identity, and the canary live there); install it next to the CLI");
540
540
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "rulvar shell: run/resume/runs/inspect/plan/kb commands, TUI progress, createServer, createWorker, OTel exporter.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -22,17 +22,17 @@
22
22
  "access": "public"
23
23
  },
24
24
  "dependencies": {
25
- "@rulvar/core": "1.0.0"
25
+ "@rulvar/core": "1.1.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.20.0",
29
29
  "tsdown": "^0.22.3",
30
30
  "typescript": "~6.0.3",
31
- "@rulvar/testing": "1.0.0",
32
- "@rulvar/store-sqlite": "1.0.0",
33
- "@rulvar/planner": "1.0.0",
34
- "@rulvar/plan": "1.0.0",
35
- "@rulvar/evals": "1.0.0"
31
+ "@rulvar/planner": "1.1.0",
32
+ "@rulvar/plan": "1.1.0",
33
+ "@rulvar/evals": "1.1.0",
34
+ "@rulvar/testing": "1.1.0",
35
+ "@rulvar/store-sqlite": "1.1.0"
36
36
  },
37
37
  "bin": {
38
38
  "rulvar": "./dist/cli.js"