@velum-labs/routekit-eval-setup 1.4.0 → 1.5.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/adapters/authoring-responses-request.d.ts +5 -0
- package/dist/adapters/authoring-responses-request.js +38 -0
- package/dist/adapters/evaluation-evidence-freshness.d.ts +7 -0
- package/dist/adapters/evaluation-evidence-freshness.js +76 -0
- package/dist/adapters/git-task-history.d.ts +67 -0
- package/dist/adapters/git-task-history.js +171 -0
- package/dist/adapters/integrated-repository-history.d.ts +21 -0
- package/dist/adapters/integrated-repository-history.js +175 -0
- package/dist/adapters/repository-command-diagnostic.d.ts +8 -0
- package/dist/adapters/repository-command-diagnostic.js +46 -0
- package/dist/adapters/repository-command-evidence.d.ts +13 -0
- package/dist/adapters/repository-command-evidence.js +102 -0
- package/dist/adapters/repository-command-runner.d.ts +238 -0
- package/dist/adapters/repository-command-runner.js +1483 -0
- package/dist/adapters/repository-import-context.d.ts +47 -0
- package/dist/adapters/repository-import-context.js +469 -0
- package/dist/adapters/repository-node-test-reporter.d.ts +3 -0
- package/dist/adapters/repository-node-test-reporter.js +27 -0
- package/dist/adapters/repository-review-evidence.d.ts +39 -0
- package/dist/adapters/repository-review-evidence.js +632 -0
- package/dist/adapters/repository-seed-selection.d.ts +7 -0
- package/dist/adapters/repository-seed-selection.js +79 -0
- package/dist/adapters/repository-solution-edits.d.ts +49 -0
- package/dist/adapters/repository-solution-edits.js +136 -0
- package/dist/adapters/repository-vitest-phase-adapter.d.ts +8 -0
- package/dist/adapters/repository-vitest-phase-adapter.js +310 -0
- package/dist/adapters/repository-vitest-reporter.d.ts +24 -0
- package/dist/adapters/repository-vitest-reporter.js +314 -0
- package/dist/adapters/strict-authoring-schema.d.ts +5 -0
- package/dist/adapters/strict-authoring-schema.js +158 -0
- package/dist/adapters/test-discovery.d.ts +30 -0
- package/dist/adapters/test-discovery.js +124 -0
- package/dist/adapters/typescript-repository-index.d.ts +51 -0
- package/dist/adapters/typescript-repository-index.js +226 -0
- package/dist/agentic-capabilities-protocol.d.ts +1373 -0
- package/dist/agentic-capabilities-protocol.js +786 -0
- package/dist/case-checkpoint-store.d.ts +29 -0
- package/dist/case-checkpoint-store.js +133 -0
- package/dist/case-pipeline-protocol-v2.d.ts +184 -0
- package/dist/case-pipeline-protocol-v2.js +193 -0
- package/dist/case-pipeline-protocol.d.ts +2626 -0
- package/dist/case-pipeline-protocol.js +371 -0
- package/dist/effect-api.d.ts +74 -12
- package/dist/effect-api.js +56 -7
- package/dist/errors.d.ts +31 -0
- package/dist/errors.js +10 -0
- package/dist/eval-capability-execution-envelope.d.ts +64 -0
- package/dist/eval-capability-execution-envelope.js +98 -0
- package/dist/eval-capability-policy.d.ts +90 -0
- package/dist/eval-capability-policy.js +107 -0
- package/dist/eval-event-log.d.ts +51 -0
- package/dist/eval-event-log.js +69 -10
- package/dist/evaluation-authoring-policy.d.ts +18 -0
- package/dist/evaluation-authoring-policy.js +19 -0
- package/dist/evaluation-authoring-validation.d.ts +22 -0
- package/dist/evaluation-authoring-validation.js +72 -0
- package/dist/evaluation-evidence.d.ts +20 -0
- package/dist/evaluation-evidence.js +319 -0
- package/dist/evaluation-grader-calibration-protocol.d.ts +108 -0
- package/dist/evaluation-grader-calibration-protocol.js +80 -0
- package/dist/evaluation-grader-calibration.d.ts +18 -0
- package/dist/evaluation-grader-calibration.js +334 -0
- package/dist/evaluation-grading-policy.d.ts +24 -0
- package/dist/evaluation-grading-policy.js +54 -0
- package/dist/evaluation-proposal-policy.d.ts +4 -0
- package/dist/evaluation-proposal-policy.js +91 -0
- package/dist/evaluation-source-retrieval.d.ts +68 -0
- package/dist/evaluation-source-retrieval.js +513 -0
- package/dist/evaluation-structure-policy.d.ts +29 -0
- package/dist/evaluation-structure-policy.js +138 -0
- package/dist/index.d.ts +124 -19
- package/dist/index.js +69 -12
- package/dist/inspection.js +2 -3
- package/dist/project-artifacts.d.ts +2 -2
- package/dist/project-artifacts.js +26 -121
- package/dist/project-authoring.d.ts +66 -5
- package/dist/project-authoring.js +783 -109
- package/dist/project-contracts.d.ts +292 -82
- package/dist/project-contracts.js +65 -7
- package/dist/project-store.js +2 -1
- package/dist/project-workflow.d.ts +3 -3
- package/dist/project-workflow.js +116 -18
- package/dist/repository-adversary-protocol.d.ts +64 -0
- package/dist/repository-adversary-protocol.js +105 -0
- package/dist/repository-behavior-protocol.d.ts +188 -0
- package/dist/repository-behavior-protocol.js +202 -0
- package/dist/repository-benchmark-protocol.d.ts +487 -0
- package/dist/repository-benchmark-protocol.js +96 -0
- package/dist/repository-execution-protocol.d.ts +150 -0
- package/dist/repository-execution-protocol.js +38 -0
- package/dist/repository-fixture-instructions.d.ts +3 -0
- package/dist/repository-fixture-instructions.js +91 -0
- package/dist/repository-fixture-protocol.d.ts +79 -0
- package/dist/repository-fixture-protocol.js +79 -0
- package/dist/repository-foundry-plan-protocol.d.ts +118 -0
- package/dist/repository-foundry-plan-protocol.js +296 -0
- package/dist/repository-foundry-progress-protocol.d.ts +52 -0
- package/dist/repository-foundry-progress-protocol.js +52 -0
- package/dist/repository-improvement-protocol.d.ts +100 -0
- package/dist/repository-improvement-protocol.js +106 -0
- package/dist/repository-language-model-protocol.d.ts +43 -0
- package/dist/repository-language-model-protocol.js +146 -0
- package/dist/repository-oracle-coverage-protocol.d.ts +18 -0
- package/dist/repository-oracle-coverage-protocol.js +39 -0
- package/dist/repository-oracle-execution-binding.d.ts +27 -0
- package/dist/repository-oracle-execution-binding.js +59 -0
- package/dist/repository-oracle-protocol.d.ts +230 -0
- package/dist/repository-oracle-protocol.js +156 -0
- package/dist/repository-oracle-scope-policy.d.ts +22 -0
- package/dist/repository-oracle-scope-policy.js +92 -0
- package/dist/repository-quality-policy.d.ts +15 -0
- package/dist/repository-quality-policy.js +357 -0
- package/dist/repository-routing-benchmark-protocol.d.ts +176 -0
- package/dist/repository-routing-benchmark-protocol.js +103 -0
- package/dist/repository-routing-model-protocol.d.ts +36 -0
- package/dist/repository-routing-model-protocol.js +89 -0
- package/dist/repository-routing-plan-protocol.d.ts +112 -0
- package/dist/repository-routing-plan-protocol.js +58 -0
- package/dist/repository-routing-quality-policy.d.ts +9 -0
- package/dist/repository-routing-quality-policy.js +191 -0
- package/dist/repository-seed-qualification-progress-protocol.d.ts +205 -0
- package/dist/repository-seed-qualification-progress-protocol.js +28 -0
- package/dist/repository-semantic-calibration-protocol.d.ts +768 -0
- package/dist/repository-semantic-calibration-protocol.js +276 -0
- package/dist/repository-semantic-calibration.d.ts +163 -0
- package/dist/repository-semantic-calibration.js +581 -0
- package/dist/repository-specification-contract-facts-protocol.d.ts +224 -0
- package/dist/repository-specification-contract-facts-protocol.js +276 -0
- package/dist/repository-specification-critique-protocol.d.ts +189 -0
- package/dist/repository-specification-critique-protocol.js +103 -0
- package/dist/repository-task-family-protocol.d.ts +24 -0
- package/dist/repository-task-family-protocol.js +37 -0
- package/dist/repository-task-seed-protocol.d.ts +384 -0
- package/dist/repository-task-seed-protocol.js +236 -0
- package/dist/repository-trajectory-protocol.d.ts +20 -0
- package/dist/repository-trajectory-protocol.js +42 -0
- package/dist/service.js +1 -1
- package/dist/services/adversary/service.d.ts +64 -0
- package/dist/services/adversary/service.js +330 -0
- package/dist/services/benchmark-compiler/service.d.ts +450 -0
- package/dist/services/benchmark-compiler/service.js +9 -0
- package/dist/services/budgeted-model/service.d.ts +118 -0
- package/dist/services/budgeted-model/service.js +460 -0
- package/dist/services/case-authoring/service.d.ts +163 -0
- package/dist/services/case-authoring/service.js +1456 -0
- package/dist/services/case-finalization/service.d.ts +283 -0
- package/dist/services/case-finalization/service.js +370 -0
- package/dist/services/case-generation/service.d.ts +619 -0
- package/dist/services/case-generation/service.js +2628 -0
- package/dist/services/case-pipeline/service.d.ts +31 -0
- package/dist/services/case-pipeline/service.js +485 -0
- package/dist/services/case-pipeline-v2/service.d.ts +70 -0
- package/dist/services/case-pipeline-v2/service.js +477 -0
- package/dist/services/command-observability/service.d.ts +13 -0
- package/dist/services/command-observability/service.js +3 -0
- package/dist/services/dimension-labeling/service.d.ts +77 -0
- package/dist/services/dimension-labeling/service.js +188 -0
- package/dist/services/eval-candidate/service.d.ts +208 -0
- package/dist/services/eval-candidate/service.js +64 -0
- package/dist/services/eval-capabilities/service.d.ts +183 -0
- package/dist/services/eval-capabilities/service.js +1433 -0
- package/dist/services/eval-environment/service.d.ts +173 -0
- package/dist/services/eval-environment/service.js +127 -0
- package/dist/services/evidence-reconstruction/service.d.ts +36 -0
- package/dist/services/evidence-reconstruction/service.js +145 -0
- package/dist/services/fixture-builder/service.d.ts +62 -0
- package/dist/services/fixture-builder/service.js +36 -0
- package/dist/services/fixture-validation/service.d.ts +75 -0
- package/dist/services/fixture-validation/service.js +295 -0
- package/dist/services/foundry/service.d.ts +831 -0
- package/dist/services/foundry/service.js +442 -0
- package/dist/services/foundry-progress/service.d.ts +62 -0
- package/dist/services/foundry-progress/service.js +149 -0
- package/dist/services/foundry-v2/service.d.ts +54 -0
- package/dist/services/foundry-v2/service.js +28 -0
- package/dist/services/grounded-authoring/service.d.ts +126 -0
- package/dist/services/grounded-authoring/service.js +822 -0
- package/dist/services/historical-case/service.d.ts +722 -0
- package/dist/services/historical-case/service.js +177 -0
- package/dist/services/improvement-loop/service.d.ts +59 -0
- package/dist/services/improvement-loop/service.js +176 -0
- package/dist/services/language-model/service.d.ts +52 -0
- package/dist/services/language-model/service.js +194 -0
- package/dist/services/oracle-builder/service.d.ts +146 -0
- package/dist/services/oracle-builder/service.js +513 -0
- package/dist/services/oracle-coverage/service.d.ts +28 -0
- package/dist/services/oracle-coverage/service.js +50 -0
- package/dist/services/oracle-coverage-witness/service.d.ts +130 -0
- package/dist/services/oracle-coverage-witness/service.js +538 -0
- package/dist/services/pipeline-challenge/service.d.ts +551 -0
- package/dist/services/pipeline-challenge/service.js +427 -0
- package/dist/services/pipeline-controls/service.d.ts +130 -0
- package/dist/services/pipeline-controls/service.js +483 -0
- package/dist/services/pipeline-oracle/service.d.ts +8 -0
- package/dist/services/pipeline-oracle/service.js +256 -0
- package/dist/services/pipeline-seed/service.d.ts +298 -0
- package/dist/services/pipeline-seed/service.js +428 -0
- package/dist/services/pipeline-spec/service.d.ts +103 -0
- package/dist/services/pipeline-spec/service.js +619 -0
- package/dist/services/pipeline-tournament/service.d.ts +258 -0
- package/dist/services/pipeline-tournament/service.js +476 -0
- package/dist/services/quality-gate/service.d.ts +233 -0
- package/dist/services/quality-gate/service.js +136 -0
- package/dist/services/repository-bundle/service.d.ts +33 -0
- package/dist/services/repository-bundle/service.js +114 -0
- package/dist/services/repository-model/service.d.ts +105 -0
- package/dist/services/repository-model/service.js +250 -0
- package/dist/services/repository-public-artifact/service.d.ts +133 -0
- package/dist/services/repository-public-artifact/service.js +330 -0
- package/dist/services/routing-benchmark/service.d.ts +362 -0
- package/dist/services/routing-benchmark/service.js +96 -0
- package/dist/services/specification-critic/service.d.ts +92 -0
- package/dist/services/specification-critic/service.js +172 -0
- package/dist/services/task-family/service.d.ts +40 -0
- package/dist/services/task-family/service.js +55 -0
- package/dist/services/task-seed/service.d.ts +906 -0
- package/dist/services/task-seed/service.js +1406 -0
- package/dist/services/task-specification/service.d.ts +27 -0
- package/dist/services/task-specification/service.js +40 -0
- package/dist/services/trajectory-policy/service.d.ts +110 -0
- package/dist/services/trajectory-policy/service.js +216 -0
- package/dist/test/agentic-capabilities-protocol.test.d.ts +1 -0
- package/dist/test/agentic-capabilities-protocol.test.js +570 -0
- package/dist/test/agentic-capabilities.test.d.ts +1 -0
- package/dist/test/agentic-capabilities.test.js +1461 -0
- package/dist/test/agentic-environment.test.d.ts +1 -0
- package/dist/test/agentic-environment.test.js +213 -0
- package/dist/test/case-pipeline-foundation.test.d.ts +1 -0
- package/dist/test/case-pipeline-foundation.test.js +535 -0
- package/dist/test/case-pipeline-protocol-v2.test.d.ts +1 -0
- package/dist/test/case-pipeline-protocol-v2.test.js +124 -0
- package/dist/test/case-pipeline-v2.test.d.ts +1 -0
- package/dist/test/case-pipeline-v2.test.js +286 -0
- package/dist/test/case-pipeline.test.d.ts +1 -0
- package/dist/test/case-pipeline.test.js +851 -0
- package/dist/test/eval-capability-policy.test.d.ts +1 -0
- package/dist/test/eval-capability-policy.test.js +50 -0
- package/dist/test/eval-event-log.test.js +34 -1
- package/dist/test/evaluation-evidence-freshness.test.d.ts +1 -0
- package/dist/test/evaluation-evidence-freshness.test.js +44 -0
- package/dist/test/evaluation-evidence.test.d.ts +1 -0
- package/dist/test/evaluation-evidence.test.js +230 -0
- package/dist/test/evaluation-grader-calibration.test.d.ts +1 -0
- package/dist/test/evaluation-grader-calibration.test.js +373 -0
- package/dist/test/evaluation-proposal-digest.test.d.ts +1 -0
- package/dist/test/evaluation-proposal-digest.test.js +187 -0
- package/dist/test/evaluation-source-retrieval.test.d.ts +1 -0
- package/dist/test/evaluation-source-retrieval.test.js +237 -0
- package/dist/test/evaluation-structure-policy.test.d.ts +1 -0
- package/dist/test/evaluation-structure-policy.test.js +196 -0
- package/dist/test/fixtures/repository-resource-panel.d.ts +39 -0
- package/dist/test/fixtures/repository-resource-panel.js +111 -0
- package/dist/test/fixtures/vitest-boundary-panel.d.ts +84 -0
- package/dist/test/fixtures/vitest-boundary-panel.js +120 -0
- package/dist/test/fixtures/vitest-phase-panel.d.ts +135 -0
- package/dist/test/fixtures/vitest-phase-panel.js +213 -0
- package/dist/test/fixtures/vitest-reporter-results.d.ts +76 -0
- package/dist/test/fixtures/vitest-reporter-results.js +94 -0
- package/dist/test/grounded-authoring.test.d.ts +1 -0
- package/dist/test/grounded-authoring.test.js +565 -0
- package/dist/test/integrated-repository-history.test.d.ts +1 -0
- package/dist/test/integrated-repository-history.test.js +227 -0
- package/dist/test/project-authoring.test.js +593 -43
- package/dist/test/project-workflow.test.js +395 -32
- package/dist/test/repository-authoring-artifacts.test.d.ts +1 -0
- package/dist/test/repository-authoring-artifacts.test.js +185 -0
- package/dist/test/repository-bundle.test.d.ts +1 -0
- package/dist/test/repository-bundle.test.js +52 -0
- package/dist/test/repository-case-generation.test.d.ts +1 -0
- package/dist/test/repository-case-generation.test.js +3465 -0
- package/dist/test/repository-command-diagnostic.test.d.ts +1 -0
- package/dist/test/repository-command-diagnostic.test.js +55 -0
- package/dist/test/repository-command-signals.test.d.ts +1 -0
- package/dist/test/repository-command-signals.test.js +124 -0
- package/dist/test/repository-fixture-scope-coverage.test.d.ts +1 -0
- package/dist/test/repository-fixture-scope-coverage.test.js +127 -0
- package/dist/test/repository-fixture-validation.test.d.ts +1 -0
- package/dist/test/repository-fixture-validation.test.js +362 -0
- package/dist/test/repository-foundry-progress.test.d.ts +1 -0
- package/dist/test/repository-foundry-progress.test.js +110 -0
- package/dist/test/repository-foundry-quality.test.d.ts +1 -0
- package/dist/test/repository-foundry-quality.test.js +1138 -0
- package/dist/test/repository-import-context.test.d.ts +1 -0
- package/dist/test/repository-import-context.test.js +354 -0
- package/dist/test/repository-model-authoring.test.d.ts +1 -0
- package/dist/test/repository-model-authoring.test.js +544 -0
- package/dist/test/repository-model.test.d.ts +1 -0
- package/dist/test/repository-model.test.js +2195 -0
- package/dist/test/repository-node-test-reporter.test.d.ts +1 -0
- package/dist/test/repository-node-test-reporter.test.js +104 -0
- package/dist/test/repository-oracle-concurrency.test.d.ts +1 -0
- package/dist/test/repository-oracle-concurrency.test.js +542 -0
- package/dist/test/repository-oracle-coverage-witness.test.d.ts +1 -0
- package/dist/test/repository-oracle-coverage-witness.test.js +511 -0
- package/dist/test/repository-oracle-coverage.test.d.ts +1 -0
- package/dist/test/repository-oracle-coverage.test.js +168 -0
- package/dist/test/repository-oracle-evidence.test.d.ts +1 -0
- package/dist/test/repository-oracle-evidence.test.js +185 -0
- package/dist/test/repository-oracle-plan.test.d.ts +1 -0
- package/dist/test/repository-oracle-plan.test.js +176 -0
- package/dist/test/repository-overlay-isolation.test.d.ts +1 -0
- package/dist/test/repository-overlay-isolation.test.js +85 -0
- package/dist/test/repository-preparation-cache.test.d.ts +1 -0
- package/dist/test/repository-preparation-cache.test.js +414 -0
- package/dist/test/repository-public-artifact.test.d.ts +1 -0
- package/dist/test/repository-public-artifact.test.js +273 -0
- package/dist/test/repository-qualification-diagnostics.test.d.ts +1 -0
- package/dist/test/repository-qualification-diagnostics.test.js +524 -0
- package/dist/test/repository-reference-authoring.test.d.ts +1 -0
- package/dist/test/repository-reference-authoring.test.js +1633 -0
- package/dist/test/repository-review-evidence-v2.test.d.ts +1 -0
- package/dist/test/repository-review-evidence-v2.test.js +183 -0
- package/dist/test/repository-review-evidence.test.d.ts +1 -0
- package/dist/test/repository-review-evidence.test.js +124 -0
- package/dist/test/repository-seed-exclusions.test.d.ts +1 -0
- package/dist/test/repository-seed-exclusions.test.js +96 -0
- package/dist/test/repository-seed-selection.test.d.ts +1 -0
- package/dist/test/repository-seed-selection.test.js +504 -0
- package/dist/test/repository-semantic-calibration.test.d.ts +1 -0
- package/dist/test/repository-semantic-calibration.test.js +688 -0
- package/dist/test/repository-solution-edits.test.d.ts +1 -0
- package/dist/test/repository-solution-edits.test.js +377 -0
- package/dist/test/repository-specification-budget.test.d.ts +1 -0
- package/dist/test/repository-specification-budget.test.js +171 -0
- package/dist/test/repository-specification-contract-checkpoint.test.d.ts +1 -0
- package/dist/test/repository-specification-contract-checkpoint.test.js +228 -0
- package/dist/test/repository-specification-contract-facts.test.d.ts +1 -0
- package/dist/test/repository-specification-contract-facts.test.js +177 -0
- package/dist/test/repository-trajectory-authoring.test.d.ts +1 -0
- package/dist/test/repository-trajectory-authoring.test.js +176 -0
- package/dist/test/repository-valid-control-plan.test.d.ts +1 -0
- package/dist/test/repository-valid-control-plan.test.js +45 -0
- package/dist/test/repository-vitest-phase.test.d.ts +1 -0
- package/dist/test/repository-vitest-phase.test.js +848 -0
- package/dist/test/repository-vitest-reporter.test.d.ts +1 -0
- package/dist/test/repository-vitest-reporter.test.js +158 -0
- package/dist/test/repository-workspace-build.test.d.ts +1 -0
- package/dist/test/repository-workspace-build.test.js +160 -0
- package/dist/test/strict-authoring-schema.test.d.ts +1 -0
- package/dist/test/strict-authoring-schema.test.js +169 -0
- package/package.json +48 -7
|
@@ -7,6 +7,8 @@ import { layer as NodeServicesLayer } from "@effect/platform-node/NodeServices";
|
|
|
7
7
|
import { CostServiceLive, makeCostService } from "@velum-labs/routekit-registry";
|
|
8
8
|
import { Cause, Effect, Layer } from "effect";
|
|
9
9
|
import { EvalDimensionContrastError, EvalModelCatalogError } from "../errors.js";
|
|
10
|
+
import { compileEvaluationEvidence, renderEvaluationEvidenceContext } from "../evaluation-evidence.js";
|
|
11
|
+
import { renderEvaluationCriteria } from "../evaluation-structure-policy.js";
|
|
10
12
|
import { EvalRepositoryInspectorLive } from "../inspection.js";
|
|
11
13
|
import { EvalProjectArtifactsLive } from "../project-artifacts.js";
|
|
12
14
|
import { estimateEvalPlanCost, scopedExpectedCalls, summarizeEvalRunLedger } from "../project-contracts.js";
|
|
@@ -35,7 +37,7 @@ const makeRepository = async () => {
|
|
|
35
37
|
const root = await mkdtemp(path.join(os.tmpdir(), "routekit-eval-project-"));
|
|
36
38
|
roots.push(root);
|
|
37
39
|
await mkdir(path.join(root, "src"), { recursive: true });
|
|
38
|
-
await writeFile(path.join(root, "README.md"), "# Example application\n");
|
|
40
|
+
await writeFile(path.join(root, "README.md"), "# Example application\n\nA terminal event must be last; later output is invalid and unsupported.\n");
|
|
39
41
|
await writeFile(path.join(root, "src", "model.ts"), 'client.responses.create({ model: "openai/current" });\n');
|
|
40
42
|
return root;
|
|
41
43
|
};
|
|
@@ -205,15 +207,89 @@ const reviewedProposedDimensions = reviewedDimensions.map((dimension, index) =>
|
|
|
205
207
|
inScopeRequest: `Solve an in-scope request for dimension ${String(index + 1)}.`,
|
|
206
208
|
nearMissRequest: `Solve a neighboring request outside dimension ${String(index + 1)}.`
|
|
207
209
|
}));
|
|
210
|
+
const reviewedPrompt = (dimensionId, index) => {
|
|
211
|
+
switch (index % 5) {
|
|
212
|
+
case 0:
|
|
213
|
+
return `Transform raw ${dimensionId} capture ${String(index + 1)}`;
|
|
214
|
+
case 1:
|
|
215
|
+
return `Locate the fault in ${dimensionId} trace ${String(index + 1)}`;
|
|
216
|
+
case 2:
|
|
217
|
+
return `Construct the ${dimensionId} artifact for sample ${String(index + 1)}`;
|
|
218
|
+
case 3:
|
|
219
|
+
return `Analyze the ${dimensionId} boundary sample ${String(index + 1)}`;
|
|
220
|
+
default:
|
|
221
|
+
return `Explain the ${dimensionId} operational result ${String(index + 1)}`;
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const reviewedEvidenceSources = compileEvaluationEvidence({
|
|
225
|
+
sources: [
|
|
226
|
+
{
|
|
227
|
+
path: "README.md",
|
|
228
|
+
content: "# Example application\n\nA terminal event must be last; later output is invalid and unsupported.\n"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
path: "src/model.ts",
|
|
232
|
+
content: 'client.responses.create({ model: "openai/current" });\n'
|
|
233
|
+
}
|
|
234
|
+
],
|
|
235
|
+
maximumBlockBytes: 3_000
|
|
236
|
+
});
|
|
237
|
+
const reviewedEvidenceBlock = reviewedEvidenceSources[0].blocks[0];
|
|
238
|
+
const reviewedCompiledFields = (caseId, index) => {
|
|
239
|
+
const criterionId = `${caseId}-criterion`;
|
|
240
|
+
const criteria = [
|
|
241
|
+
{
|
|
242
|
+
id: criterionId,
|
|
243
|
+
description: `Derive the observable repository behavior for case ${String(index + 1)}.`,
|
|
244
|
+
importance: "critical",
|
|
245
|
+
gradingMode: "semantic"
|
|
246
|
+
}
|
|
247
|
+
];
|
|
248
|
+
return {
|
|
249
|
+
context: renderEvaluationEvidenceContext([reviewedEvidenceBlock]),
|
|
250
|
+
rubric: renderEvaluationCriteria(criteria),
|
|
251
|
+
evidenceIds: [reviewedEvidenceBlock.id],
|
|
252
|
+
criteria,
|
|
253
|
+
positiveControls: [
|
|
254
|
+
{
|
|
255
|
+
id: `${caseId}-positive`,
|
|
256
|
+
response: `The response derives the repository-backed behavior for case ${String(index + 1)}.`
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
negativeControls: [
|
|
260
|
+
{
|
|
261
|
+
id: `${caseId}-missing`,
|
|
262
|
+
response: "The response discusses the topic but omits the required behavior.",
|
|
263
|
+
targetedCriterionIds: [criterionId],
|
|
264
|
+
kind: "missing-criterion"
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
id: `${caseId}-forbidden`,
|
|
268
|
+
response: "The response invents behavior contradicted by the repository evidence.",
|
|
269
|
+
targetedCriterionIds: [criterionId],
|
|
270
|
+
kind: "forbidden-behavior"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
id: `${caseId}-non-responsive`,
|
|
274
|
+
response: "This is a polished overview that never answers the concrete request.",
|
|
275
|
+
targetedCriterionIds: [criterionId],
|
|
276
|
+
kind: "non-responsive"
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
};
|
|
280
|
+
};
|
|
208
281
|
const reviewedSuites = reviewedDimensions.map((dimension) => ({
|
|
209
282
|
version: 1,
|
|
210
283
|
dimensionId: dimension.id,
|
|
211
284
|
maximumOutputTokens: 256,
|
|
212
|
-
cases: Array.from({ length: 20 }, (_, index) =>
|
|
213
|
-
id
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
285
|
+
cases: Array.from({ length: 20 }, (_, index) => {
|
|
286
|
+
const id = `${dimension.id}-case-${String(index + 1)}`;
|
|
287
|
+
return {
|
|
288
|
+
id,
|
|
289
|
+
prompt: reviewedPrompt(dimension.id, index),
|
|
290
|
+
...reviewedCompiledFields(id, index)
|
|
291
|
+
};
|
|
292
|
+
})
|
|
217
293
|
}));
|
|
218
294
|
const reviewedDecompositionBenchmark = {
|
|
219
295
|
maximumVectorL1Error: 0.3,
|
|
@@ -233,32 +309,53 @@ const reviewedCompositionSuite = {
|
|
|
233
309
|
maximumOutputTokens: 256,
|
|
234
310
|
minimumWinnerScoreGap: 0.05,
|
|
235
311
|
minimumWinnerAgreement: 0.8,
|
|
236
|
-
cases: Array.from({ length: 20 }, (_, index) =>
|
|
237
|
-
id
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
312
|
+
cases: Array.from({ length: 20 }, (_, index) => {
|
|
313
|
+
const id = `composition-case-${String(index + 1)}`;
|
|
314
|
+
return {
|
|
315
|
+
id,
|
|
316
|
+
prompt: reviewedPrompt("multi-dimension", index),
|
|
317
|
+
...reviewedCompiledFields(id, index),
|
|
318
|
+
decomposition: {
|
|
319
|
+
weights: reviewedDimensions.map((dimension, dimensionIndex) => ({
|
|
320
|
+
dimensionId: dimension.id,
|
|
321
|
+
weight: dimensionIndex === index % reviewedDimensions.length ||
|
|
322
|
+
dimensionIndex === (index + 1) % reviewedDimensions.length
|
|
323
|
+
? 0.5
|
|
324
|
+
: 0
|
|
325
|
+
})),
|
|
326
|
+
unknownWeight: 0
|
|
327
|
+
},
|
|
328
|
+
requirements: {
|
|
329
|
+
endpoint: "responses",
|
|
330
|
+
requiresTools: false,
|
|
331
|
+
requiresVision: false
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
})
|
|
256
335
|
};
|
|
257
336
|
const reviewedEvaluationInput = {
|
|
337
|
+
evidenceSources: reviewedEvidenceSources,
|
|
258
338
|
suites: reviewedSuites,
|
|
259
339
|
decompositionBenchmark: reviewedDecompositionBenchmark,
|
|
260
340
|
compositionSuite: reviewedCompositionSuite
|
|
261
341
|
};
|
|
342
|
+
const flashcardEvaluationInput = {
|
|
343
|
+
...reviewedEvaluationInput,
|
|
344
|
+
suites: reviewedSuites.map((suite) => ({
|
|
345
|
+
...suite,
|
|
346
|
+
cases: Array.from({ length: 20 }, (_, index) => {
|
|
347
|
+
const scenario = Math.floor(index / 2);
|
|
348
|
+
return {
|
|
349
|
+
id: `${suite.dimensionId}-flashcard-${String(index + 1)}`,
|
|
350
|
+
prompt: index % 2 === 0
|
|
351
|
+
? "Diagnose the described RouteKit behavior. Use only the supplied context."
|
|
352
|
+
: "Give a concise verification criterion. Use only the supplied context.",
|
|
353
|
+
context: `Captured scenario ${String(scenario + 1)} emitted output after completion. The terminal event must be last.`,
|
|
354
|
+
rubric: "Reject post-terminal output and require completion to be the final event."
|
|
355
|
+
};
|
|
356
|
+
})
|
|
357
|
+
}))
|
|
358
|
+
};
|
|
262
359
|
async function completeProjectSetup(root, candidateModels = "openai/gpt-5.6-luna openai/gpt-5.6-terra openai/gpt-5.6-sol") {
|
|
263
360
|
await Effect.runPromise(Effect.gen(function* () {
|
|
264
361
|
const workflow = yield* EvalProjectWorkflow;
|
|
@@ -388,15 +485,36 @@ test("reviewed artifacts are digest-bound and produce an immutable exact-call pl
|
|
|
388
485
|
assert.deepEqual(JSON.parse(await readFile(planPath, "utf8")), result.plan);
|
|
389
486
|
const firstDimension = reviewedDimensions[0];
|
|
390
487
|
const generatedSuite = await readFile(path.join(root, ".routekit", "evals", "plans", result.plan.planId, "dimensions", firstDimension.id, `${firstDimension.id}.eval.ts`), "utf8");
|
|
488
|
+
const candidateCases = JSON.parse(await readFile(path.join(root, ".routekit", "evals", "plans", result.plan.planId, "dimensions", firstDimension.id, "data", "candidate-cases.json"), "utf8"));
|
|
489
|
+
const hiddenOracles = JSON.parse(await readFile(path.join(root, ".routekit", "evals", "plans", result.plan.planId, "dimensions", firstDimension.id, "data", "hidden-oracles.json"), "utf8"));
|
|
391
490
|
const completionAssertion = generatedSuite.indexOf("run.toComplete();");
|
|
491
|
+
const oracleLookup = generatedSuite.indexOf("hiddenOracleById.get(candidateCase.id)");
|
|
392
492
|
const judgeCall = generatedSuite.indexOf("await judge.autoEvals");
|
|
393
493
|
const completionRethrow = generatedSuite.indexOf("throw candidateCompletionError;");
|
|
394
494
|
const judgeRethrow = generatedSuite.indexOf("throw judgeError;");
|
|
395
495
|
assert.match(generatedSuite, /emit the complete target-protocol envelope and terminal event/u);
|
|
396
496
|
assert.match(generatedSuite, /include the concrete output rather than only describing it/u);
|
|
497
|
+
assert.match(generatedSuite, /You are a strict evaluator for AI agent outputs\./u);
|
|
498
|
+
assert.deepEqual(Object.keys(candidateCases[0]).sort(), [
|
|
499
|
+
"context",
|
|
500
|
+
"id",
|
|
501
|
+
"prompt"
|
|
502
|
+
]);
|
|
503
|
+
assert.equal(Object.hasOwn(candidateCases[0], "rubric"), false);
|
|
504
|
+
assert.equal(Object.hasOwn(candidateCases[0], "criteria"), false);
|
|
505
|
+
assert.deepEqual(Object.keys(hiddenOracles[0]).sort(), [
|
|
506
|
+
"criteria",
|
|
507
|
+
"id",
|
|
508
|
+
"negativeControls",
|
|
509
|
+
"positiveControls",
|
|
510
|
+
"rubric"
|
|
511
|
+
]);
|
|
512
|
+
assert.equal(candidateCases[0].id, hiddenOracles[0].id);
|
|
397
513
|
assert.ok(judgeCall >= 0);
|
|
514
|
+
assert.ok(oracleLookup >= 0);
|
|
398
515
|
assert.ok(completionAssertion >= 0);
|
|
399
|
-
assert.ok(completionAssertion <
|
|
516
|
+
assert.ok(completionAssertion < oracleLookup);
|
|
517
|
+
assert.ok(oracleLookup < judgeCall);
|
|
400
518
|
assert.ok(judgeCall < completionRethrow);
|
|
401
519
|
assert.ok(completionRethrow < judgeRethrow);
|
|
402
520
|
for (const dimension of reviewedDimensions) {
|
|
@@ -404,6 +522,95 @@ test("reviewed artifacts are digest-bound and produce an immutable exact-call pl
|
|
|
404
522
|
.mode & 0o777, 0o600);
|
|
405
523
|
}
|
|
406
524
|
});
|
|
525
|
+
test("evaluation approval rejects historical cases without compiler provenance", async () => {
|
|
526
|
+
const root = await makeRepository();
|
|
527
|
+
await completeProjectSetup(root);
|
|
528
|
+
const exit = await Effect.runPromise(Effect.gen(function* () {
|
|
529
|
+
const workflow = yield* EvalProjectWorkflow;
|
|
530
|
+
const proposedBasis = yield* workflow.proposeDimensions(root, reviewedProposedDimensions);
|
|
531
|
+
yield* workflow.approveDimensions(root, proposedBasis.artifacts.basisProposalDigest);
|
|
532
|
+
const proposed = yield* workflow.proposeEvaluations(root, flashcardEvaluationInput);
|
|
533
|
+
return yield* Effect.exit(workflow.approveEvaluations(root, proposed.artifacts.evaluationProposalDigest));
|
|
534
|
+
}).pipe(Effect.provide(ProjectWorkflowTestLive)));
|
|
535
|
+
assert.equal(exit._tag, "Failure");
|
|
536
|
+
if (exit._tag === "Failure") {
|
|
537
|
+
const error = Cause.squash(exit.cause);
|
|
538
|
+
assert.match(String(error), /is not compiler-backed/u);
|
|
539
|
+
}
|
|
540
|
+
const approvalPath = path.join(root, ".routekit", "evals", "evaluations.approved.json");
|
|
541
|
+
await assert.rejects(stat(approvalPath), /ENOENT/u);
|
|
542
|
+
});
|
|
543
|
+
test("repository evidence changes stale approval before approval and planning", async () => {
|
|
544
|
+
const beforeApprovalRoot = await makeRepository();
|
|
545
|
+
await completeProjectSetup(beforeApprovalRoot);
|
|
546
|
+
const beforeApproval = await Effect.runPromise(Effect.gen(function* () {
|
|
547
|
+
const workflow = yield* EvalProjectWorkflow;
|
|
548
|
+
const proposedBasis = yield* workflow.proposeDimensions(beforeApprovalRoot, reviewedProposedDimensions);
|
|
549
|
+
yield* workflow.approveDimensions(beforeApprovalRoot, proposedBasis.artifacts.basisProposalDigest);
|
|
550
|
+
const proposed = yield* workflow.proposeEvaluations(beforeApprovalRoot, reviewedEvaluationInput);
|
|
551
|
+
return proposed.artifacts.evaluationProposalDigest;
|
|
552
|
+
}).pipe(Effect.provide(ProjectWorkflowTestLive)));
|
|
553
|
+
await writeFile(path.join(beforeApprovalRoot, "README.md"), "# Example application\n\nChanged after authoring.\n");
|
|
554
|
+
const approvalExit = await Effect.runPromise(Effect.gen(function* () {
|
|
555
|
+
const workflow = yield* EvalProjectWorkflow;
|
|
556
|
+
return yield* Effect.exit(workflow.approveEvaluations(beforeApprovalRoot, beforeApproval));
|
|
557
|
+
}).pipe(Effect.provide(ProjectWorkflowTestLive)));
|
|
558
|
+
assert.equal(approvalExit._tag, "Failure");
|
|
559
|
+
if (approvalExit._tag === "Failure") {
|
|
560
|
+
assert.match(String(Cause.squash(approvalExit.cause)), /evidence source changed after authoring/u);
|
|
561
|
+
}
|
|
562
|
+
const beforePlanRoot = await makeRepository();
|
|
563
|
+
await completeProjectSetup(beforePlanRoot);
|
|
564
|
+
await Effect.runPromise(Effect.gen(function* () {
|
|
565
|
+
const workflow = yield* EvalProjectWorkflow;
|
|
566
|
+
const proposedBasis = yield* workflow.proposeDimensions(beforePlanRoot, reviewedProposedDimensions);
|
|
567
|
+
yield* workflow.approveDimensions(beforePlanRoot, proposedBasis.artifacts.basisProposalDigest);
|
|
568
|
+
const proposed = yield* workflow.proposeEvaluations(beforePlanRoot, reviewedEvaluationInput);
|
|
569
|
+
yield* workflow.approveEvaluations(beforePlanRoot, proposed.artifacts.evaluationProposalDigest);
|
|
570
|
+
}).pipe(Effect.provide(ProjectWorkflowTestLive)));
|
|
571
|
+
await writeFile(path.join(beforePlanRoot, "README.md"), "# Example application\n\nChanged before planning.\n");
|
|
572
|
+
const stale = await Effect.runPromise(Effect.gen(function* () {
|
|
573
|
+
const workflow = yield* EvalProjectWorkflow;
|
|
574
|
+
const status = yield* workflow.status(beforePlanRoot);
|
|
575
|
+
const planExit = yield* Effect.exit(workflow.createPlan(beforePlanRoot, "pilot"));
|
|
576
|
+
return { status, planExit };
|
|
577
|
+
}).pipe(Effect.provide(ProjectWorkflowTestLive)));
|
|
578
|
+
assert.equal(stale.status?.artifacts?.evaluationsApproved, false);
|
|
579
|
+
assert.equal(stale.status?.nextAction, "approve-evaluations");
|
|
580
|
+
assert.equal(stale.planExit._tag, "Failure");
|
|
581
|
+
if (stale.planExit._tag === "Failure") {
|
|
582
|
+
assert.match(String(stale.planExit.cause), /evidence source changed after authoring/u);
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
test("ready projects can explicitly rebind stale evaluation approvals", async () => {
|
|
586
|
+
const root = await makeRepository();
|
|
587
|
+
await completeProjectSetup(root);
|
|
588
|
+
const rebound = await Effect.runPromise(Effect.gen(function* () {
|
|
589
|
+
const workflow = yield* EvalProjectWorkflow;
|
|
590
|
+
const proposedBasis = yield* workflow.proposeDimensions(root, reviewedProposedDimensions);
|
|
591
|
+
yield* workflow.approveDimensions(root, proposedBasis.artifacts.basisProposalDigest);
|
|
592
|
+
const proposed = yield* workflow.proposeEvaluations(root, reviewedEvaluationInput);
|
|
593
|
+
const digest = proposed.artifacts.evaluationProposalDigest;
|
|
594
|
+
const ready = yield* workflow.approveEvaluations(root, digest);
|
|
595
|
+
yield* Effect.promise(() => writeFile(path.join(root, ".routekit", "evals", "evaluations.approval.json"), `${JSON.stringify({
|
|
596
|
+
version: 1,
|
|
597
|
+
kind: "evaluations",
|
|
598
|
+
digest,
|
|
599
|
+
approvedAt: "2026-08-30T00:00:00.000Z"
|
|
600
|
+
})}\n`, { mode: 0o600 }));
|
|
601
|
+
const stale = yield* workflow.status(root);
|
|
602
|
+
const reboundStatus = yield* workflow.approveEvaluations(root, digest);
|
|
603
|
+
return { ready, stale, reboundStatus };
|
|
604
|
+
}).pipe(Effect.provide(ProjectWorkflowTestLive)));
|
|
605
|
+
assert.equal(rebound.ready.state.stage, "ready");
|
|
606
|
+
assert.ok(rebound.stale !== undefined);
|
|
607
|
+
assert.equal(rebound.stale.state.stage, "ready");
|
|
608
|
+
assert.equal(rebound.stale.artifacts?.evaluationsApproved, false);
|
|
609
|
+
assert.equal(rebound.stale.nextAction, "approve-evaluations");
|
|
610
|
+
assert.equal(rebound.reboundStatus.state.stage, "ready");
|
|
611
|
+
assert.equal(rebound.reboundStatus.artifacts?.evaluationsApproved, true);
|
|
612
|
+
assert.equal(rebound.reboundStatus.nextAction, "run");
|
|
613
|
+
});
|
|
407
614
|
test("full qualification refuses fewer than twenty reviewed cases per dimension", async () => {
|
|
408
615
|
const root = await makeRepository();
|
|
409
616
|
await completeProjectSetup(root);
|
|
@@ -412,6 +619,7 @@ test("full qualification refuses fewer than twenty reviewed cases per dimension"
|
|
|
412
619
|
const proposed = yield* workflow.proposeDimensions(root, reviewedProposedDimensions);
|
|
413
620
|
yield* workflow.approveDimensions(root, proposed.artifacts.basisProposalDigest);
|
|
414
621
|
const evaluations = yield* workflow.proposeEvaluations(root, {
|
|
622
|
+
evidenceSources: reviewedEvidenceSources,
|
|
415
623
|
suites: reviewedSuites.map((suite) => ({ ...suite, cases: suite.cases.slice(0, 5) })),
|
|
416
624
|
decompositionBenchmark: {
|
|
417
625
|
...reviewedDecompositionBenchmark,
|
|
@@ -564,18 +772,25 @@ const qualifiedReport = (plan, runId, projectId, publishAllowed = true) => {
|
|
|
564
772
|
expectedCases: plan.selectedCompositionCaseIds.length,
|
|
565
773
|
comparableCases: plan.selectedCompositionCaseIds.length,
|
|
566
774
|
agreeingCases: plan.selectedCompositionCaseIds.length,
|
|
567
|
-
|
|
775
|
+
...(plan.selectedCompositionCaseIds.length === 0
|
|
776
|
+
? {}
|
|
777
|
+
: { winnerAgreement: 1 }),
|
|
778
|
+
conclusion: plan.selectedCompositionCaseIds.length === 0 ? "inconclusive" : "passed",
|
|
779
|
+
publishable: plan.scope === "full" && plan.selectedCompositionCaseIds.length > 0,
|
|
568
780
|
cases: plan.selectedCompositionCaseIds.map((caseId) => ({
|
|
569
781
|
caseId,
|
|
570
782
|
predictedWinner: candidateModels[0],
|
|
783
|
+
predictedTiedModels: [],
|
|
571
784
|
observedWinner: candidateModels[0],
|
|
785
|
+
observedTiedModels: [],
|
|
572
786
|
predictedScoreGap: 0.1,
|
|
573
787
|
observedScoreGap: 0.2,
|
|
788
|
+
comparable: true,
|
|
574
789
|
passed: true
|
|
575
790
|
}))
|
|
576
791
|
}
|
|
577
792
|
},
|
|
578
|
-
ledger: Effect.runSync(summarizeEvalRunLedger(comparisons, plan.expectedCallCount, testCostService, observations)),
|
|
793
|
+
ledger: Effect.runSync(summarizeEvalRunLedger(comparisons, plan.expectedCallCount, testCostService, observations, plan.classifierModel)),
|
|
579
794
|
activation: {
|
|
580
795
|
version: 2,
|
|
581
796
|
generatedAt: "2026-08-18T00:02:00.000Z",
|
|
@@ -599,7 +814,8 @@ const qualifiedReport = (plan, runId, projectId, publishAllowed = true) => {
|
|
|
599
814
|
failureRate: 0,
|
|
600
815
|
averageJudgeScore: 0.9,
|
|
601
816
|
p95DurationMs: 250,
|
|
602
|
-
|
|
817
|
+
averageCostUsd: 0.01,
|
|
818
|
+
unpricedCalls: 0
|
|
603
819
|
})))
|
|
604
820
|
}
|
|
605
821
|
};
|
|
@@ -633,7 +849,7 @@ test("run lifecycle retains complete sanitized evidence and activates only after
|
|
|
633
849
|
assert.equal(outcome.loaded?.status, "passed");
|
|
634
850
|
assert.equal(outcome.loaded?.ledger.observedCalls, 740);
|
|
635
851
|
assert.equal(outcome.loaded?.ledger.observedCandidateRows, 360);
|
|
636
|
-
assert.equal(outcome.loaded?.ledger.unpricedCalls,
|
|
852
|
+
assert.equal(outcome.loaded?.ledger.unpricedCalls, 0);
|
|
637
853
|
assert.equal(outcome.activated.state.stage, "activated");
|
|
638
854
|
const reportPath = path.join(root, ".routekit", "evals", "runs", outcome.started.runId, "report.json");
|
|
639
855
|
assert.equal((await stat(reportPath)).mode & 0o777, 0o600);
|
|
@@ -695,6 +911,98 @@ test("finishRun derives ledger expectations from the selected case slice", async
|
|
|
695
911
|
assert.equal(outcome.report.ledger.observedCalls, 4);
|
|
696
912
|
assert.equal(outcome.report.ledger.observedCandidateRows, 2);
|
|
697
913
|
});
|
|
914
|
+
test("zero-comparable pilot persists a completed inconclusive diagnostic", async () => {
|
|
915
|
+
const root = await makeRepository();
|
|
916
|
+
const plan = await createPlan(root, "pilot");
|
|
917
|
+
const outcome = await Effect.runPromise(Effect.gen(function* () {
|
|
918
|
+
const workflow = yield* EvalProjectWorkflow;
|
|
919
|
+
const started = yield* workflow.startRun(root, plan.planId);
|
|
920
|
+
const status = yield* workflow.status(root);
|
|
921
|
+
const passing = qualifiedReport(plan, started.runId, status.state.projectId);
|
|
922
|
+
assert.equal(passing.status, "passed");
|
|
923
|
+
if (passing.status !== "passed")
|
|
924
|
+
return undefined;
|
|
925
|
+
const report = {
|
|
926
|
+
...passing,
|
|
927
|
+
status: "completed",
|
|
928
|
+
qualification: {
|
|
929
|
+
...passing.qualification,
|
|
930
|
+
composition: {
|
|
931
|
+
expectedCases: plan.selectedCompositionCaseIds.length,
|
|
932
|
+
comparableCases: 0,
|
|
933
|
+
agreeingCases: 0,
|
|
934
|
+
conclusion: "inconclusive",
|
|
935
|
+
reason: "insufficient top-two separation",
|
|
936
|
+
publishable: false,
|
|
937
|
+
cases: plan.selectedCompositionCaseIds.map((caseId) => ({
|
|
938
|
+
caseId,
|
|
939
|
+
predictedWinner: null,
|
|
940
|
+
predictedTiedModels: [...plan.candidateModels],
|
|
941
|
+
observedWinner: null,
|
|
942
|
+
observedTiedModels: [...plan.candidateModels],
|
|
943
|
+
predictedScoreGap: 0,
|
|
944
|
+
observedScoreGap: 0,
|
|
945
|
+
comparable: false,
|
|
946
|
+
passed: false
|
|
947
|
+
}))
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
};
|
|
951
|
+
const finished = yield* workflow.finishRun(root, report);
|
|
952
|
+
const persisted = yield* workflow.result(root, started.runId);
|
|
953
|
+
return { finished, persisted };
|
|
954
|
+
}).pipe(Effect.provide(ProjectWorkflowTestLive)));
|
|
955
|
+
assert.equal(outcome?.finished.state.stage, "ready");
|
|
956
|
+
assert.equal(outcome?.persisted?.status, "completed");
|
|
957
|
+
assert.equal(outcome?.persisted?.qualification?.composition.expectedCases, 5);
|
|
958
|
+
assert.equal(outcome?.persisted?.qualification?.composition.comparableCases, 0);
|
|
959
|
+
assert.equal(outcome?.persisted?.qualification?.composition.winnerAgreement, undefined);
|
|
960
|
+
assert.equal(outcome?.persisted?.qualification?.composition.conclusion, "inconclusive");
|
|
961
|
+
assert.equal(outcome?.persisted?.qualification?.composition.publishable, false);
|
|
962
|
+
});
|
|
963
|
+
test("zero-comparable full qualification remains fail closed and unpublished", async () => {
|
|
964
|
+
const root = await makeRepository();
|
|
965
|
+
const plan = await createPlan(root, "full");
|
|
966
|
+
const outcome = await Effect.runPromise(Effect.gen(function* () {
|
|
967
|
+
const workflow = yield* EvalProjectWorkflow;
|
|
968
|
+
const started = yield* workflow.startRun(root, plan.planId);
|
|
969
|
+
const status = yield* workflow.status(root);
|
|
970
|
+
const passing = qualifiedReport(plan, started.runId, status.state.projectId);
|
|
971
|
+
assert.equal(passing.status, "passed");
|
|
972
|
+
if (passing.status !== "passed")
|
|
973
|
+
return undefined;
|
|
974
|
+
const report = {
|
|
975
|
+
...passing,
|
|
976
|
+
qualification: {
|
|
977
|
+
...passing.qualification,
|
|
978
|
+
composition: {
|
|
979
|
+
expectedCases: plan.selectedCompositionCaseIds.length,
|
|
980
|
+
comparableCases: 0,
|
|
981
|
+
agreeingCases: 0,
|
|
982
|
+
conclusion: "inconclusive",
|
|
983
|
+
reason: "insufficient top-two separation",
|
|
984
|
+
publishable: false,
|
|
985
|
+
cases: plan.selectedCompositionCaseIds.map((caseId) => ({
|
|
986
|
+
caseId,
|
|
987
|
+
predictedWinner: null,
|
|
988
|
+
predictedTiedModels: [...plan.candidateModels],
|
|
989
|
+
observedWinner: null,
|
|
990
|
+
observedTiedModels: [...plan.candidateModels],
|
|
991
|
+
predictedScoreGap: 0,
|
|
992
|
+
observedScoreGap: 0,
|
|
993
|
+
comparable: false,
|
|
994
|
+
passed: false
|
|
995
|
+
}))
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
const finished = yield* Effect.exit(workflow.finishRun(root, report));
|
|
1000
|
+
const current = yield* workflow.status(root);
|
|
1001
|
+
return { finished, current };
|
|
1002
|
+
}).pipe(Effect.provide(ProjectWorkflowTestLive)));
|
|
1003
|
+
assert.equal(outcome?.finished._tag, "Failure");
|
|
1004
|
+
assert.equal(outcome?.current?.state.stage, "running");
|
|
1005
|
+
});
|
|
698
1006
|
test("failed runs preserve plan revisions for retry while mismatched plans remain stale", async () => {
|
|
699
1007
|
const root = await makeRepository();
|
|
700
1008
|
const plan = await createPlan(root, "full");
|
|
@@ -755,6 +1063,33 @@ test("failed runs preserve plan revisions for retry while mismatched plans remai
|
|
|
755
1063
|
unpricedCalls: 0,
|
|
756
1064
|
subscriptionUnitCalls: 0
|
|
757
1065
|
},
|
|
1066
|
+
events: [
|
|
1067
|
+
{
|
|
1068
|
+
name: "plan",
|
|
1069
|
+
at: "2026-08-21T03:47:27.000Z",
|
|
1070
|
+
runId: first.runId,
|
|
1071
|
+
plannedCalls: plan.expectedCallCount
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
name: "failure-detail",
|
|
1075
|
+
at: "2026-08-21T03:47:48.000Z",
|
|
1076
|
+
runId: first.runId,
|
|
1077
|
+
phase: "target",
|
|
1078
|
+
reason: "qualification timed out before observing any calls",
|
|
1079
|
+
retryable: true,
|
|
1080
|
+
accounting: {
|
|
1081
|
+
expectedCalls: plan.expectedCallCount,
|
|
1082
|
+
observedCalls: 0,
|
|
1083
|
+
knownInputTokens: 0,
|
|
1084
|
+
knownOutputTokens: 0,
|
|
1085
|
+
unknownTokenMeasurements: 0,
|
|
1086
|
+
knownPricedSubtotalUsd: 0,
|
|
1087
|
+
unpricedCalls: 0,
|
|
1088
|
+
subscriptionUnitCalls: 0
|
|
1089
|
+
},
|
|
1090
|
+
cleanup: { sessionOpened: true, sessionClosed: true }
|
|
1091
|
+
}
|
|
1092
|
+
],
|
|
758
1093
|
failure: "qualification timed out before observing any calls",
|
|
759
1094
|
errors: []
|
|
760
1095
|
});
|
|
@@ -779,7 +1114,7 @@ test("startRun rematerializes stale dimension and composition suite templates",
|
|
|
779
1114
|
const dimensionManifestPath = path.join(dimensionRoot, "routekit.eval-manifest.json");
|
|
780
1115
|
const compositionManifestPath = path.join(compositionRoot, "routekit.eval-manifest.json");
|
|
781
1116
|
const staleTemplate = `// generated by RouteKit 1.0.21
|
|
782
|
-
await judge.autoEvals({ criteria:
|
|
1117
|
+
await judge.autoEvals({ criteria: mixedCase.rubric, prompt, run });
|
|
783
1118
|
run.toComplete();
|
|
784
1119
|
`;
|
|
785
1120
|
await Promise.all([
|
|
@@ -808,6 +1143,7 @@ run.toComplete();
|
|
|
808
1143
|
assert.doesNotMatch(suite, /generated by RouteKit 1\.0\.21/u);
|
|
809
1144
|
assert.match(suite, /emit the complete target-protocol envelope and terminal event/u);
|
|
810
1145
|
assert.match(suite, /include the concrete output rather than only describing it/u);
|
|
1146
|
+
assert.match(suite, /You are a strict evaluator for AI agent outputs\./u);
|
|
811
1147
|
assert.ok(judgeCall >= 0);
|
|
812
1148
|
assert.ok(completionAssertion >= 0);
|
|
813
1149
|
assert.ok(completionAssertion < judgeCall);
|
|
@@ -860,6 +1196,33 @@ test("failed run reports persist the nested qualification error chain", async ()
|
|
|
860
1196
|
unpricedCalls: 0,
|
|
861
1197
|
subscriptionUnitCalls: 0
|
|
862
1198
|
},
|
|
1199
|
+
events: [
|
|
1200
|
+
{
|
|
1201
|
+
name: "plan",
|
|
1202
|
+
at: "2026-08-21T03:47:27.000Z",
|
|
1203
|
+
runId: started.runId,
|
|
1204
|
+
plannedCalls: plan.expectedCallCount
|
|
1205
|
+
},
|
|
1206
|
+
{
|
|
1207
|
+
name: "failure-detail",
|
|
1208
|
+
at: "2026-08-21T03:47:48.000Z",
|
|
1209
|
+
runId: started.runId,
|
|
1210
|
+
phase: "comparison",
|
|
1211
|
+
reason: "RouteKit Eval comparison failed",
|
|
1212
|
+
retryable: false,
|
|
1213
|
+
accounting: {
|
|
1214
|
+
expectedCalls: plan.expectedCallCount,
|
|
1215
|
+
observedCalls: 0,
|
|
1216
|
+
knownInputTokens: 0,
|
|
1217
|
+
knownOutputTokens: 0,
|
|
1218
|
+
unknownTokenMeasurements: 0,
|
|
1219
|
+
knownPricedSubtotalUsd: 0,
|
|
1220
|
+
unpricedCalls: 0,
|
|
1221
|
+
subscriptionUnitCalls: 0
|
|
1222
|
+
},
|
|
1223
|
+
cleanup: { sessionOpened: true, sessionClosed: true }
|
|
1224
|
+
}
|
|
1225
|
+
],
|
|
863
1226
|
failure: 'qualification dimension "provider-protocol-translation" failed ' +
|
|
864
1227
|
"(per-test timeout 600000ms); observed call ids: none",
|
|
865
1228
|
errors: [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|