@velum-labs/routekit-eval-setup 1.3.2 → 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 -10
- package/dist/effect-api.js +56 -6
- 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 +140 -0
- package/dist/eval-event-log.js +220 -0
- 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 -17
- package/dist/index.js +69 -11
- package/dist/inspection.js +2 -3
- package/dist/project-artifacts.d.ts +7 -2
- package/dist/project-artifacts.js +49 -136
- package/dist/project-authoring.d.ts +66 -5
- package/dist/project-authoring.js +783 -109
- package/dist/project-contracts.d.ts +419 -84
- package/dist/project-contracts.js +160 -52
- package/dist/project-store.js +2 -1
- package/dist/project-workflow.d.ts +5 -4
- package/dist/project-workflow.js +154 -35
- 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.d.ts +1 -0
- package/dist/test/eval-event-log.test.js +125 -0
- 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 +419 -40
- 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 -6
|
@@ -0,0 +1,851 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { test } from "node:test";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
import { Effect, Layer, Schema } from "effect";
|
|
9
|
+
import { makeCaseCheckpointStoreV1 } from "../case-checkpoint-store.js";
|
|
10
|
+
import { checkpointDigestV1, makePipelineCaseContextV1, PIPELINE_STAGES } from "../case-pipeline-protocol.js";
|
|
11
|
+
import { EvalProjectAuthoringError } from "../errors.js";
|
|
12
|
+
import { RepositoryHiddenOracleV1 } from "../repository-oracle-protocol.js";
|
|
13
|
+
import { evaluateRepositoryOracleScopeCoverageV1 } from "../repository-oracle-scope-policy.js";
|
|
14
|
+
import { EvalAuthoringTransport } from "../project-authoring.js";
|
|
15
|
+
import { readCasePipelineStatusV1, runCasePipelineV1 } from "../services/case-pipeline/service.js";
|
|
16
|
+
import { RepositoryFoundryProgressLive } from "../services/foundry-progress/service.js";
|
|
17
|
+
import { RepositoryFoundryLanguageModelLive } from "../services/language-model/service.js";
|
|
18
|
+
import { runPipelineAdmitStageV1 } from "../services/pipeline-challenge/service.js";
|
|
19
|
+
import { runPipelineSeedStageV1 } from "../services/pipeline-seed/service.js";
|
|
20
|
+
import { buildRepositoryBehaviorMapV1 } from "../services/repository-model/service.js";
|
|
21
|
+
const execute = promisify(execFile);
|
|
22
|
+
const model = "openai/gpt-6-astra";
|
|
23
|
+
const dimension = {
|
|
24
|
+
id: "repository-behavior-repair",
|
|
25
|
+
description: "Repair user-observable repository behavior while preserving compatible behavior.",
|
|
26
|
+
includes: ["historical executable defects", "public behavior preservation"],
|
|
27
|
+
excludes: ["style-only changes"]
|
|
28
|
+
};
|
|
29
|
+
async function repository(t) {
|
|
30
|
+
const root = await mkdtemp(join(tmpdir(), "case-pipeline-clamp-"));
|
|
31
|
+
t.after(() => rm(root, { recursive: true, force: true }));
|
|
32
|
+
const git = async (...args) => (await execute("git", ["-C", root, ...args], { encoding: "utf8" })).stdout.trim();
|
|
33
|
+
await git("init", "-q");
|
|
34
|
+
await git("config", "user.email", "eval@example.test");
|
|
35
|
+
await git("config", "user.name", "Eval Fixture");
|
|
36
|
+
await mkdir(join(root, "src"), { recursive: true });
|
|
37
|
+
await writeFile(join(root, "package.json"), `${JSON.stringify({ name: "clamp-fixture", private: true, type: "module", exports: "./src/index.js", scripts: { test: "node --test" } }, null, 2)}\n`);
|
|
38
|
+
await writeFile(join(root, "src/clamp.js"), "export const clamp = (value) => Math.min(100, value);\n");
|
|
39
|
+
await writeFile(join(root, "src/index.js"), 'export { clamp } from "./clamp.js";\n');
|
|
40
|
+
await writeFile(join(root, "src/clamp.test.js"), [
|
|
41
|
+
'import assert from "node:assert/strict";',
|
|
42
|
+
'import test from "node:test";',
|
|
43
|
+
'import { clamp } from "./index.js";',
|
|
44
|
+
'test("clamps high values", () => assert.equal(clamp(101), 100));'
|
|
45
|
+
].join("\n"));
|
|
46
|
+
await writeFile(join(root, "src/control.test.js"), 'import assert from "node:assert/strict"; import test from "node:test"; test("control", () => assert.equal(2, 2));\n');
|
|
47
|
+
await git("add", ".");
|
|
48
|
+
await git("commit", "-qm", "add upper clamp");
|
|
49
|
+
const initialCommit = await git("rev-parse", "HEAD");
|
|
50
|
+
await writeFile(join(root, "src/clamp.js"), "export const clamp = (value) => Math.max(0, Math.min(100, value));\n");
|
|
51
|
+
await writeFile(join(root, "src/clamp.test.js"), [
|
|
52
|
+
'import assert from "node:assert/strict";',
|
|
53
|
+
'import test from "node:test";',
|
|
54
|
+
'import { clamp } from "./index.js";',
|
|
55
|
+
'test("clamps low values", () => assert.equal(clamp(-1), 0));',
|
|
56
|
+
'test("clamps high values", () => assert.equal(clamp(101), 100));',
|
|
57
|
+
'test("preserves values", () => assert.equal(clamp(25.5), 25.5));'
|
|
58
|
+
].join("\n"));
|
|
59
|
+
await git("add", ".");
|
|
60
|
+
await git("commit", "-qm", "fix clamp lower bound");
|
|
61
|
+
const referenceCommit = await git("rev-parse", "HEAD");
|
|
62
|
+
const caseDirectory = join(await mkdtemp(join(tmpdir(), "case-pipeline-state-")), "case");
|
|
63
|
+
t.after(() => rm(join(caseDirectory, ".."), { recursive: true, force: true }));
|
|
64
|
+
return { root, initialCommit, referenceCommit, caseDirectory };
|
|
65
|
+
}
|
|
66
|
+
async function repositoryWithSupersededIncompatibleTest(t) {
|
|
67
|
+
const root = await mkdtemp(join(tmpdir(), "case-pipeline-current-surface-"));
|
|
68
|
+
t.after(() => rm(root, { recursive: true, force: true }));
|
|
69
|
+
const git = async (...args) => (await execute("git", ["-C", root, ...args], { encoding: "utf8" })).stdout.trim();
|
|
70
|
+
await git("init", "-q");
|
|
71
|
+
await git("config", "user.email", "eval@example.test");
|
|
72
|
+
await git("config", "user.name", "Eval Fixture");
|
|
73
|
+
await mkdir(join(root, "packages/main/src"), { recursive: true });
|
|
74
|
+
await mkdir(join(root, "packages/extra/src"), { recursive: true });
|
|
75
|
+
await writeFile(join(root, "package.json"), `${JSON.stringify({ name: "current-surface-fixture", private: true, workspaces: ["packages/*"] }, null, 2)}\n`);
|
|
76
|
+
for (const name of ["main", "extra"]) {
|
|
77
|
+
await writeFile(join(root, `packages/${name}/package.json`), `${JSON.stringify({ name: `fixture-${name}`, private: true, type: "module", scripts: { test: "node --test" } }, null, 2)}\n`);
|
|
78
|
+
}
|
|
79
|
+
await writeFile(join(root, "packages/main/src/clamp.js"), "export const clamp = (value) => Math.min(100, value);\n");
|
|
80
|
+
await writeFile(join(root, "packages/main/src/clamp.test.js"), [
|
|
81
|
+
'import assert from "node:assert/strict";',
|
|
82
|
+
'import test from "node:test";',
|
|
83
|
+
'import { clamp } from "./clamp.js";',
|
|
84
|
+
'test("clamps high values", () => assert.equal(clamp(101), 100));'
|
|
85
|
+
].join("\n"));
|
|
86
|
+
await writeFile(join(root, "packages/extra/src/extra.test.js"), 'import assert from "node:assert/strict"; import test from "node:test"; test("extra control", () => assert.equal(2, 2));\n');
|
|
87
|
+
await git("add", ".");
|
|
88
|
+
await git("commit", "-qm", "add fixture packages");
|
|
89
|
+
const initialCommit = await git("rev-parse", "HEAD");
|
|
90
|
+
await writeFile(join(root, "packages/main/src/clamp.js"), [
|
|
91
|
+
"export const clamp = (value) => {",
|
|
92
|
+
' if (typeof value !== "number") throw new TypeError("value must be a number");',
|
|
93
|
+
" return Math.max(0, Math.min(100, value));",
|
|
94
|
+
"};",
|
|
95
|
+
""
|
|
96
|
+
].join("\n"));
|
|
97
|
+
await writeFile(join(root, "packages/main/src/clamp.test.js"), [
|
|
98
|
+
'import assert from "node:assert/strict";',
|
|
99
|
+
'import test from "node:test";',
|
|
100
|
+
'import { clamp } from "./clamp.js";',
|
|
101
|
+
'test("rejects non-numbers", () => assert.throws(() => clamp("25"), TypeError));',
|
|
102
|
+
'test("clamps high values", () => assert.equal(clamp(101), 100));'
|
|
103
|
+
].join("\n"));
|
|
104
|
+
await writeFile(join(root, "packages/extra/src/reference-only-helper.js"), "export const answer = 42;\n");
|
|
105
|
+
await writeFile(join(root, "packages/extra/src/extra.test.js"), [
|
|
106
|
+
'import assert from "node:assert/strict";',
|
|
107
|
+
'import test from "node:test";',
|
|
108
|
+
'import { answer } from "./reference-only-helper.js";',
|
|
109
|
+
'test("reference-only helper", () => assert.equal(answer, 42));'
|
|
110
|
+
].join("\n"));
|
|
111
|
+
await git("add", ".");
|
|
112
|
+
await git("commit", "-qm", "reject non-number clamp input");
|
|
113
|
+
const referenceCommit = await git("rev-parse", "HEAD");
|
|
114
|
+
await rm(join(root, "packages/extra"), { recursive: true });
|
|
115
|
+
await git("add", "-A");
|
|
116
|
+
await git("commit", "-qm", "remove superseded reference-only coverage");
|
|
117
|
+
const tipCommit = await git("rev-parse", "HEAD");
|
|
118
|
+
const caseDirectory = join(await mkdtemp(join(tmpdir(), "case-pipeline-current-surface-state-")), "case");
|
|
119
|
+
t.after(() => rm(join(caseDirectory, ".."), { recursive: true, force: true }));
|
|
120
|
+
return { root, initialCommit, referenceCommit, tipCommit, caseDirectory };
|
|
121
|
+
}
|
|
122
|
+
const fixture = (id, assertion, kind, expectationMode) => ({
|
|
123
|
+
id,
|
|
124
|
+
kind,
|
|
125
|
+
description: id,
|
|
126
|
+
expectedBehavior: id,
|
|
127
|
+
expectationMode,
|
|
128
|
+
source: "generated",
|
|
129
|
+
testPath: "src/clamp.test.js"
|
|
130
|
+
});
|
|
131
|
+
const overlay = (id, assertion) => ({
|
|
132
|
+
path: "src/clamp.test.js",
|
|
133
|
+
fixtureIds: [id],
|
|
134
|
+
content: [
|
|
135
|
+
'import assert from "node:assert/strict";',
|
|
136
|
+
'import test from "node:test";',
|
|
137
|
+
'import { clamp } from "./index.js";',
|
|
138
|
+
`test(${JSON.stringify(id)}, () => { ${assertion} });`
|
|
139
|
+
].join("\n")
|
|
140
|
+
});
|
|
141
|
+
const suite = (caseId, overconstrainValidAlternative = false) => ({
|
|
142
|
+
version: 1,
|
|
143
|
+
caseId,
|
|
144
|
+
fixtures: [
|
|
145
|
+
fixture("negative", "", "historical-regression", "changes"),
|
|
146
|
+
fixture("upper", "", "boundary", "preserved"),
|
|
147
|
+
fixture("fraction", "", "metamorphic", "preserved"),
|
|
148
|
+
...(overconstrainValidAlternative
|
|
149
|
+
? [fixture("implementation-shape", "", "boundary", "preserved")]
|
|
150
|
+
: [])
|
|
151
|
+
],
|
|
152
|
+
overlays: [
|
|
153
|
+
overlay("negative", "assert.equal(clamp(-1), 0)"),
|
|
154
|
+
overlay("upper", "assert.equal(clamp(101), 100)"),
|
|
155
|
+
overlay("fraction", "assert.equal(clamp(25.5), 25.5)"),
|
|
156
|
+
...(overconstrainValidAlternative
|
|
157
|
+
? [overlay("implementation-shape", 'assert.equal(Object.hasOwn(clamp, "prototype"), false)')]
|
|
158
|
+
: [])
|
|
159
|
+
]
|
|
160
|
+
});
|
|
161
|
+
const correctA = "export const clamp = (value) => Math.min(100, Math.max(0, value));\n";
|
|
162
|
+
const correctB = "export function clamp(value) { if (value < 0) return 0; if (value > 100) return 100; return value; }\n";
|
|
163
|
+
const wrong = "export const clamp = (value) => Math.min(100, Math.max(0, Math.round(value)));\n";
|
|
164
|
+
const heldOut = "export const clamp = (value) => Math.max(0, Math.min(100, Math.trunc(value)));\n";
|
|
165
|
+
const edits = (source) => [{ path: "src/clamp.js", content: source }];
|
|
166
|
+
test("automatic seed discovery retains comparative model ranking", async (t) => {
|
|
167
|
+
const repo = await repository(t);
|
|
168
|
+
const context = makePipelineCaseContextV1({
|
|
169
|
+
repositoryRoot: repo.root,
|
|
170
|
+
caseDirectory: repo.caseDirectory,
|
|
171
|
+
caseId: "pipeline-clamp-discovery",
|
|
172
|
+
dimension,
|
|
173
|
+
primaryModel: model,
|
|
174
|
+
budget: { maxModelCalls: 10, maxWallMs: 3_600_000 },
|
|
175
|
+
requestedRef: repo.referenceCommit,
|
|
176
|
+
oracleRepetitions: 2,
|
|
177
|
+
oracleConcurrency: 1
|
|
178
|
+
});
|
|
179
|
+
const map = await Effect.runPromise(buildRepositoryBehaviorMapV1({
|
|
180
|
+
repositoryRoot: context.repositoryRoot,
|
|
181
|
+
requestedRef: context.requestedRef ?? "HEAD"
|
|
182
|
+
}));
|
|
183
|
+
const scripted = transport();
|
|
184
|
+
const checkpoint = await Effect.runPromise(runPipelineSeedStageV1({
|
|
185
|
+
context,
|
|
186
|
+
map,
|
|
187
|
+
checkpoints: {},
|
|
188
|
+
checkpoint: () => Effect.void
|
|
189
|
+
}).pipe(Effect.provide(Layer.mergeAll(RepositoryFoundryLanguageModelLive.pipe(Layer.provide(scripted.layer)), RepositoryFoundryProgressLive()))));
|
|
190
|
+
assert.equal(checkpoint.selection.selectedCommit, repo.referenceCommit);
|
|
191
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "PipelineSeedRankingV1").length, 1, "automatic discovery still ranks competing candidates with the model");
|
|
192
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "PipelineSeedDimensionFitV1").length, 1, "the replay-qualified automatic candidate still receives complete dimension assessment");
|
|
193
|
+
});
|
|
194
|
+
test("explicit seed qualification uses the inspected tip's executable test surface", async (t) => {
|
|
195
|
+
const repo = await repositoryWithSupersededIncompatibleTest(t);
|
|
196
|
+
const context = makePipelineCaseContextV1({
|
|
197
|
+
repositoryRoot: repo.root,
|
|
198
|
+
caseDirectory: repo.caseDirectory,
|
|
199
|
+
caseId: "pipeline-clamp-current-surface",
|
|
200
|
+
dimension,
|
|
201
|
+
primaryModel: model,
|
|
202
|
+
budget: { maxModelCalls: 10, maxWallMs: 3_600_000 },
|
|
203
|
+
referenceCommit: repo.referenceCommit,
|
|
204
|
+
requestedRef: repo.tipCommit,
|
|
205
|
+
oracleRepetitions: 2,
|
|
206
|
+
oracleConcurrency: 1
|
|
207
|
+
});
|
|
208
|
+
const map = await Effect.runPromise(buildRepositoryBehaviorMapV1({
|
|
209
|
+
repositoryRoot: context.repositoryRoot,
|
|
210
|
+
requestedRef: context.requestedRef ?? "HEAD"
|
|
211
|
+
}));
|
|
212
|
+
const scripted = transport();
|
|
213
|
+
const checkpoint = await Effect.runPromise(runPipelineSeedStageV1({
|
|
214
|
+
context,
|
|
215
|
+
map,
|
|
216
|
+
checkpoints: {},
|
|
217
|
+
checkpoint: () => Effect.void
|
|
218
|
+
}).pipe(Effect.provide(Layer.mergeAll(RepositoryFoundryLanguageModelLive.pipe(Layer.provide(scripted.layer)), RepositoryFoundryProgressLive()))));
|
|
219
|
+
assert.equal(checkpoint.selection.selectedCommit, repo.referenceCommit);
|
|
220
|
+
assert.deepEqual(checkpoint.seed.candidateTestIds, ["test-packages-main-src-clamp-test-js"]);
|
|
221
|
+
assert.equal(checkpoint.qualification.stability.stable, true);
|
|
222
|
+
assert.equal(checkpoint.qualification.seed.status, "qualified");
|
|
223
|
+
});
|
|
224
|
+
function reply(input, options) {
|
|
225
|
+
const parsed = JSON.parse(input.input);
|
|
226
|
+
switch (input.schemaName) {
|
|
227
|
+
case "PipelineSeedRankingV1": {
|
|
228
|
+
const candidates = parsed.candidates;
|
|
229
|
+
return {
|
|
230
|
+
candidates: candidates.map(({ commit }, index) => ({
|
|
231
|
+
commit,
|
|
232
|
+
score: 100 - index,
|
|
233
|
+
rationale: "Executable historical clamp repair fits the dimension."
|
|
234
|
+
}))
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
case "PipelineSeedDimensionFitV1": {
|
|
238
|
+
const candidate = parsed.candidate;
|
|
239
|
+
const requested = parsed.dimension;
|
|
240
|
+
return {
|
|
241
|
+
commit: candidate.commit,
|
|
242
|
+
requestedDimension: requested.id,
|
|
243
|
+
outcome: "fit",
|
|
244
|
+
detail: "The replayed clamp repair directly exercises one coherent slice of the requested dimension and respects its exclusions.",
|
|
245
|
+
includes: requested.includes.map((requirement, index) => ({
|
|
246
|
+
requirement,
|
|
247
|
+
outcome: index === 0 ? "supports" : "does-not-support",
|
|
248
|
+
detail: index === 0
|
|
249
|
+
? "The replayed behavior supplies this capability."
|
|
250
|
+
: "This narrow historical fix does not need to cover every example in the dimension."
|
|
251
|
+
})),
|
|
252
|
+
excludes: requested.excludes.map((requirement) => ({
|
|
253
|
+
requirement,
|
|
254
|
+
outcome: "respected",
|
|
255
|
+
detail: "The replayed behavior stays outside this exclusion."
|
|
256
|
+
}))
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
case "routekit_pipeline_spec_analysis_v1": {
|
|
260
|
+
const task = parsed.task;
|
|
261
|
+
const behaviorId = task.seed.targetBehavior[0].id;
|
|
262
|
+
return {
|
|
263
|
+
action: "submit",
|
|
264
|
+
result: {
|
|
265
|
+
summary: "Clamp needs a lower bound while retaining its upper bound and exact in-range values.",
|
|
266
|
+
userObservableBehaviors: [
|
|
267
|
+
"negative values become zero",
|
|
268
|
+
"upper values remain capped",
|
|
269
|
+
"in-range values remain unchanged"
|
|
270
|
+
],
|
|
271
|
+
constraints: ["preserve the clamp export"],
|
|
272
|
+
risks: ["rounding would corrupt in-range values"],
|
|
273
|
+
relevantPaths: ["src/clamp.js", "src/index.js"],
|
|
274
|
+
scope: [
|
|
275
|
+
{
|
|
276
|
+
id: "lower-bound",
|
|
277
|
+
kind: "changed",
|
|
278
|
+
behaviorIds: [behaviorId],
|
|
279
|
+
description: "Negative inputs return zero.",
|
|
280
|
+
evidence: [
|
|
281
|
+
{ commit: "initial", path: "src/clamp.js", startLine: 1, endLine: 1 },
|
|
282
|
+
{ commit: "reference", path: "src/clamp.js", startLine: 1, endLine: 1 }
|
|
283
|
+
]
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
id: "preserve-range",
|
|
287
|
+
kind: "preserved",
|
|
288
|
+
behaviorIds: [behaviorId],
|
|
289
|
+
description: "In-range behavior remains unchanged.",
|
|
290
|
+
evidence: [
|
|
291
|
+
{ commit: "initial", path: "src/clamp.js", startLine: 1, endLine: 1 },
|
|
292
|
+
{ commit: "reference", path: "src/clamp.js", startLine: 1, endLine: 1 }
|
|
293
|
+
]
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
id: "preserve-upper",
|
|
297
|
+
kind: "preserved",
|
|
298
|
+
behaviorIds: [behaviorId],
|
|
299
|
+
description: "Upper-bound behavior remains unchanged.",
|
|
300
|
+
evidence: [
|
|
301
|
+
{ commit: "initial", path: "src/clamp.js", startLine: 1, endLine: 1 },
|
|
302
|
+
{ commit: "reference", path: "src/clamp.js", startLine: 1, endLine: 1 }
|
|
303
|
+
]
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
case "routekit_pipeline_visible_task_v1":
|
|
310
|
+
return {
|
|
311
|
+
requestText: "Repair clamp so negative inputs return zero while values above one hundred remain capped and in-range values remain unchanged.",
|
|
312
|
+
constraints: ["Preserve the public clamp export."]
|
|
313
|
+
};
|
|
314
|
+
case "routekit_pipeline_specification_review_v1": {
|
|
315
|
+
const envelope = parsed;
|
|
316
|
+
const task = (envelope.task ?? parsed);
|
|
317
|
+
const source = task.sourceCatalog.find(({ path, sourceId }) => path === "src/clamp.js" && sourceId.length > 0);
|
|
318
|
+
const referenceSource = task.sourceCatalog.find(({ path, sourceId }) => path === "src/clamp.js" && sourceId !== source.sourceId) ?? source;
|
|
319
|
+
return {
|
|
320
|
+
action: "submit",
|
|
321
|
+
result: {
|
|
322
|
+
verdict: "sufficient",
|
|
323
|
+
detail: "The task covers the executed historical behavior and preservation boundary.",
|
|
324
|
+
criticalBehaviorCoverage: task.targetBehavior
|
|
325
|
+
.filter(({ critical }) => critical)
|
|
326
|
+
.map(({ id }) => ({
|
|
327
|
+
behaviorId: id,
|
|
328
|
+
outcome: "covered",
|
|
329
|
+
detail: "Explicitly stated."
|
|
330
|
+
})),
|
|
331
|
+
dimensionFit: {
|
|
332
|
+
requestedDimension: dimension.id,
|
|
333
|
+
outcome: "fit",
|
|
334
|
+
detail: "Behavioral repository repair.",
|
|
335
|
+
evidencePaths: ["src/clamp.js"]
|
|
336
|
+
},
|
|
337
|
+
referenceCompatibility: {
|
|
338
|
+
outcome: "compatible",
|
|
339
|
+
detail: "Reference implements all scope.",
|
|
340
|
+
scopeCoverage: task.scope.map(({ id }) => ({
|
|
341
|
+
scopeId: id,
|
|
342
|
+
outcome: "supported",
|
|
343
|
+
detail: "Supported by reference.",
|
|
344
|
+
evidence: [{ sourceId: referenceSource.sourceId, startLine: 1, endLine: 1 }]
|
|
345
|
+
}))
|
|
346
|
+
},
|
|
347
|
+
findings: []
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
case "routekit_pipeline_oracle_submission_v1":
|
|
352
|
+
return {
|
|
353
|
+
action: "submit",
|
|
354
|
+
result: {
|
|
355
|
+
suite: (() => {
|
|
356
|
+
const proposed = suite(parsed.task.visibleTask.id, options.oracleRejectsValidAlternative);
|
|
357
|
+
return options.oracleMissesChangedScope ? {
|
|
358
|
+
...proposed,
|
|
359
|
+
overlays: proposed.overlays.map((entry) => entry.fixtureIds.includes("negative")
|
|
360
|
+
? overlay("negative", "assert.equal(clamp(25), 25)") : entry)
|
|
361
|
+
} : proposed;
|
|
362
|
+
})(),
|
|
363
|
+
scopeCoverage: [
|
|
364
|
+
{
|
|
365
|
+
scopeId: "lower-bound",
|
|
366
|
+
outcome: "covered",
|
|
367
|
+
fixtureIds: ["negative"],
|
|
368
|
+
detail: "Negative assertion."
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
scopeId: "preserve-range",
|
|
372
|
+
outcome: "covered",
|
|
373
|
+
fixtureIds: ["fraction"],
|
|
374
|
+
detail: "In-range preservation assertion."
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
scopeId: "preserve-upper",
|
|
378
|
+
outcome: "covered",
|
|
379
|
+
fixtureIds: ["upper"],
|
|
380
|
+
detail: "Upper-bound preservation assertion."
|
|
381
|
+
}
|
|
382
|
+
]
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
case "routekit_pipeline_oracle_coverage_review_v1":
|
|
386
|
+
return {
|
|
387
|
+
verdict: "approve",
|
|
388
|
+
detail: "Every scope has an executable assertion.",
|
|
389
|
+
scopeCoverage: [
|
|
390
|
+
{
|
|
391
|
+
scopeId: "lower-bound",
|
|
392
|
+
outcome: "covered",
|
|
393
|
+
detail: "negative assertion",
|
|
394
|
+
counterexample: "",
|
|
395
|
+
assertionEvidence: [{ fixtureId: "negative", excerpt: "assert.equal(clamp(-1), 0)" }]
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
scopeId: "preserve-range",
|
|
399
|
+
outcome: "covered",
|
|
400
|
+
detail: "fraction assertion",
|
|
401
|
+
counterexample: "",
|
|
402
|
+
assertionEvidence: [
|
|
403
|
+
{ fixtureId: "fraction", excerpt: "assert.equal(clamp(25.5), 25.5)" }
|
|
404
|
+
]
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
scopeId: "preserve-upper",
|
|
408
|
+
outcome: "covered",
|
|
409
|
+
detail: "upper assertion",
|
|
410
|
+
counterexample: "",
|
|
411
|
+
assertionEvidence: [{ fixtureId: "upper", excerpt: "assert.equal(clamp(101), 100)" }]
|
|
412
|
+
}
|
|
413
|
+
]
|
|
414
|
+
};
|
|
415
|
+
case "routekit_pipeline_oracle_coverage_witness_v1": {
|
|
416
|
+
const hypothesis = parsed.pendingCoverageHypothesis;
|
|
417
|
+
const lowerBound = hypothesis.scopeId === "lower-bound";
|
|
418
|
+
return {
|
|
419
|
+
witnesses: [
|
|
420
|
+
{
|
|
421
|
+
scopeId: hypothesis.scopeId,
|
|
422
|
+
explanation: lowerBound
|
|
423
|
+
? "Removing the lower clamp violates only the changed lower-bound behavior."
|
|
424
|
+
: "Rounding an in-range fraction violates only the preserved exact-value behavior.",
|
|
425
|
+
fileOverrides: [
|
|
426
|
+
{
|
|
427
|
+
path: "src/clamp.js",
|
|
428
|
+
edits: [
|
|
429
|
+
{
|
|
430
|
+
search: "export const clamp = (value) => Math.max(0, Math.min(100, value));",
|
|
431
|
+
replace: lowerBound
|
|
432
|
+
? "export const clamp = (value) => Math.min(100, value);"
|
|
433
|
+
: "export const clamp = (value) => Math.max(0, Math.min(100, Math.round(value)));"
|
|
434
|
+
}
|
|
435
|
+
]
|
|
436
|
+
}
|
|
437
|
+
],
|
|
438
|
+
testPath: "src/clamp.test.js",
|
|
439
|
+
testSource: overlay(`witness-${hypothesis.scopeId}`, lowerBound ? "assert.equal(clamp(-1), 0)" : "assert.equal(clamp(25.5), 25.5)").content,
|
|
440
|
+
expectedBehavior: lowerBound
|
|
441
|
+
? "Negative values clamp to zero."
|
|
442
|
+
: "In-range fractional values remain unchanged.",
|
|
443
|
+
expectationMode: lowerBound ? "changes" : "preserved"
|
|
444
|
+
}
|
|
445
|
+
]
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
case "routekit_pipeline_valid_solution_generator_a_v1":
|
|
449
|
+
return options.oracleRejectsValidAlternative
|
|
450
|
+
? {
|
|
451
|
+
id: "solver-b",
|
|
452
|
+
family: "guards",
|
|
453
|
+
kind: "behavior-preserving-valid",
|
|
454
|
+
fileOverrides: edits(correctB)
|
|
455
|
+
}
|
|
456
|
+
: {
|
|
457
|
+
id: "solver-a",
|
|
458
|
+
family: "composition",
|
|
459
|
+
kind: "independent-valid",
|
|
460
|
+
fileOverrides: edits(correctA)
|
|
461
|
+
};
|
|
462
|
+
case "routekit_pipeline_valid_solution_generator_b_v1":
|
|
463
|
+
return {
|
|
464
|
+
id: "solver-b",
|
|
465
|
+
family: "guards",
|
|
466
|
+
kind: "behavior-preserving-valid",
|
|
467
|
+
fileOverrides: edits(correctB)
|
|
468
|
+
};
|
|
469
|
+
case "routekit_pipeline_adversary_v1":
|
|
470
|
+
return {
|
|
471
|
+
id: "near-miss",
|
|
472
|
+
family: "partial-fix",
|
|
473
|
+
kind: "mutation",
|
|
474
|
+
fileOverrides: edits(wrong)
|
|
475
|
+
};
|
|
476
|
+
case "routekit_pipeline_control_correctness_review_v1": {
|
|
477
|
+
const task = parsed;
|
|
478
|
+
assert.ok(task.solutions.every(({ expectedClass }) => expectedClass === undefined), "fixture-blind critics do not receive proposal labels");
|
|
479
|
+
return {
|
|
480
|
+
critiques: task.solutions.map(({ id }) => ({
|
|
481
|
+
solutionId: id,
|
|
482
|
+
classification: id.startsWith("solver-") ? "valid" : "wrong",
|
|
483
|
+
detail: id.startsWith("solver-")
|
|
484
|
+
? "The implementation satisfies the visible lower bound and preservation requirements."
|
|
485
|
+
: "The implementation rounds an in-range value and violates the visible preservation requirement.",
|
|
486
|
+
violatedBehaviorIds: id.startsWith("solver-") ? [] : [task.targetBehavior[0].id]
|
|
487
|
+
}))
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
case "routekit_pipeline_tournament_repair_v1": {
|
|
491
|
+
const task = parsed.task;
|
|
492
|
+
assert.deepEqual(task.measuredAdequacy.falseRejectedSolutionIds, options.oracleMissesChangedScope ? [] : ["solver-b"]);
|
|
493
|
+
if (options.oracleMissesChangedScope)
|
|
494
|
+
assert.deepEqual(task.measuredScopeGaps.unresolvedScopeIds, ["lower-bound"]);
|
|
495
|
+
const replacementSuite = suite(task.visibleTask.id);
|
|
496
|
+
const mixedPurposeSuite = options.mixedPurposeRepairFixture
|
|
497
|
+
? {
|
|
498
|
+
...replacementSuite,
|
|
499
|
+
fixtures: replacementSuite.fixtures.map((candidate) => candidate.id === "upper"
|
|
500
|
+
? { ...candidate, expectationMode: "changes" }
|
|
501
|
+
: candidate)
|
|
502
|
+
}
|
|
503
|
+
: replacementSuite;
|
|
504
|
+
return {
|
|
505
|
+
action: "submit",
|
|
506
|
+
result: {
|
|
507
|
+
targetedSolutionIds: options.oracleMissesChangedScope
|
|
508
|
+
? ["historical-reference", "historical-defect"] : ["solver-b"],
|
|
509
|
+
suite: mixedPurposeSuite,
|
|
510
|
+
rationale: "Remove the implementation-shape assertion while retaining all user-observable behavior assertions."
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
case "routekit_pipeline_held_out_adversary_v1":
|
|
515
|
+
return {
|
|
516
|
+
solutions: [
|
|
517
|
+
{
|
|
518
|
+
id: "held-out-rounding",
|
|
519
|
+
family: "over-broad",
|
|
520
|
+
kind: "model-near-miss",
|
|
521
|
+
fileOverrides: edits(heldOut)
|
|
522
|
+
}
|
|
523
|
+
]
|
|
524
|
+
};
|
|
525
|
+
default:
|
|
526
|
+
throw new Error(`unhandled scripted request ${input.schemaName} (${input.operationId})`);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
function transport(options = {}) {
|
|
530
|
+
const calls = [];
|
|
531
|
+
let interruptionStep = 0;
|
|
532
|
+
const completeDetailed = (input) => Effect.gen(function* () {
|
|
533
|
+
calls.push(input);
|
|
534
|
+
if (options.interruptOnceAt !== undefined &&
|
|
535
|
+
input.operationId.includes(options.interruptOnceAt)) {
|
|
536
|
+
interruptionStep += 1;
|
|
537
|
+
if (interruptionStep === 1) {
|
|
538
|
+
return yield* new EvalProjectAuthoringError({
|
|
539
|
+
operation: "authoring-evaluations",
|
|
540
|
+
detail: "Transport error: injected transport failure"
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
if (interruptionStep === 2) {
|
|
544
|
+
return yield* Effect.die("injected transport interruption after retry");
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
const response = reply(input, options);
|
|
548
|
+
const schemaProperties = input.jsonSchema.properties;
|
|
549
|
+
return {
|
|
550
|
+
text: JSON.stringify(schemaProperties !== undefined && Object.hasOwn(schemaProperties, "turn")
|
|
551
|
+
? { turn: response }
|
|
552
|
+
: response),
|
|
553
|
+
callId: `fake-${String(calls.length)}`
|
|
554
|
+
};
|
|
555
|
+
});
|
|
556
|
+
return {
|
|
557
|
+
calls,
|
|
558
|
+
layer: Layer.succeed(EvalAuthoringTransport, EvalAuthoringTransport.of({
|
|
559
|
+
complete: (input) => Effect.map(completeDetailed(input), ({ text }) => text),
|
|
560
|
+
completeDetailed
|
|
561
|
+
}))
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
const runPipeline = async (input) => {
|
|
565
|
+
const map = await Effect.runPromise(buildRepositoryBehaviorMapV1({
|
|
566
|
+
repositoryRoot: input.context.repositoryRoot,
|
|
567
|
+
requestedRef: input.context.requestedRef ?? "HEAD"
|
|
568
|
+
}));
|
|
569
|
+
return Effect.runPromise(runCasePipelineV1({
|
|
570
|
+
context: input.context, map,
|
|
571
|
+
...(input.store === undefined ? {} : { store: input.store })
|
|
572
|
+
}).pipe(Effect.provide(Layer.mergeAll(RepositoryFoundryLanguageModelLive.pipe(Layer.provide(input.transportLayer)), RepositoryFoundryProgressLive()))));
|
|
573
|
+
};
|
|
574
|
+
const contextFor = (repo, caseId, maxModelCalls) => makePipelineCaseContextV1({
|
|
575
|
+
repositoryRoot: repo.root,
|
|
576
|
+
caseDirectory: repo.caseDirectory,
|
|
577
|
+
caseId,
|
|
578
|
+
dimension,
|
|
579
|
+
primaryModel: model,
|
|
580
|
+
budget: { maxModelCalls, maxWallMs: 3_600_000 },
|
|
581
|
+
referenceCommit: repo.referenceCommit,
|
|
582
|
+
requestedRef: repo.referenceCommit,
|
|
583
|
+
oracleRepetitions: 2,
|
|
584
|
+
oracleConcurrency: 1
|
|
585
|
+
});
|
|
586
|
+
const receivedCalls = async (caseDirectory) => {
|
|
587
|
+
const store = makeCaseCheckpointStoreV1({ caseDirectory });
|
|
588
|
+
const ledger = await Effect.runPromise(store.readLedger);
|
|
589
|
+
return {
|
|
590
|
+
ledger,
|
|
591
|
+
received: ledger.filter(({ phase }) => phase === "received")
|
|
592
|
+
};
|
|
593
|
+
};
|
|
594
|
+
test("real pipeline admits from executed evidence and a rerun makes zero model calls", async (t) => {
|
|
595
|
+
const repo = await repository(t);
|
|
596
|
+
const context = contextFor(repo, "pipeline-clamp", 80);
|
|
597
|
+
const scripted = transport();
|
|
598
|
+
const first = await runPipeline({ context, transportLayer: scripted.layer });
|
|
599
|
+
assert.equal(first.state.status, "admitted", first.state.reason);
|
|
600
|
+
assert.equal(first.state.stage, "done");
|
|
601
|
+
assert.equal(first.admit?.verdict, "admitted");
|
|
602
|
+
assert.equal(first.admit?.benchmarkCase.status, "valid-library");
|
|
603
|
+
assert.ok((first.checkpoints.tournament?.oracle.observations.length ?? 0) > 0);
|
|
604
|
+
assert.ok((first.checkpoints.challenge?.oracle.observations.length ?? 0) > 0);
|
|
605
|
+
assert.deepEqual(first.checkpoints.oracle?.witnesses, []);
|
|
606
|
+
assert.equal(first.checkpoints.oracle?.scopeCoverage.find(({ scopeId }) => scopeId === "preserve-upper")
|
|
607
|
+
?.outcome, "uncertain", "the scheduling ceiling advances to executed tournament evidence without self-attesting remaining scope coverage");
|
|
608
|
+
assert.ok((first.admit?.evidence.validCount ?? 0) >= 2);
|
|
609
|
+
assert.ok((first.admit?.evidence.wrongCount ?? 0) >= 1);
|
|
610
|
+
assert.equal(first.admit?.evidence.heldOutWrongCount, 1);
|
|
611
|
+
assert.ok((first.admit?.evidence.semanticKills.length ?? 0) >= 2);
|
|
612
|
+
assert.deepEqual(first.checkpoints.tournament?.valid.map(({ id }) => id), ["solver-a"], "one generated valid control supplements the executed historical reference");
|
|
613
|
+
assert.ok(first.checkpoints.tournament?.oracle.solutions.some(({ id, expectedClass }) => id === "historical-reference" && expectedClass === "valid"), "the development tournament retains the executed historical reference as independent valid evidence");
|
|
614
|
+
const challengeSolutionIds = first.checkpoints.challenge?.oracle.solutions.map(({ id }) => id) ?? [];
|
|
615
|
+
assert.ok(challengeSolutionIds.includes("historical-reference"));
|
|
616
|
+
assert.ok(challengeSolutionIds.includes("held-out-rounding"));
|
|
617
|
+
assert.ok(!challengeSolutionIds.includes("solver-a"), "the fresh challenge excludes development valid controls");
|
|
618
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "routekit_pipeline_oracle_coverage_review_v1").length, 0, "oracle authoring does not spend proactive critic calls before measured execution");
|
|
619
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "routekit_pipeline_oracle_coverage_witness_v1").length, 0, "oracle authoring does not spend proactive witness calls before measured execution");
|
|
620
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "routekit_pipeline_valid_solution_generator_a_v1").length, 1);
|
|
621
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "routekit_pipeline_valid_solution_generator_b_v1").length, 0);
|
|
622
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "routekit_pipeline_control_correctness_review_v1").length, 0, "fixture-blind control critics stay lazy when execution accepts the generated valid control");
|
|
623
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "routekit_pipeline_tournament_repair_v1").length, 0);
|
|
624
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "PipelineSeedRankingV1").length, 0, "an explicit reference has no candidate-ranking model call");
|
|
625
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "PipelineSeedDimensionFitV1").length, 1, "the explicit reference still receives a complete model dimension assessment");
|
|
626
|
+
const callsBeforeScopeCheck = scripted.calls.length;
|
|
627
|
+
const map = await Effect.runPromise(buildRepositoryBehaviorMapV1({
|
|
628
|
+
repositoryRoot: context.repositoryRoot,
|
|
629
|
+
requestedRef: context.requestedRef ?? "HEAD"
|
|
630
|
+
}));
|
|
631
|
+
const invalidScopeAdmission = await Effect.runPromise(runPipelineAdmitStageV1({
|
|
632
|
+
context,
|
|
633
|
+
map,
|
|
634
|
+
checkpoints: {
|
|
635
|
+
...first.checkpoints,
|
|
636
|
+
oracle: {
|
|
637
|
+
...first.checkpoints.oracle,
|
|
638
|
+
scopeCoverage: first.checkpoints.oracle.scopeCoverage.map((coverage) => coverage.scopeId === "lower-bound" ? { ...coverage, fixtureIds: ["upper"] } : coverage)
|
|
639
|
+
}
|
|
640
|
+
},
|
|
641
|
+
checkpoint: () => Effect.void
|
|
642
|
+
}).pipe(Effect.provide(Layer.mergeAll(RepositoryFoundryLanguageModelLive.pipe(Layer.provide(scripted.layer)), RepositoryFoundryProgressLive()))));
|
|
643
|
+
assert.equal(invalidScopeAdmission.verdict, "rejected");
|
|
644
|
+
assert.ok(invalidScopeAdmission.reasons.some((reason) => reason.includes("changed scope lower-bound lacks one mapped changes fixture with repeated historical-reference passes and attributed historical-defect failures")), "a model-authored mapping cannot substitute unrelated executed fixture evidence");
|
|
645
|
+
assert.equal(scripted.calls.length, callsBeforeScopeCheck, "executed scope verification adds no model calls");
|
|
646
|
+
const mixedPurposeFixtureAdmission = await Effect.runPromise(runPipelineAdmitStageV1({
|
|
647
|
+
context,
|
|
648
|
+
map,
|
|
649
|
+
checkpoints: {
|
|
650
|
+
...first.checkpoints,
|
|
651
|
+
tournament: {
|
|
652
|
+
...first.checkpoints.tournament,
|
|
653
|
+
oracle: {
|
|
654
|
+
...first.checkpoints.tournament.oracle,
|
|
655
|
+
fixtures: first.checkpoints.tournament.oracle.fixtures.map((candidate) => candidate.id === "upper" && candidate.kind === "boundary"
|
|
656
|
+
? { ...candidate, expectationMode: "changes" }
|
|
657
|
+
: candidate)
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
},
|
|
661
|
+
checkpoint: () => Effect.void
|
|
662
|
+
}).pipe(Effect.provide(Layer.mergeAll(RepositoryFoundryLanguageModelLive.pipe(Layer.provide(scripted.layer)), RepositoryFoundryProgressLive()))));
|
|
663
|
+
assert.equal(mixedPurposeFixtureAdmission.verdict, "admitted", "a repeatedly passing fixture may prove a mapped preserved scope while its primary expectation also changes");
|
|
664
|
+
assert.equal(scripted.calls.length, callsBeforeScopeCheck, "mixed-purpose executed scope verification adds no model calls");
|
|
665
|
+
for (let index = 1; index < PIPELINE_STAGES.length; index += 1) {
|
|
666
|
+
const stage = PIPELINE_STAGES[index];
|
|
667
|
+
const parent = first.checkpoints[PIPELINE_STAGES[index - 1]];
|
|
668
|
+
assert.equal(first.checkpoints[stage].parentDigest, checkpointDigestV1(parent));
|
|
669
|
+
}
|
|
670
|
+
const accounting = await receivedCalls(repo.caseDirectory);
|
|
671
|
+
assert.equal(first.state.modelCalls, accounting.received.length);
|
|
672
|
+
assert.ok(accounting.received.every(({ operationId }) => !operationId.includes(":admit")), "admit adds no language-model receipt");
|
|
673
|
+
const callsAfterAdmission = scripted.calls.length;
|
|
674
|
+
const ledgerAfterAdmission = accounting.ledger.length;
|
|
675
|
+
const rerun = await runPipeline({ context, transportLayer: scripted.layer });
|
|
676
|
+
assert.equal(rerun.state.status, "admitted");
|
|
677
|
+
assert.equal(scripted.calls.length, callsAfterAdmission, "valid checkpoints skip every model role");
|
|
678
|
+
const afterRerun = await receivedCalls(repo.caseDirectory);
|
|
679
|
+
assert.equal(afterRerun.ledger.length, ledgerAfterAdmission);
|
|
680
|
+
assert.equal(rerun.state.modelCalls, first.state.modelCalls);
|
|
681
|
+
const incompatible = await runPipeline({
|
|
682
|
+
context: {
|
|
683
|
+
...context,
|
|
684
|
+
dimension: { ...context.dimension, includes: [...context.dimension.includes, "changed"] }
|
|
685
|
+
},
|
|
686
|
+
transportLayer: scripted.layer
|
|
687
|
+
});
|
|
688
|
+
assert.equal(incompatible.state.status, "failed");
|
|
689
|
+
assert.match(incompatible.state.reason ?? "", /different pipeline identity/u);
|
|
690
|
+
assert.equal(scripted.calls.length, callsAfterAdmission, "an incompatible scientific identity is rejected before any model call");
|
|
691
|
+
});
|
|
692
|
+
test("pipeline resumes after an injected transport interruption", async (t) => {
|
|
693
|
+
const repo = await repository(t);
|
|
694
|
+
const context = contextFor(repo, "pipeline-clamp-interrupt", 80);
|
|
695
|
+
const scripted = transport({ interruptOnceAt: ":spec:writer:" });
|
|
696
|
+
const interrupted = await runPipeline({ context, transportLayer: scripted.layer });
|
|
697
|
+
assert.equal(interrupted.state.status, "running", interrupted.state.reason);
|
|
698
|
+
assert.equal(interrupted.state.stage, "spec");
|
|
699
|
+
assert.match(interrupted.state.reason ?? "", /injected transport interruption after retry/u);
|
|
700
|
+
assert.ok(interrupted.checkpoints.seed !== undefined, "accepted seed survives the interruption");
|
|
701
|
+
const seedDigest = checkpointDigestV1(interrupted.checkpoints.seed);
|
|
702
|
+
const callsBeforeResume = scripted.calls.length;
|
|
703
|
+
const resumed = await runPipeline({ context, transportLayer: scripted.layer });
|
|
704
|
+
assert.equal(resumed.state.status, "admitted");
|
|
705
|
+
assert.equal(resumed.admit?.verdict, "admitted");
|
|
706
|
+
assert.ok(resumed.state.resumeCount >= 1);
|
|
707
|
+
assert.ok(scripted.calls.length > callsBeforeResume);
|
|
708
|
+
assert.equal(checkpointDigestV1(resumed.checkpoints.seed), seedDigest);
|
|
709
|
+
assert.equal(scripted.calls.filter(({ operationId }) => operationId.includes(":pipeline:seed")).length, 0, "resume does not rerun the accepted seed checkpoint");
|
|
710
|
+
});
|
|
711
|
+
test("pipeline checkpoints each lazy critic round before a later interruption", async (t) => {
|
|
712
|
+
const repo = await repository(t);
|
|
713
|
+
const context = contextFor(repo, "pipeline-clamp-critic-resume", 80);
|
|
714
|
+
const scripted = transport({
|
|
715
|
+
oracleRejectsValidAlternative: true,
|
|
716
|
+
interruptOnceAt: "solution-critic-b"
|
|
717
|
+
});
|
|
718
|
+
const interrupted = await runPipeline({ context, transportLayer: scripted.layer });
|
|
719
|
+
assert.equal(interrupted.state.status, "running", interrupted.state.reason);
|
|
720
|
+
assert.equal(interrupted.state.stage, "tournament");
|
|
721
|
+
assert.equal(interrupted.checkpoints.tournament?.critiques?.filter(({ solutionId }) => solutionId === "solver-b").length, 1, "the accepted first critic round is durable before the second critic completes");
|
|
722
|
+
assert.equal(scripted.calls.filter(({ operationId }) => operationId.includes("solution-critic-a")).length, 1);
|
|
723
|
+
const resumed = await runPipeline({ context, transportLayer: scripted.layer });
|
|
724
|
+
assert.equal(resumed.state.status, "admitted", resumed.state.reason);
|
|
725
|
+
assert.equal(resumed.admit?.verdict, "admitted");
|
|
726
|
+
assert.equal(scripted.calls.filter(({ operationId }) => operationId.includes("solution-critic-a")).length, 1, "resume does not repeat an accepted checkpointed critic round");
|
|
727
|
+
assert.equal(resumed.checkpoints.tournament?.critiques?.filter(({ solutionId }) => solutionId === "solver-b")
|
|
728
|
+
.length, 2);
|
|
729
|
+
});
|
|
730
|
+
test("tournament repair accepts a mixed-purpose fixture for mapped preserved scope", async (t) => {
|
|
731
|
+
const repo = await repository(t);
|
|
732
|
+
const context = contextFor(repo, "pipeline-clamp-mixed-purpose-repair", 80);
|
|
733
|
+
const scripted = transport({
|
|
734
|
+
oracleRejectsValidAlternative: true,
|
|
735
|
+
mixedPurposeRepairFixture: true
|
|
736
|
+
});
|
|
737
|
+
const completed = await runPipeline({ context, transportLayer: scripted.layer });
|
|
738
|
+
assert.equal(completed.state.status, "admitted", completed.state.reason);
|
|
739
|
+
assert.equal(completed.admit?.verdict, "admitted");
|
|
740
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "routekit_pipeline_tournament_repair_v1").length, 1, "a valid mixed-purpose replacement is accepted without a feedback retry");
|
|
741
|
+
assert.equal(completed.checkpoints.tournament?.suite.fixtures.find(({ id }) => id === "upper")
|
|
742
|
+
?.expectationMode, "changes");
|
|
743
|
+
});
|
|
744
|
+
test("tournament repairs executed scope gaps before freeze or held-out work", async (t) => {
|
|
745
|
+
const repo = await repository(t);
|
|
746
|
+
const context = contextFor(repo, "pipeline-clamp-scope-repair", 80);
|
|
747
|
+
const scripted = transport({
|
|
748
|
+
oracleMissesChangedScope: true,
|
|
749
|
+
interruptOnceAt: ":pipeline:tournament:repair:"
|
|
750
|
+
});
|
|
751
|
+
const interrupted = await runPipeline({ context, transportLayer: scripted.layer });
|
|
752
|
+
const measured = interrupted.checkpoints.tournament;
|
|
753
|
+
assert.equal(measured.adequacy.admitted, false, "generic control separation cannot hide a missing grounded behavior");
|
|
754
|
+
assert.deepEqual(measured.adequacy.falseAcceptedSolutionIds, []);
|
|
755
|
+
assert.deepEqual(measured.adequacy.falseRejectedSolutionIds, []);
|
|
756
|
+
assert.match(measured.adequacy.rejectionReasons.join(";"), /changed scope lower-bound/u);
|
|
757
|
+
assert.equal(interrupted.checkpoints.challenge, undefined, "do not spend held-out work on a known repairable scope gap");
|
|
758
|
+
assert.equal(scripted.calls.some(({ schemaName }) => schemaName === "routekit_pipeline_held_out_adversary_v1"), false);
|
|
759
|
+
const resumed = await runPipeline({ context, transportLayer: scripted.layer });
|
|
760
|
+
assert.equal(resumed.state.status, "admitted", resumed.state.reason);
|
|
761
|
+
assert.equal(resumed.checkpoints.tournament?.history.at(-1)?.decision, "accepted", "reducing only an executed scope gap is scientific progress");
|
|
762
|
+
assert.equal(resumed.checkpoints.tournament?.adequacy.admitted, true);
|
|
763
|
+
const oracle = resumed.checkpoints.tournament.oracle;
|
|
764
|
+
const scopeInput = {
|
|
765
|
+
spec: resumed.checkpoints.spec, oracleCheckpoint: resumed.checkpoints.oracle,
|
|
766
|
+
oracle, repetitions: 2, label: "development"
|
|
767
|
+
};
|
|
768
|
+
assert.deepEqual(evaluateRepositoryOracleScopeCoverageV1(scopeInput).reasons, []);
|
|
769
|
+
for (const damage of ["missing", "duplicate", "unknown", "timeout", "unexecuted"]) {
|
|
770
|
+
const rows = oracle.observations.filter((row) => row.solutionId === "historical-defect" && row.clauseId === "fixture-negative");
|
|
771
|
+
assert.equal(rows.length, 2);
|
|
772
|
+
const observations = oracle.observations.filter((row) => !rows.includes(row));
|
|
773
|
+
observations.push(...(damage === "missing" ? rows.slice(0, 1)
|
|
774
|
+
: damage === "duplicate" ? [rows[0], rows[0]]
|
|
775
|
+
: rows.map((row) => ({
|
|
776
|
+
...row,
|
|
777
|
+
outcome: damage === "unknown" ? "unknown" : row.outcome,
|
|
778
|
+
detail: damage === "timeout" ? row.detail.replace("timeout=false", "timeout=true")
|
|
779
|
+
: damage === "unexecuted" ? row.detail.replace("gradeExecuted=true", "gradeExecuted=false")
|
|
780
|
+
: row.detail
|
|
781
|
+
}))));
|
|
782
|
+
assert.deepEqual(evaluateRepositoryOracleScopeCoverageV1({
|
|
783
|
+
...scopeInput, oracle: { ...oracle, observations }
|
|
784
|
+
}).unresolvedScopeIds, ["lower-bound"], `${damage} evidence cannot close a scope gate`);
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
test("tournament challenger resumes complete replay units without replacing its incumbent early", async (t) => {
|
|
788
|
+
const repo = await repository(t);
|
|
789
|
+
const context = contextFor(repo, "pipeline-clamp-challenger-resume", 80);
|
|
790
|
+
const scripted = transport({ oracleRejectsValidAlternative: true });
|
|
791
|
+
const base = makeCaseCheckpointStoreV1({ caseDirectory: repo.caseDirectory });
|
|
792
|
+
const captured = [];
|
|
793
|
+
const store = {
|
|
794
|
+
...base,
|
|
795
|
+
writeWorkCheckpoint: (name, value) => base.writeWorkCheckpoint(name, value).pipe(Effect.tap(() => Effect.gen(function* () {
|
|
796
|
+
if (!name.startsWith("pipeline-execution-tournament-") || captured.length > 0)
|
|
797
|
+
return;
|
|
798
|
+
const { oracle } = Schema.decodeUnknownSync(Schema.Struct({
|
|
799
|
+
oracle: RepositoryHiddenOracleV1
|
|
800
|
+
}))(value);
|
|
801
|
+
if (oracle.observations.length === 0)
|
|
802
|
+
return;
|
|
803
|
+
captured.push(oracle);
|
|
804
|
+
return yield* Effect.die("injected challenger slice interruption");
|
|
805
|
+
})))
|
|
806
|
+
};
|
|
807
|
+
const interrupted = await runPipeline({ context, transportLayer: scripted.layer, store });
|
|
808
|
+
assert.equal(interrupted.state.status, "running", interrupted.state.reason);
|
|
809
|
+
assert.match(interrupted.state.reason ?? "", /injected challenger slice interruption/u);
|
|
810
|
+
assert.equal(captured.length, 1);
|
|
811
|
+
assert.equal(interrupted.checkpoints.tournament?.adequacy.admitted, false, "partial challenger evidence cannot promote or overwrite the incumbent");
|
|
812
|
+
assert.deepEqual(interrupted.checkpoints.tournament?.adequacy.falseRejectedSolutionIds, ["solver-b"]);
|
|
813
|
+
const resumed = await runPipeline({ context, transportLayer: scripted.layer, store: base });
|
|
814
|
+
assert.equal(resumed.state.status, "admitted", resumed.state.reason);
|
|
815
|
+
assert.equal(scripted.calls.filter(({ schemaName }) => schemaName === "routekit_pipeline_tournament_repair_v1").length, 1, "the accepted repair proposal is not purchased again");
|
|
816
|
+
for (const row of captured[0].observations) {
|
|
817
|
+
assert.deepEqual(resumed.checkpoints.tournament.oracle.observations.find((candidate) => candidate.solutionId === row.solutionId &&
|
|
818
|
+
candidate.clauseId === row.clauseId &&
|
|
819
|
+
candidate.repetition === row.repetition), row, "completed challenger replay evidence survives byte-for-byte");
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
test("pipeline resumes budget exhaustion with a larger cumulative budget", async (t) => {
|
|
823
|
+
const repo = await repository(t);
|
|
824
|
+
const scripted = transport();
|
|
825
|
+
const exhausted = await runPipeline({
|
|
826
|
+
context: contextFor(repo, "pipeline-clamp-budget", 2),
|
|
827
|
+
transportLayer: scripted.layer
|
|
828
|
+
});
|
|
829
|
+
assert.equal(exhausted.state.status, "exhausted");
|
|
830
|
+
assert.equal(exhausted.state.modelCalls, 2);
|
|
831
|
+
const callsAtExhaustion = scripted.calls.length;
|
|
832
|
+
const accountingAtExhaustion = await receivedCalls(repo.caseDirectory);
|
|
833
|
+
assert.equal(accountingAtExhaustion.received.length, 2);
|
|
834
|
+
const completed = await runPipeline({
|
|
835
|
+
context: contextFor(repo, "pipeline-clamp-budget", 80),
|
|
836
|
+
transportLayer: scripted.layer
|
|
837
|
+
});
|
|
838
|
+
assert.equal(completed.state.status, "admitted", completed.state.reason);
|
|
839
|
+
assert.equal(completed.admit?.verdict, "admitted");
|
|
840
|
+
assert.ok(completed.state.resumeCount >= 1);
|
|
841
|
+
assert.ok(completed.state.modelCalls > exhausted.state.modelCalls);
|
|
842
|
+
assert.ok(scripted.calls.length > callsAtExhaustion);
|
|
843
|
+
const finalAccounting = await receivedCalls(repo.caseDirectory);
|
|
844
|
+
assert.equal(completed.state.modelCalls, finalAccounting.received.length);
|
|
845
|
+
assert.equal(finalAccounting.received.filter(({ operationId }) => operationId.includes(":admit")).length, 0);
|
|
846
|
+
const status = await Effect.runPromise(readCasePipelineStatusV1({ caseDirectory: repo.caseDirectory }));
|
|
847
|
+
assert.equal(status.state?.status, "admitted");
|
|
848
|
+
assert.equal(status.state?.modelCalls, completed.state.modelCalls);
|
|
849
|
+
assert.equal(status.ledgerEntries, finalAccounting.ledger.length);
|
|
850
|
+
assert.equal(status.checkpoints.admit?.verdict, "admitted");
|
|
851
|
+
});
|