@velum-labs/routekit-eval-setup 1.0.20 → 1.0.21

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.
@@ -787,7 +787,7 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
787
787
  const next = {
788
788
  version: state.version,
789
789
  projectId: state.projectId,
790
- revision: state.revision + 1,
790
+ revision: state.revision,
791
791
  createdAt: state.createdAt,
792
792
  updatedAt: now,
793
793
  sourceInventory: state.sourceInventory,
@@ -879,7 +879,7 @@ export const makeEvalProjectWorkflow = Effect.gen(function* () {
879
879
  const next = {
880
880
  version: state.version,
881
881
  projectId: state.projectId,
882
- revision: state.revision + 1,
882
+ revision: state.revision,
883
883
  createdAt: state.createdAt,
884
884
  updatedAt: report.finishedAt,
885
885
  sourceInventory: state.sourceInventory,
@@ -542,6 +542,77 @@ test("run lifecycle retains complete sanitized evidence and activates only after
542
542
  const reportPath = path.join(root, ".routekit", "evals", "runs", outcome.started.runId, "report.json");
543
543
  assert.equal((await stat(reportPath)).mode & 0o777, 0o600);
544
544
  });
545
+ test("failed runs preserve plan revisions for retry while mismatched plans remain stale", async () => {
546
+ const root = await makeRepository();
547
+ const plan = await createPlan(root, "full");
548
+ const mismatchedPlans = [
549
+ {
550
+ ...plan,
551
+ planId: `${plan.planId}-project`,
552
+ projectId: "different-project-id"
553
+ },
554
+ {
555
+ ...plan,
556
+ planId: `${plan.planId}-evaluation`,
557
+ evaluationDigest: "different-evaluation-digest"
558
+ },
559
+ {
560
+ ...plan,
561
+ planId: `${plan.planId}-models`,
562
+ candidateModels: [...plan.candidateModels].reverse()
563
+ }
564
+ ];
565
+ await Promise.all(mismatchedPlans.map((mismatchedPlan) => writeFile(path.join(root, ".routekit", "evals", "plans", `${mismatchedPlan.planId}.json`), JSON.stringify(mismatchedPlan))));
566
+ const rerun = await Effect.runPromise(Effect.gen(function* () {
567
+ const workflow = yield* EvalProjectWorkflow;
568
+ for (const mismatchedPlan of mismatchedPlans) {
569
+ const mismatch = yield* Effect.exit(workflow.startRun(root, mismatchedPlan.planId));
570
+ assert.equal(mismatch._tag, "Failure");
571
+ if (mismatch._tag === "Failure") {
572
+ assert.match(String(mismatch.cause), /execution plan is stale/u);
573
+ }
574
+ }
575
+ const first = yield* workflow.startRun(root, plan.planId);
576
+ const running = yield* workflow.status(root);
577
+ const ready = yield* workflow.failRun(root, {
578
+ version: 1,
579
+ status: "failed",
580
+ runId: first.runId,
581
+ planId: plan.planId,
582
+ projectId: running.state.projectId,
583
+ startedAt: "2026-08-21T03:47:27.000Z",
584
+ finishedAt: "2026-08-21T03:47:48.000Z",
585
+ basisDigest: plan.basisDigest,
586
+ evaluationDigest: plan.evaluationDigest,
587
+ target: {
588
+ kind: "configured",
589
+ identity: "routekit-generation:48",
590
+ publishAllowed: true
591
+ },
592
+ cleanup: { sessionOpened: true, sessionClosed: true },
593
+ comparisons: [],
594
+ ledger: {
595
+ expectedCalls: plan.expectedCallCount,
596
+ observedCalls: 0,
597
+ observedCandidateRows: 0,
598
+ knownInputTokens: 0,
599
+ knownOutputTokens: 0,
600
+ unknownTokenMeasurements: 0,
601
+ knownPricedSubtotalUsd: 0,
602
+ unpricedCalls: 0
603
+ },
604
+ failure: "qualification timed out before observing any calls",
605
+ errors: []
606
+ });
607
+ const second = yield* workflow.startRun(root, plan.planId);
608
+ return { ready, second };
609
+ }).pipe(Effect.provide(ProjectWorkflowTestLive)));
610
+ assert.equal(rerun.ready.state.stage, "ready");
611
+ assert.equal(rerun.ready.state.revision, plan.projectRevision);
612
+ assert.equal(rerun.ready.state.basisDigest, plan.basisDigest);
613
+ assert.equal(rerun.ready.state.evaluationDigest, plan.evaluationDigest);
614
+ assert.equal(rerun.second.plan.planId, plan.planId);
615
+ });
545
616
  test("failed run reports persist the nested qualification error chain", async () => {
546
617
  const root = await makeRepository();
547
618
  const plan = await createPlan(root, "full");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@velum-labs/routekit-eval-setup",
3
3
  "private": false,
4
- "version": "1.0.20",
4
+ "version": "1.0.21",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/velum-labs/routekit.git",
@@ -32,8 +32,8 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "effect": "4.0.0-rc.108",
35
- "@velum-labs/routekit-eval-contracts": "1.0.20",
36
- "@velum-labs/routekit-runtime": "1.0.20"
35
+ "@velum-labs/routekit-eval-contracts": "1.0.21",
36
+ "@velum-labs/routekit-runtime": "1.0.21"
37
37
  },
38
38
  "keywords": [
39
39
  "routekit",