@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,79 @@
|
|
|
1
|
+
// Natural-language dimension descriptions contain the same function words as
|
|
2
|
+
// nearly every test name. They are not evidence of a shared behavior. Keep
|
|
3
|
+
// actual domain terms and zero-overlap candidates: this remains retrieval, not
|
|
4
|
+
// a semantic eligibility or admission decision.
|
|
5
|
+
const grammaticalWords = new Set([
|
|
6
|
+
"across",
|
|
7
|
+
"all",
|
|
8
|
+
"and",
|
|
9
|
+
"any",
|
|
10
|
+
"are",
|
|
11
|
+
"for",
|
|
12
|
+
"from",
|
|
13
|
+
"has",
|
|
14
|
+
"have",
|
|
15
|
+
"into",
|
|
16
|
+
"its",
|
|
17
|
+
"that",
|
|
18
|
+
"the",
|
|
19
|
+
"their",
|
|
20
|
+
"then",
|
|
21
|
+
"there",
|
|
22
|
+
"these",
|
|
23
|
+
"this",
|
|
24
|
+
"those",
|
|
25
|
+
"was",
|
|
26
|
+
"were",
|
|
27
|
+
"when",
|
|
28
|
+
"where",
|
|
29
|
+
"which",
|
|
30
|
+
"while",
|
|
31
|
+
"with"
|
|
32
|
+
]);
|
|
33
|
+
const words = (value) => new Set((value
|
|
34
|
+
.normalize("NFKC")
|
|
35
|
+
.toLowerCase()
|
|
36
|
+
.match(/[\p{L}\p{N}]+/gu) ?? [])
|
|
37
|
+
.filter((word) => word.length >= 3 && !grammaticalWords.has(word))
|
|
38
|
+
.map((word) => (word.endsWith("s") && word.length > 4 ? word.slice(0, -1) : word)));
|
|
39
|
+
const behaviorPaths = (episode) => [
|
|
40
|
+
...new Set([...episode.implementationPaths, ...episode.protocolPaths, ...episode.testPaths])
|
|
41
|
+
];
|
|
42
|
+
/** Retrieval heuristic only; executable qualification and dimension critics remain mandatory. */
|
|
43
|
+
export function rankRepositorySeedCandidatesV1(map, requestedDimension) {
|
|
44
|
+
const terms = [...words(requestedDimension)];
|
|
45
|
+
return map.historyEpisodes
|
|
46
|
+
.filter((episode) => episode.seedEligible &&
|
|
47
|
+
episode.parentCommit !== undefined &&
|
|
48
|
+
// Historical extraction overlays every changed test at its post-change
|
|
49
|
+
// path. Deleted tests cannot be read there, and moved tests require
|
|
50
|
+
// explicit old/new path handling that this replay lane does not provide.
|
|
51
|
+
!episode.changedPaths.some((entry) => entry.kind === "test" && ["deleted", "renamed"].includes(entry.status)) &&
|
|
52
|
+
behaviorPaths(episode).every((path) => !path.split("/").some((segment) => /^(?:docs?|examples?)$/iu.test(segment))))
|
|
53
|
+
.map((episode) => {
|
|
54
|
+
const subject = words(episode.subject);
|
|
55
|
+
const paths = words(behaviorPaths(episode).join(" "));
|
|
56
|
+
const names = words(map.tests
|
|
57
|
+
.filter((test) => episode.testPaths.includes(test.path))
|
|
58
|
+
.flatMap((test) => test.names)
|
|
59
|
+
.join(" "));
|
|
60
|
+
const matchedTerms = terms.filter((term) => subject.has(term) || paths.has(term) || names.has(term));
|
|
61
|
+
const relevance = terms.reduce((total, term) => total +
|
|
62
|
+
// Commit descriptions often name broad goals. Prefer concrete path
|
|
63
|
+
// evidence over wording alone when spending a bounded replay budget.
|
|
64
|
+
(subject.has(term) ? 1 : 0) +
|
|
65
|
+
(paths.has(term) ? 2 : 0) +
|
|
66
|
+
(names.has(term) ? 1 : 0), 0);
|
|
67
|
+
return { episode, relevance, matchedTerms };
|
|
68
|
+
})
|
|
69
|
+
.sort((left, right) =>
|
|
70
|
+
// Broad refactors touch many plausible keywords without isolating one
|
|
71
|
+
// behavior. Rank relevance per behavior/test path before raw overlap;
|
|
72
|
+
// incidental documentation neither supplies evidence nor expands scope.
|
|
73
|
+
right.relevance / Math.max(1, behaviorPaths(right.episode).length) -
|
|
74
|
+
left.relevance / Math.max(1, behaviorPaths(left.episode).length) ||
|
|
75
|
+
behaviorPaths(left.episode).length - behaviorPaths(right.episode).length ||
|
|
76
|
+
right.relevance - left.relevance ||
|
|
77
|
+
right.episode.occurredAt.localeCompare(left.episode.occurredAt) ||
|
|
78
|
+
left.episode.commit.localeCompare(right.episode.commit));
|
|
79
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { RepositoryFoundryError } from "../errors.js";
|
|
3
|
+
export declare const RepositorySolutionFileOutputV1: Schema.Union<readonly [Schema.Struct<{
|
|
4
|
+
readonly path: Schema.String;
|
|
5
|
+
readonly content: Schema.String;
|
|
6
|
+
}>, Schema.Struct<{
|
|
7
|
+
readonly path: Schema.String;
|
|
8
|
+
readonly edits: Schema.$Array<Schema.Struct<{
|
|
9
|
+
readonly search: Schema.String;
|
|
10
|
+
readonly replace: Schema.String;
|
|
11
|
+
}>>;
|
|
12
|
+
}>]>;
|
|
13
|
+
export type RepositorySolutionFileOutputV1 = typeof RepositorySolutionFileOutputV1.Type;
|
|
14
|
+
export type RepositorySolutionEditSourceV1 = {
|
|
15
|
+
readonly path: string;
|
|
16
|
+
readonly content: string;
|
|
17
|
+
readonly visibleExcerpt: string;
|
|
18
|
+
/** Separate excerpts actually supplied to the same model request; never concatenated. */
|
|
19
|
+
readonly additionalVisibleExcerpts?: readonly string[];
|
|
20
|
+
};
|
|
21
|
+
export declare const loadPinnedSolutionEditSourcesV1: (input: {
|
|
22
|
+
readonly repositoryRoot: string;
|
|
23
|
+
readonly initialCommit: string;
|
|
24
|
+
readonly visibleSources: readonly {
|
|
25
|
+
readonly path: string;
|
|
26
|
+
readonly content: string;
|
|
27
|
+
}[];
|
|
28
|
+
readonly allowedPaths: ReadonlySet<string>;
|
|
29
|
+
}) => Effect.Effect<RepositorySolutionEditSourceV1[], RepositoryFoundryError, never>;
|
|
30
|
+
export declare const materializeSolutionFileOverridesV1: (input: {
|
|
31
|
+
readonly fileOverrides: readonly RepositorySolutionFileOutputV1[];
|
|
32
|
+
readonly sources: readonly RepositorySolutionEditSourceV1[];
|
|
33
|
+
readonly allowedPaths: ReadonlySet<string>;
|
|
34
|
+
}) => {
|
|
35
|
+
fileOverrides: {
|
|
36
|
+
path: string;
|
|
37
|
+
content: string;
|
|
38
|
+
}[];
|
|
39
|
+
provenance: {
|
|
40
|
+
path: string;
|
|
41
|
+
mode: "legacy-full-file" | "exact-edits";
|
|
42
|
+
baseSha256?: string;
|
|
43
|
+
resultSha256: string;
|
|
44
|
+
ranges: readonly {
|
|
45
|
+
start: number;
|
|
46
|
+
end: number;
|
|
47
|
+
}[];
|
|
48
|
+
}[];
|
|
49
|
+
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { Effect, Schema } from "effect";
|
|
3
|
+
import { RepositoryFoundryError } from "../errors.js";
|
|
4
|
+
import { captureGitTreeSnapshotV1, readGitTreeFileV1 } from "./git-task-history.js";
|
|
5
|
+
export const RepositorySolutionFileOutputV1 = Schema.Union([
|
|
6
|
+
Schema.Struct({ path: Schema.String, content: Schema.String }),
|
|
7
|
+
Schema.Struct({
|
|
8
|
+
path: Schema.String,
|
|
9
|
+
edits: Schema.Array(Schema.Struct({ search: Schema.String, replace: Schema.String }))
|
|
10
|
+
})
|
|
11
|
+
]);
|
|
12
|
+
const MAXIMUM_FILE_BYTES = 256_000;
|
|
13
|
+
const MAXIMUM_EDITS_PER_FILE = 32;
|
|
14
|
+
const fail = (detail) => {
|
|
15
|
+
throw new RepositoryFoundryError({ operation: "compile-reviewed-case", detail });
|
|
16
|
+
};
|
|
17
|
+
const safePath = (path) => path.length > 0 &&
|
|
18
|
+
path.length <= 1_024 &&
|
|
19
|
+
!path.includes("\0") &&
|
|
20
|
+
!path.includes("\\") &&
|
|
21
|
+
!path.split("/").some((part) => part === "" || part === "." || part === "..");
|
|
22
|
+
const hash = (text) => createHash("sha256").update(text).digest("hex");
|
|
23
|
+
export const loadPinnedSolutionEditSourcesV1 = Effect.fn("CaseGeneration.loadPinnedSolutionEditSources")(function* (input) {
|
|
24
|
+
const snapshot = yield* captureGitTreeSnapshotV1({
|
|
25
|
+
repositoryRoot: input.repositoryRoot,
|
|
26
|
+
requestedRef: input.initialCommit
|
|
27
|
+
});
|
|
28
|
+
const sources = [];
|
|
29
|
+
const visibleByPath = new Map();
|
|
30
|
+
for (const source of input.visibleSources) {
|
|
31
|
+
const excerpts = visibleByPath.get(source.path) ?? new Set();
|
|
32
|
+
excerpts.add(source.content);
|
|
33
|
+
visibleByPath.set(source.path, excerpts);
|
|
34
|
+
}
|
|
35
|
+
for (const [path, suppliedExcerpts] of visibleByPath) {
|
|
36
|
+
if (!input.allowedPaths.has(path) || !snapshot.files.includes(path))
|
|
37
|
+
continue;
|
|
38
|
+
if (!safePath(path)) {
|
|
39
|
+
return yield* new RepositoryFoundryError({
|
|
40
|
+
operation: "compile-reviewed-case",
|
|
41
|
+
detail: "solution edit base has an unsafe path"
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const content = yield* readGitTreeFileV1({ snapshot, path });
|
|
45
|
+
// Oversized sources can still be read as context, but cannot become an
|
|
46
|
+
// executable full-file override under the existing solution size policy.
|
|
47
|
+
if (Buffer.byteLength(content) > MAXIMUM_FILE_BYTES)
|
|
48
|
+
continue;
|
|
49
|
+
const excerpts = [...suppliedExcerpts];
|
|
50
|
+
const superset = excerpts.find(excerpt => excerpts.every(other => excerpt.includes(other)));
|
|
51
|
+
sources.push({
|
|
52
|
+
path,
|
|
53
|
+
content,
|
|
54
|
+
visibleExcerpt: superset ?? excerpts[0],
|
|
55
|
+
...(superset === undefined ? { additionalVisibleExcerpts: excerpts.slice(1) } : {})
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return sources;
|
|
59
|
+
});
|
|
60
|
+
export const materializeSolutionFileOverridesV1 = (input) => {
|
|
61
|
+
const sources = new Map(input.sources.map((source) => [source.path, source]));
|
|
62
|
+
const seen = new Set();
|
|
63
|
+
const provenance = [];
|
|
64
|
+
const fileOverrides = input.fileOverrides.map((override) => {
|
|
65
|
+
const { path } = override;
|
|
66
|
+
if (!safePath(path) || !input.allowedPaths.has(path) || seen.has(path)) {
|
|
67
|
+
fail("solution edit targets a duplicate, unsafe, or unreviewed path");
|
|
68
|
+
}
|
|
69
|
+
seen.add(path);
|
|
70
|
+
const source = sources.get(path);
|
|
71
|
+
if ("content" in override) {
|
|
72
|
+
if ("edits" in override)
|
|
73
|
+
fail("solution override cannot combine content and edits");
|
|
74
|
+
if (override.content.trim().length === 0 ||
|
|
75
|
+
Buffer.byteLength(override.content) > MAXIMUM_FILE_BYTES) {
|
|
76
|
+
fail("solution full-file override is empty or oversized");
|
|
77
|
+
}
|
|
78
|
+
provenance.push({
|
|
79
|
+
path,
|
|
80
|
+
mode: "legacy-full-file",
|
|
81
|
+
...(source === undefined ? {} : { baseSha256: hash(source.content) }),
|
|
82
|
+
resultSha256: hash(override.content),
|
|
83
|
+
ranges: []
|
|
84
|
+
});
|
|
85
|
+
return { path, content: override.content };
|
|
86
|
+
}
|
|
87
|
+
if (source === undefined)
|
|
88
|
+
fail("solution exact edits require a reviewed, visible, complete pinned pre-change base");
|
|
89
|
+
if (override.edits.length === 0 || override.edits.length > MAXIMUM_EDITS_PER_FILE) {
|
|
90
|
+
fail("solution exact edits require between one and 32 replacements per file");
|
|
91
|
+
}
|
|
92
|
+
const ranges = override.edits
|
|
93
|
+
.map(({ search, replace }) => {
|
|
94
|
+
if (search.length === 0 || search === replace)
|
|
95
|
+
fail("solution exact search must be nonempty and change its matched text");
|
|
96
|
+
const start = source.content.indexOf(search);
|
|
97
|
+
const visibleOnce = [source.visibleExcerpt, ...(source.additionalVisibleExcerpts ?? [])]
|
|
98
|
+
.some(excerpt => {
|
|
99
|
+
const visibleStart = excerpt.indexOf(search);
|
|
100
|
+
return visibleStart >= 0 && excerpt.indexOf(search, visibleStart + 1) === -1;
|
|
101
|
+
});
|
|
102
|
+
if (start < 0 ||
|
|
103
|
+
source.content.indexOf(search, start + 1) !== -1 ||
|
|
104
|
+
!visibleOnce) {
|
|
105
|
+
fail("solution exact search must match once in both the visible excerpt and pinned full source");
|
|
106
|
+
}
|
|
107
|
+
return { start, end: start + search.length, replace };
|
|
108
|
+
})
|
|
109
|
+
.sort((a, b) => a.start - b.start);
|
|
110
|
+
if (ranges.some((range, index) => index > 0 && range.start < ranges[index - 1].end)) {
|
|
111
|
+
fail("solution exact replacements overlap in the original pre-change source");
|
|
112
|
+
}
|
|
113
|
+
const resultBytes = Buffer.byteLength(source.content) +
|
|
114
|
+
ranges.reduce((change, range) => change +
|
|
115
|
+
Buffer.byteLength(range.replace) -
|
|
116
|
+
Buffer.byteLength(source.content.slice(range.start, range.end)), 0);
|
|
117
|
+
if (resultBytes > MAXIMUM_FILE_BYTES) {
|
|
118
|
+
fail("materialized solution override exceeds the existing file size bound");
|
|
119
|
+
}
|
|
120
|
+
let content = source.content;
|
|
121
|
+
for (const range of [...ranges].reverse()) {
|
|
122
|
+
content = content.slice(0, range.start) + range.replace + content.slice(range.end);
|
|
123
|
+
}
|
|
124
|
+
if (content.trim().length === 0)
|
|
125
|
+
fail("materialized solution override is empty");
|
|
126
|
+
provenance.push({
|
|
127
|
+
path,
|
|
128
|
+
mode: "exact-edits",
|
|
129
|
+
baseSha256: hash(source.content),
|
|
130
|
+
resultSha256: hash(content),
|
|
131
|
+
ranges: ranges.map(({ start, end }) => ({ start, end }))
|
|
132
|
+
});
|
|
133
|
+
return { path, content };
|
|
134
|
+
});
|
|
135
|
+
return { fileOverrides, provenance };
|
|
136
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Static platform inspection only. Missing/changed dependencies do not gain semantic credit. */
|
|
2
|
+
export declare function repositoryVitestPhaseAdapterV1(input: {
|
|
3
|
+
readonly cwd: string;
|
|
4
|
+
readonly checkout: string;
|
|
5
|
+
}): Promise<{
|
|
6
|
+
readonly supported: boolean;
|
|
7
|
+
readonly source: string;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFile, realpath } from "node:fs/promises";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { dirname, isAbsolute, join, relative, sep } from "node:path";
|
|
5
|
+
// These hashes describe the published 3.2.7 implementation, not an arbitrary
|
|
6
|
+
// package claiming that version. No dependency/cache bytes are modified.
|
|
7
|
+
const VITEST_FILES = {
|
|
8
|
+
"dist/index.js": "d207c396b9e41b3987bc24e335e808d9bd09c5841044d33b073cebbbc0154a37",
|
|
9
|
+
"dist/runners.js": "95c2e3dd20803ad53e56d545840dac9b954546324c918e5fcffcbdb3a62c3de3",
|
|
10
|
+
"dist/chunks/index.CwejwG0H.js": "5a92953a14e89edddf7470e49689dda55f9af902f1ca598af2433560f3dd70b4",
|
|
11
|
+
"dist/chunks/cli-api.DVe0nWUx.js": "4c2fecfeb976ee9cdf00cf4a03daef462cefd08e0e502b2ce7c1daf3ac540135"
|
|
12
|
+
};
|
|
13
|
+
const RUNNER_FILES = {
|
|
14
|
+
"dist/index.js": "1802b89f2c5ab0344e0d5777d063e5ef3b019af7efed9d3db23460970bd6416c",
|
|
15
|
+
"dist/chunk-hooks.js": "5e0b0ece2242e3475a0312a375fac6e47287602792d7f4999d2d733ecda2d69a"
|
|
16
|
+
};
|
|
17
|
+
/** Static platform inspection only. Missing/changed dependencies do not gain semantic credit. */
|
|
18
|
+
export async function repositoryVitestPhaseAdapterV1(input) {
|
|
19
|
+
try {
|
|
20
|
+
const checkout = await realpath(input.checkout);
|
|
21
|
+
const fromCheckout = createRequire(join(input.cwd, "package.json"));
|
|
22
|
+
const vitestManifest = await realpath(fromCheckout.resolve("vitest/package.json"));
|
|
23
|
+
const fromVitest = createRequire(vitestManifest);
|
|
24
|
+
const runnerManifest = await realpath(fromVitest.resolve("@vitest/runner/package.json"));
|
|
25
|
+
const viteManifest = await realpath(fromVitest.resolve("vite/package.json"));
|
|
26
|
+
for (const [path, version] of [
|
|
27
|
+
[vitestManifest, "3.2.7"],
|
|
28
|
+
[runnerManifest, "3.2.7"],
|
|
29
|
+
[viteManifest, "7.3.6"]
|
|
30
|
+
]) {
|
|
31
|
+
const local = relative(checkout, path);
|
|
32
|
+
if (local === ".." || local.startsWith(`..${sep}`) || isAbsolute(local)) {
|
|
33
|
+
return { supported: false, source: "" };
|
|
34
|
+
}
|
|
35
|
+
const manifest = JSON.parse(await readFile(path, "utf8"));
|
|
36
|
+
if (manifest.version !== version)
|
|
37
|
+
return { supported: false, source: "" };
|
|
38
|
+
}
|
|
39
|
+
for (const [root, inventory] of [
|
|
40
|
+
[dirname(vitestManifest), VITEST_FILES],
|
|
41
|
+
[dirname(runnerManifest), RUNNER_FILES]
|
|
42
|
+
]) {
|
|
43
|
+
for (const [path, expected] of Object.entries(inventory)) {
|
|
44
|
+
const actual = createHash("sha256").update(await readFile(join(root, path))).digest("hex");
|
|
45
|
+
if (actual !== expected)
|
|
46
|
+
return { supported: false, source: "" };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
supported: true,
|
|
51
|
+
source: `import { VitestTestRunner } from ${JSON.stringify(join(dirname(vitestManifest), "dist/runners.js"))};\n` +
|
|
52
|
+
`import { getCurrentSuite, getFn, getHooks } from ${JSON.stringify(join(dirname(runnerManifest), "dist/index.js"))};\n` +
|
|
53
|
+
REPOSITORY_VITEST_PHASE_SOURCE
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return { supported: false, source: "" };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// A framework adapter, not an execution/resource owner. The original Vitest
|
|
61
|
+
// collector and lifecycle still run. The host wraps only an observed raw
|
|
62
|
+
// callback BEFORE Vitest's withFixtures/timeout/assertion wrappers.
|
|
63
|
+
const REPOSITORY_VITEST_PHASE_SOURCE = String.raw `
|
|
64
|
+
const apply = Reflect.apply;
|
|
65
|
+
const arrayPush = Array.prototype.push;
|
|
66
|
+
const own = Object.prototype.hasOwnProperty;
|
|
67
|
+
const cleanupMetadata = [
|
|
68
|
+
Symbol.for("VITEST_CLEANUP_TIMEOUT"),
|
|
69
|
+
Symbol.for("VITEST_CLEANUP_STACK_TRACE")
|
|
70
|
+
];
|
|
71
|
+
const plain = value => value != null && typeof value === "object" &&
|
|
72
|
+
(Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
73
|
+
const cleanOptions = value => value === undefined || typeof value === "number" ||
|
|
74
|
+
(plain(value) && Object.entries(Object.getOwnPropertyDescriptors(value)).every(([key, descriptor]) =>
|
|
75
|
+
key === "timeout" && "value" in descriptor && typeof descriptor.value === "number"));
|
|
76
|
+
const errorsOf = test => test.result?.errors ?? [];
|
|
77
|
+
const thrownErrorCount = error => Array.isArray(error) ? error.length : 1;
|
|
78
|
+
const healthyHooks = test => Object.values(test.result?.hooks ?? {}).every(state => state === "pass");
|
|
79
|
+
class PhaseAttributionError extends Error {
|
|
80
|
+
name = "RouteKitVitestPhaseAttributionError";
|
|
81
|
+
code = "ROUTEKIT_VITEST_PHASE_UNATTRIBUTED";
|
|
82
|
+
}
|
|
83
|
+
export default class RepositoryVitestPhaseAdapter extends VitestTestRunner {
|
|
84
|
+
#facts = new WeakMap();
|
|
85
|
+
#tests = [];
|
|
86
|
+
#collections = 0;
|
|
87
|
+
#invalid = false;
|
|
88
|
+
#pendingCleanup = 0;
|
|
89
|
+
#wrappedHooks = new WeakSet();
|
|
90
|
+
|
|
91
|
+
constructor(config) {
|
|
92
|
+
super(config);
|
|
93
|
+
if (this.pool !== "forks" || this.workerState.environment?.name !== "node" ||
|
|
94
|
+
config.mode !== "test" || config.isolate !== true) {
|
|
95
|
+
throw new PhaseAttributionError("unsupported worker configuration");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#observeCleanup(callback) {
|
|
100
|
+
if (typeof callback !== "function") {
|
|
101
|
+
this.#invalid = true;
|
|
102
|
+
return callback;
|
|
103
|
+
}
|
|
104
|
+
const adapter = this;
|
|
105
|
+
const wrapped = async function(...args) {
|
|
106
|
+
adapter.#pendingCleanup += 1;
|
|
107
|
+
try {
|
|
108
|
+
const value = await apply(callback, this, args);
|
|
109
|
+
return typeof value === "function" ? adapter.#observeCleanup(value) : value;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
// Keep the actual cleanup throw outside mutable task.result inventory.
|
|
112
|
+
adapter.#invalid = true;
|
|
113
|
+
throw error;
|
|
114
|
+
} finally {
|
|
115
|
+
adapter.#pendingCleanup -= 1;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
// The pinned framework reads these descriptors from the invoked suite
|
|
119
|
+
// hook when constructing its returned-cleanup timeout wrapper. Replacing
|
|
120
|
+
// the callback must not replace a local timeout with the global default
|
|
121
|
+
// or discard the original registration stack.
|
|
122
|
+
for (const key of cleanupMetadata) {
|
|
123
|
+
const descriptor = Object.getOwnPropertyDescriptor(callback, key);
|
|
124
|
+
if (descriptor !== undefined) Object.defineProperty(wrapped, key, descriptor);
|
|
125
|
+
}
|
|
126
|
+
return wrapped;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
#observeTestHooks(test) {
|
|
130
|
+
const adapter = this;
|
|
131
|
+
for (const name of ["onFinished", "onFailed"]) {
|
|
132
|
+
const callbacks = test[name] ?? [];
|
|
133
|
+
if (!Array.isArray(callbacks)) {
|
|
134
|
+
this.#invalid = true;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (this.#wrappedHooks.has(callbacks)) continue;
|
|
138
|
+
if (callbacks.push !== arrayPush) {
|
|
139
|
+
this.#invalid = true;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
this.#wrappedHooks.add(callbacks);
|
|
143
|
+
for (let index = 0; index < callbacks.length; index += 1) {
|
|
144
|
+
callbacks[index] = this.#observeCleanup(callbacks[index]);
|
|
145
|
+
}
|
|
146
|
+
// Both context methods and exported globals push an already timeout-
|
|
147
|
+
// wrapped callback here. Keep the actual arrays and native push return
|
|
148
|
+
// value/receiver; Vitest alone still chooses when/how to iterate them.
|
|
149
|
+
// This also observes registrations after the body, including onFailed
|
|
150
|
+
// registered by an onFinished callback before failed hooks are selected.
|
|
151
|
+
Object.defineProperty(callbacks, "push", {
|
|
152
|
+
configurable: true, enumerable: false, writable: true,
|
|
153
|
+
value: function(...items) {
|
|
154
|
+
return apply(arrayPush, this, items.map(callback => adapter.#observeCleanup(callback)));
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
test[name] = callbacks;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async onBeforeRunSuite(suite) {
|
|
162
|
+
await super.onBeforeRunSuite(suite);
|
|
163
|
+
// Match the pinned runSuite early-failure branch after the superclass hook.
|
|
164
|
+
// Collection failure can leave no hook map; preserve its original result.
|
|
165
|
+
if (suite.result?.state === "fail") {
|
|
166
|
+
this.#invalid = true;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
for (const callbacks of Object.values(getHooks(suite))) {
|
|
170
|
+
if (this.#wrappedHooks.has(callbacks)) continue;
|
|
171
|
+
this.#wrappedHooks.add(callbacks);
|
|
172
|
+
for (let index = 0; index < callbacks.length; index += 1) {
|
|
173
|
+
callbacks[index] = this.#observeCleanup(callbacks[index]);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async importFile(filepath, source) {
|
|
179
|
+
if (source !== "collect" && source !== "setup") {
|
|
180
|
+
this.#invalid = true;
|
|
181
|
+
return super.importFile(filepath, source);
|
|
182
|
+
}
|
|
183
|
+
// clearCollectorContext has run before importFile in the pinned framework.
|
|
184
|
+
// Nested collectors are deliberately unobserved and therefore abstain.
|
|
185
|
+
const collector = getCurrentSuite();
|
|
186
|
+
const original = collector.test.fn;
|
|
187
|
+
const adapter = this;
|
|
188
|
+
const registration = function(name, optionsOrFn, fnOrOptions) {
|
|
189
|
+
const callbackIndex = typeof optionsOrFn === "function" ? 1 :
|
|
190
|
+
typeof fnOrOptions === "function" ? 2 : -1;
|
|
191
|
+
const callback = callbackIndex === 1 ? optionsOrFn : fnOrOptions;
|
|
192
|
+
const options = callbackIndex === 1 ? fnOrOptions : optionsOrFn;
|
|
193
|
+
const contextKeys = Reflect.ownKeys(this ?? {});
|
|
194
|
+
const supported = callbackIndex !== -1 && cleanOptions(options) && plain(this) &&
|
|
195
|
+
contextKeys.every(key => key === "sequential") &&
|
|
196
|
+
!collector.fixtures()?.length &&
|
|
197
|
+
!apply(own, callback, ["__VITEST_FIXTURE_INDEX__"]);
|
|
198
|
+
if (!supported) return apply(original, this, [name, optionsOrFn, fnOrOptions]);
|
|
199
|
+
const fact = { entries: 0, returns: 0, throws: 0, thrownCount: 0, cleanEntry: false,
|
|
200
|
+
beforeCleanup: undefined, finalized: false, task: undefined, fn: undefined };
|
|
201
|
+
const wrapped = async function(...args) {
|
|
202
|
+
fact.entries += 1;
|
|
203
|
+
fact.cleanEntry = fact.task !== undefined && errorsOf(fact.task).length === 0 &&
|
|
204
|
+
fact.task.result?.state === "run";
|
|
205
|
+
try {
|
|
206
|
+
const value = await apply(callback, this, args);
|
|
207
|
+
fact.returns += 1;
|
|
208
|
+
return value;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
fact.throws += 1;
|
|
211
|
+
fact.thrownCount = thrownErrorCount(error);
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
const args = [name, optionsOrFn, fnOrOptions];
|
|
216
|
+
args[callbackIndex] = wrapped;
|
|
217
|
+
const before = collector.tasks.length;
|
|
218
|
+
const value = apply(original, this, args);
|
|
219
|
+
const task = collector.tasks[before];
|
|
220
|
+
if (collector.tasks.length !== before + 1 || task?.type !== "test") {
|
|
221
|
+
adapter.#invalid = true;
|
|
222
|
+
return value;
|
|
223
|
+
}
|
|
224
|
+
fact.task = task;
|
|
225
|
+
fact.fn = getFn(task);
|
|
226
|
+
adapter.#facts.set(task, fact);
|
|
227
|
+
return value;
|
|
228
|
+
};
|
|
229
|
+
collector.test.fn = registration;
|
|
230
|
+
try {
|
|
231
|
+
return await super.importFile(filepath, source);
|
|
232
|
+
} finally {
|
|
233
|
+
if (collector.test.fn !== registration) this.#invalid = true;
|
|
234
|
+
else collector.test.fn = original;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
onCollected(files) {
|
|
239
|
+
this.#collections += 1;
|
|
240
|
+
const visit = tasks => {
|
|
241
|
+
for (const task of tasks) {
|
|
242
|
+
if (task.type === "test") this.#tests.push(task);
|
|
243
|
+
else { this.#invalid = true; visit(task.tasks ?? []); }
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
for (const file of files) visit(file.tasks);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async onBeforeRunTask(test) {
|
|
250
|
+
await super.onBeforeRunTask(test);
|
|
251
|
+
const fact = this.#facts.get(test);
|
|
252
|
+
if (!fact || getFn(test) !== fact.fn || test.fails || test.concurrent ||
|
|
253
|
+
(test.retry ?? 0) !== 0 || (test.repeats ?? 0) !== 0 ||
|
|
254
|
+
(test.mode !== "run" && test.mode !== "queued")) {
|
|
255
|
+
this.#invalid = true;
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
this.#observeTestHooks(test);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// This is the framework boundary AFTER its try/catch and BEFORE afterEach,
|
|
262
|
+
// returned-hook cleanup, fixture teardown, onTestFinished and onTestFailed.
|
|
263
|
+
// A body wrapper alone cannot certify that these later phases stayed clean.
|
|
264
|
+
onTaskFinished(test) {
|
|
265
|
+
const fact = this.#facts.get(test);
|
|
266
|
+
if (!fact || fact.beforeCleanup !== undefined || fact.entries !== 1 ||
|
|
267
|
+
fact.returns + fact.throws !== 1 || !fact.cleanEntry || !healthyHooks(test)) {
|
|
268
|
+
this.#invalid = true;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const values = errorsOf(test);
|
|
272
|
+
if (!Array.isArray(values) || values.length !== (fact.throws === 1 ? fact.thrownCount : 0) ||
|
|
273
|
+
(fact.throws === 1 && (fact.thrownCount < 1 || test.result?.state !== "fail")) ||
|
|
274
|
+
(fact.returns === 1 && test.result?.state !== "pass")) {
|
|
275
|
+
this.#invalid = true;
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
// Preserve identity and immutable primitive snapshots, not test.meta or a
|
|
279
|
+
// candidate-supplied phase label. No stack/message inspection is used.
|
|
280
|
+
fact.beforeCleanup = values.map(error => ({ error, name: error?.name, code: error?.code }));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async onAfterRunTask(test) {
|
|
284
|
+
await super.onAfterRunTask(test);
|
|
285
|
+
const fact = this.#facts.get(test);
|
|
286
|
+
const before = fact?.beforeCleanup;
|
|
287
|
+
const after = errorsOf(test);
|
|
288
|
+
if (!fact || !before || getFn(test) !== fact.fn || !healthyHooks(test) ||
|
|
289
|
+
!Array.isArray(after) || before.length !== after.length ||
|
|
290
|
+
!before.every((item, index) => item.error === after[index] &&
|
|
291
|
+
item.name === after[index]?.name && item.code === after[index]?.code) ||
|
|
292
|
+
test.result?.state !== (fact.throws === 1 ? "fail" : "pass")) {
|
|
293
|
+
this.#invalid = true;
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
fact.finalized = true;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async onAfterRunFiles() {
|
|
300
|
+
await super.onAfterRunFiles();
|
|
301
|
+
if (this.#invalid || this.#pendingCleanup !== 0 || this.#collections !== 1 || this.#tests.length === 0 ||
|
|
302
|
+
this.#tests.some(test => this.#facts.get(test)?.finalized !== true)) {
|
|
303
|
+
// Deliberately AFTER normal test cleanup; never use an arbitrary launch or
|
|
304
|
+
// import failure as this attribution refusal. The existing reporter's
|
|
305
|
+
// unhandled-error/completion guards turn this host error into unknown.
|
|
306
|
+
throw new PhaseAttributionError("test callback or cleanup phase was not attributable");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
`;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { RepositoryCommandRecipeV1 } from "../repository-behavior-protocol.js";
|
|
2
|
+
/** Only the explicitly recognized, one-shot Vitest execution receives this reporter. */
|
|
3
|
+
export declare function repositoryVitestTestArgumentsV1(recipe: RepositoryCommandRecipeV1, reporterPath: string): readonly string[] | undefined;
|
|
4
|
+
/**
|
|
5
|
+
* Written outside the candidate-writable checkout. The parent reporter observes
|
|
6
|
+
* worker results; a completed process or assertion-looking console text is not
|
|
7
|
+
* sufficient evidence. The private phased frame is emitted only after installing
|
|
8
|
+
* the pinned host callback adapter at the resolved-config boundary. Historical
|
|
9
|
+
* unphased frames are preserved but cannot retain semantic credit.
|
|
10
|
+
*/
|
|
11
|
+
export declare function repositoryVitestReporterSourceV1(input: {
|
|
12
|
+
readonly phaseAdapterPath: string;
|
|
13
|
+
readonly runtimeSupported: boolean;
|
|
14
|
+
}): string;
|
|
15
|
+
type Evidence = {
|
|
16
|
+
readonly outcome: "pass" | "fail" | "unknown";
|
|
17
|
+
readonly detail: string;
|
|
18
|
+
readonly inconclusiveReason?: "unattributed-test-failure";
|
|
19
|
+
};
|
|
20
|
+
/** Undefined means that this command did not emit the host's Vitest protocol. */
|
|
21
|
+
export declare function repositoryVitestTestEvidenceV1(result: {
|
|
22
|
+
readonly exitCode: number | null;
|
|
23
|
+
}, output: string): Evidence | undefined;
|
|
24
|
+
export {};
|