@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,5 @@
|
|
|
1
|
+
import { type EvalAuthoringCompletion } from "../project-authoring.js";
|
|
2
|
+
/** Capacity belongs to a named review, never to arbitrary generated input. */
|
|
3
|
+
export declare const evalAuthoringRequestByteLimit: (input: Pick<EvalAuthoringCompletion, "reviewInputVersion" | "foundryRole" | "schemaName">) => number;
|
|
4
|
+
/** The same wire representation is used for sizing and transport. */
|
|
5
|
+
export declare const evalAuthoringResponsesRequestBody: (input: EvalAuthoringCompletion) => string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { EVAL_AUTHORING_REQUEST_BYTES, EVAL_AUTHORING_REVIEW_REQUEST_BYTES } from "../project-authoring.js";
|
|
2
|
+
/** Capacity belongs to a named review, never to arbitrary generated input. */
|
|
3
|
+
export const evalAuthoringRequestByteLimit = (input) => {
|
|
4
|
+
if (input.reviewInputVersion === undefined)
|
|
5
|
+
return EVAL_AUTHORING_REQUEST_BYTES;
|
|
6
|
+
if (input.reviewInputVersion !== 2 ||
|
|
7
|
+
!((input.foundryRole === "quality-reviewer" &&
|
|
8
|
+
input.schemaName === "routekit_repository_generation_quality_review_v1") ||
|
|
9
|
+
(input.foundryRole === "independent-evidence-review" &&
|
|
10
|
+
input.schemaName === "routekit_foundry_independent_evidence_review_v1")))
|
|
11
|
+
throw new Error("expanded input capacity requires a versioned complete evidence review");
|
|
12
|
+
return EVAL_AUTHORING_REVIEW_REQUEST_BYTES;
|
|
13
|
+
};
|
|
14
|
+
/** The same wire representation is used for sizing and transport. */
|
|
15
|
+
export const evalAuthoringResponsesRequestBody = (input) => JSON.stringify({
|
|
16
|
+
model: input.model,
|
|
17
|
+
instructions: input.instructions,
|
|
18
|
+
input: [
|
|
19
|
+
{
|
|
20
|
+
type: "message",
|
|
21
|
+
role: "user",
|
|
22
|
+
content: [{ type: "input_text", text: input.input }]
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
text: {
|
|
26
|
+
format: {
|
|
27
|
+
type: "json_schema",
|
|
28
|
+
name: input.schemaName,
|
|
29
|
+
schema: input.jsonSchema,
|
|
30
|
+
strict: true
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
stream: true,
|
|
34
|
+
...(input.reasoningEffort === undefined
|
|
35
|
+
? {}
|
|
36
|
+
: { reasoning: { effort: input.reasoningEffort } }),
|
|
37
|
+
max_output_tokens: input.maximumOutputTokens
|
|
38
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Effect, FileSystem, Path } from "effect";
|
|
2
|
+
import { EvalEvaluationEvidenceFreshnessError } from "../errors.js";
|
|
3
|
+
import type { EvalEvidenceSource } from "../project-contracts.js";
|
|
4
|
+
export declare function assertCurrentEvaluationEvidence(input: {
|
|
5
|
+
readonly repositoryRoot: string;
|
|
6
|
+
readonly evidenceSources: readonly EvalEvidenceSource[];
|
|
7
|
+
}): Effect.Effect<void, EvalEvaluationEvidenceFreshnessError, FileSystem.FileSystem | Path.Path>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { lstat } from "node:fs/promises";
|
|
3
|
+
import { Effect, FileSystem, Path } from "effect";
|
|
4
|
+
import { EvalEvaluationEvidenceFreshnessError } from "../errors.js";
|
|
5
|
+
import { assertEvaluationEvidenceSources, compileEvaluationEvidence } from "../evaluation-evidence.js";
|
|
6
|
+
import { EVAL_AUTHORING_EVIDENCE_BLOCK_BYTES } from "../evaluation-authoring-policy.js";
|
|
7
|
+
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
|
|
8
|
+
const pathIsWithin = (paths, root, candidate) => {
|
|
9
|
+
const relative = paths.relative(root, candidate);
|
|
10
|
+
return (relative === "" ||
|
|
11
|
+
(relative !== ".." &&
|
|
12
|
+
!relative.startsWith(`..${paths.sep}`) &&
|
|
13
|
+
!paths.isAbsolute(relative)));
|
|
14
|
+
};
|
|
15
|
+
const freshnessError = (detail, cause) => new EvalEvaluationEvidenceFreshnessError({
|
|
16
|
+
detail,
|
|
17
|
+
...(cause === undefined ? {} : { cause })
|
|
18
|
+
});
|
|
19
|
+
export function assertCurrentEvaluationEvidence(input) {
|
|
20
|
+
return Effect.gen(function* () {
|
|
21
|
+
const fs = yield* FileSystem.FileSystem;
|
|
22
|
+
const paths = yield* Path.Path;
|
|
23
|
+
yield* Effect.try({
|
|
24
|
+
try: () => assertEvaluationEvidenceSources(input.evidenceSources),
|
|
25
|
+
catch: (cause) => freshnessError("evaluation evidence metadata failed validation", cause)
|
|
26
|
+
});
|
|
27
|
+
const root = yield* fs
|
|
28
|
+
.realPath(input.repositoryRoot)
|
|
29
|
+
.pipe(Effect.mapError((cause) => freshnessError("evaluation repository root is unavailable", cause)));
|
|
30
|
+
for (const source of input.evidenceSources) {
|
|
31
|
+
const unresolved = paths.resolve(root, source.path);
|
|
32
|
+
const info = yield* Effect.tryPromise({
|
|
33
|
+
try: () => lstat(unresolved),
|
|
34
|
+
catch: (cause) => freshnessError(`evaluation evidence source is unavailable: ${source.path}`, cause)
|
|
35
|
+
});
|
|
36
|
+
if (!info.isFile() || info.isSymbolicLink()) {
|
|
37
|
+
return yield* freshnessError(`evaluation evidence source must remain a regular non-symlink file: ${source.path}`);
|
|
38
|
+
}
|
|
39
|
+
const canonical = yield* fs
|
|
40
|
+
.realPath(unresolved)
|
|
41
|
+
.pipe(Effect.mapError((cause) => freshnessError(`evaluation evidence source cannot be resolved safely: ${source.path}`, cause)));
|
|
42
|
+
if (!pathIsWithin(paths, root, canonical)) {
|
|
43
|
+
return yield* freshnessError(`evaluation evidence source escapes the repository: ${source.path}`);
|
|
44
|
+
}
|
|
45
|
+
const content = yield* fs
|
|
46
|
+
.readFileString(canonical)
|
|
47
|
+
.pipe(Effect.mapError((cause) => freshnessError(`evaluation evidence source is unavailable: ${source.path}`, cause)));
|
|
48
|
+
if (sha256(content) !== source.sourceDigest) {
|
|
49
|
+
return yield* freshnessError(`evaluation evidence source changed after authoring: ${source.path}`);
|
|
50
|
+
}
|
|
51
|
+
if (source.sourceBytes !== undefined &&
|
|
52
|
+
Buffer.byteLength(content, "utf8") !== source.sourceBytes) {
|
|
53
|
+
return yield* freshnessError(`evaluation evidence source byte metadata changed after authoring: ${source.path}`);
|
|
54
|
+
}
|
|
55
|
+
const current = yield* Effect.try({
|
|
56
|
+
try: () => compileEvaluationEvidence({
|
|
57
|
+
sources: [{ path: source.path, content }],
|
|
58
|
+
maximumBlockBytes: EVAL_AUTHORING_EVIDENCE_BLOCK_BYTES
|
|
59
|
+
})[0],
|
|
60
|
+
catch: (cause) => freshnessError(`evaluation evidence source could not be recompiled: ${source.path}`, cause)
|
|
61
|
+
});
|
|
62
|
+
if (source.sourceBlockCount !== undefined &&
|
|
63
|
+
current.sourceBlockCount !== source.sourceBlockCount) {
|
|
64
|
+
return yield* freshnessError(`evaluation evidence source block metadata changed after authoring: ${source.path}`);
|
|
65
|
+
}
|
|
66
|
+
const currentByOrdinal = new Map(current.blocks.map((block) => [block.ordinal, block]));
|
|
67
|
+
for (const block of source.blocks) {
|
|
68
|
+
const currentBlock = currentByOrdinal.get(block.ordinal);
|
|
69
|
+
if (currentBlock === undefined ||
|
|
70
|
+
JSON.stringify(currentBlock) !== JSON.stringify(block)) {
|
|
71
|
+
return yield* freshnessError(`evaluation evidence block changed after authoring: ${block.id}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { RepositoryFoundryError } from "../errors.js";
|
|
3
|
+
export type GitTreeSnapshotV1 = {
|
|
4
|
+
readonly root: string;
|
|
5
|
+
readonly requestedRef: string;
|
|
6
|
+
readonly commit: string;
|
|
7
|
+
readonly tree: string;
|
|
8
|
+
readonly files: readonly string[];
|
|
9
|
+
};
|
|
10
|
+
export declare const captureGitTreeSnapshotV1: (input: {
|
|
11
|
+
readonly repositoryRoot: string;
|
|
12
|
+
readonly requestedRef: string;
|
|
13
|
+
}) => Effect.Effect<{
|
|
14
|
+
root: string;
|
|
15
|
+
requestedRef: string;
|
|
16
|
+
commit: string;
|
|
17
|
+
tree: string;
|
|
18
|
+
files: string[];
|
|
19
|
+
}, RepositoryFoundryError, never>;
|
|
20
|
+
export declare const readGitTreeFileV1: (input: {
|
|
21
|
+
readonly snapshot: GitTreeSnapshotV1;
|
|
22
|
+
readonly path: string;
|
|
23
|
+
}) => Effect.Effect<string, RepositoryFoundryError, never>;
|
|
24
|
+
export declare const readGitChangeEpisodesV1: (input: {
|
|
25
|
+
readonly snapshot: GitTreeSnapshotV1;
|
|
26
|
+
readonly maximumEpisodes?: number;
|
|
27
|
+
}) => Effect.Effect<{
|
|
28
|
+
occurredAt: string;
|
|
29
|
+
subject: string;
|
|
30
|
+
body: string;
|
|
31
|
+
changedPaths: {
|
|
32
|
+
readonly kind: "protocol" | "schema" | "test" | "documentation" | "implementation" | "operational" | "other";
|
|
33
|
+
readonly path: string;
|
|
34
|
+
readonly status: "added" | "modified" | "deleted" | "renamed" | "copied";
|
|
35
|
+
readonly previousPath?: string | undefined;
|
|
36
|
+
}[];
|
|
37
|
+
testPaths: string[];
|
|
38
|
+
implementationPaths: string[];
|
|
39
|
+
protocolPaths: string[];
|
|
40
|
+
behaviorChanging: boolean;
|
|
41
|
+
seedEligible: boolean;
|
|
42
|
+
parentCommit?: string | undefined;
|
|
43
|
+
id: string;
|
|
44
|
+
commit: string;
|
|
45
|
+
}[], RepositoryFoundryError, never>;
|
|
46
|
+
export declare const readGitChangeEpisodeV1: (input: {
|
|
47
|
+
readonly repositoryRoot: string;
|
|
48
|
+
readonly commit: string;
|
|
49
|
+
}) => Effect.Effect<{
|
|
50
|
+
occurredAt: string;
|
|
51
|
+
subject: string;
|
|
52
|
+
body: string;
|
|
53
|
+
changedPaths: {
|
|
54
|
+
readonly kind: "protocol" | "schema" | "test" | "documentation" | "implementation" | "operational" | "other";
|
|
55
|
+
readonly path: string;
|
|
56
|
+
readonly status: "added" | "modified" | "deleted" | "renamed" | "copied";
|
|
57
|
+
readonly previousPath?: string | undefined;
|
|
58
|
+
}[];
|
|
59
|
+
testPaths: string[];
|
|
60
|
+
implementationPaths: string[];
|
|
61
|
+
protocolPaths: string[];
|
|
62
|
+
behaviorChanging: boolean;
|
|
63
|
+
seedEligible: boolean;
|
|
64
|
+
parentCommit?: string | undefined;
|
|
65
|
+
id: string;
|
|
66
|
+
commit: string;
|
|
67
|
+
}, RepositoryFoundryError, never>;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { realpath } from "node:fs/promises";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
import { Effect } from "effect";
|
|
5
|
+
import { RepositoryFoundryError } from "../errors.js";
|
|
6
|
+
const execFilePromise = promisify(execFile);
|
|
7
|
+
const MAX_GIT_OUTPUT_BYTES = 32 * 1024 * 1024;
|
|
8
|
+
const DEFAULT_HISTORY_EPISODES = 200;
|
|
9
|
+
const failure = (operation, detail, cause) => new RepositoryFoundryError({
|
|
10
|
+
operation,
|
|
11
|
+
detail,
|
|
12
|
+
...(cause === undefined ? {} : { cause })
|
|
13
|
+
});
|
|
14
|
+
const git = (root, args, operation) => Effect.tryPromise({
|
|
15
|
+
try: async () => {
|
|
16
|
+
const output = (await execFilePromise("git", ["-C", root, ...args], {
|
|
17
|
+
encoding: "utf8",
|
|
18
|
+
maxBuffer: MAX_GIT_OUTPUT_BYTES,
|
|
19
|
+
windowsHide: true
|
|
20
|
+
}));
|
|
21
|
+
return output.stdout;
|
|
22
|
+
},
|
|
23
|
+
catch: (cause) => failure(operation, `git ${args.join(" ")} failed`, cause)
|
|
24
|
+
});
|
|
25
|
+
const pathKind = (path) => {
|
|
26
|
+
const lower = path.toLowerCase();
|
|
27
|
+
const base = lower.split("/").at(-1) ?? lower;
|
|
28
|
+
if (/(?:^|[._-])(?:test|spec)(?:[._-]|$)/u.test(base) ||
|
|
29
|
+
/(^|\/)(?:test|tests|__tests__)(\/|$)/u.test(lower)) {
|
|
30
|
+
return "test";
|
|
31
|
+
}
|
|
32
|
+
if (/(^|\/)(?:docs?|examples?)(\/|$)/u.test(lower) ||
|
|
33
|
+
/(^|\/)readme(?:\.[^/]*)?$/u.test(lower) ||
|
|
34
|
+
/\.(?:md|mdx)$/u.test(lower)) {
|
|
35
|
+
return "documentation";
|
|
36
|
+
}
|
|
37
|
+
if (/schema/u.test(base))
|
|
38
|
+
return "schema";
|
|
39
|
+
if (/(?:protocol|contracts?)/u.test(base) ||
|
|
40
|
+
/(^|\/)(?:protocols?|contracts?)(\/|$)/u.test(lower)) {
|
|
41
|
+
return "protocol";
|
|
42
|
+
}
|
|
43
|
+
if (/(^|\/)(?:\.github|deploy|infra|scripts?|docker)(\/|$)/u.test(lower) ||
|
|
44
|
+
/(?:dockerfile|compose\.ya?ml)$/u.test(base)) {
|
|
45
|
+
return "operational";
|
|
46
|
+
}
|
|
47
|
+
if (/\.(?:[cm]?[jt]sx?|py|go|rs|java|kt|swift|rb|php|cs|cpp|cc|c|h)$/u.test(lower)) {
|
|
48
|
+
return "implementation";
|
|
49
|
+
}
|
|
50
|
+
return "other";
|
|
51
|
+
};
|
|
52
|
+
const changedStatus = (raw) => {
|
|
53
|
+
const code = raw[0];
|
|
54
|
+
if (code === "A")
|
|
55
|
+
return "added";
|
|
56
|
+
if (code === "D")
|
|
57
|
+
return "deleted";
|
|
58
|
+
if (code === "R")
|
|
59
|
+
return "renamed";
|
|
60
|
+
if (code === "C")
|
|
61
|
+
return "copied";
|
|
62
|
+
return "modified";
|
|
63
|
+
};
|
|
64
|
+
const parseChangedPaths = (value) => {
|
|
65
|
+
const tokens = value.split("\0").filter((token) => token.length > 0);
|
|
66
|
+
const paths = [];
|
|
67
|
+
for (let index = 0; index < tokens.length;) {
|
|
68
|
+
const rawStatus = tokens[index++];
|
|
69
|
+
if (rawStatus === undefined)
|
|
70
|
+
break;
|
|
71
|
+
const status = changedStatus(rawStatus);
|
|
72
|
+
if (status === "renamed" || status === "copied") {
|
|
73
|
+
const previousPath = tokens[index++];
|
|
74
|
+
const path = tokens[index++];
|
|
75
|
+
if (previousPath === undefined || path === undefined)
|
|
76
|
+
break;
|
|
77
|
+
paths.push({
|
|
78
|
+
path,
|
|
79
|
+
previousPath,
|
|
80
|
+
status,
|
|
81
|
+
kind: pathKind(path)
|
|
82
|
+
});
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const path = tokens[index++];
|
|
86
|
+
if (path === undefined)
|
|
87
|
+
break;
|
|
88
|
+
paths.push({ path, status, kind: pathKind(path) });
|
|
89
|
+
}
|
|
90
|
+
return paths;
|
|
91
|
+
};
|
|
92
|
+
const metadata = (value) => {
|
|
93
|
+
const [commit = "", parents = "", occurredAt = "", subject = "", ...body] = value.split("\0");
|
|
94
|
+
const parentCommit = parents.split(/\s+/u).filter(Boolean)[0];
|
|
95
|
+
return {
|
|
96
|
+
commit,
|
|
97
|
+
parentCount: parents.split(/\s+/u).filter(Boolean).length,
|
|
98
|
+
...(parentCommit === undefined ? {} : { parentCommit }),
|
|
99
|
+
occurredAt,
|
|
100
|
+
subject,
|
|
101
|
+
body: body.join("\0").trim()
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
export const captureGitTreeSnapshotV1 = Effect.fn("RepositoryFoundry.captureGitTreeSnapshot")(function* (input) {
|
|
105
|
+
const root = yield* Effect.tryPromise({
|
|
106
|
+
try: () => realpath(input.repositoryRoot),
|
|
107
|
+
catch: (cause) => failure("resolve-repository", `failed to resolve ${JSON.stringify(input.repositoryRoot)}`, cause)
|
|
108
|
+
});
|
|
109
|
+
const requestedRef = input.requestedRef.trim();
|
|
110
|
+
if (requestedRef.length === 0) {
|
|
111
|
+
return yield* failure("resolve-repository", "requested Git ref must not be empty");
|
|
112
|
+
}
|
|
113
|
+
const commit = (yield* git(root, ["rev-parse", "--verify", `${requestedRef}^{commit}`], "read-git-tree")).trim();
|
|
114
|
+
const tree = (yield* git(root, ["rev-parse", "--verify", `${requestedRef}^{tree}`], "read-git-tree")).trim();
|
|
115
|
+
const files = (yield* git(root, ["ls-tree", "-r", "--name-only", "-z", tree], "read-git-tree"))
|
|
116
|
+
.split("\0")
|
|
117
|
+
.filter((path) => path.length > 0)
|
|
118
|
+
.sort();
|
|
119
|
+
return { root, requestedRef, commit, tree, files };
|
|
120
|
+
});
|
|
121
|
+
export const readGitTreeFileV1 = Effect.fn("RepositoryFoundry.readGitTreeFile")(function* (input) {
|
|
122
|
+
if (!input.snapshot.files.includes(input.path) ||
|
|
123
|
+
input.path.startsWith("/") ||
|
|
124
|
+
input.path.split("/").includes("..") ||
|
|
125
|
+
input.path.includes("\0")) {
|
|
126
|
+
return yield* failure("read-git-tree", `path is not in the frozen Git tree: ${JSON.stringify(input.path)}`);
|
|
127
|
+
}
|
|
128
|
+
return yield* git(input.snapshot.root, ["show", `${input.snapshot.tree}:${input.path}`], "read-git-tree");
|
|
129
|
+
});
|
|
130
|
+
export const readGitChangeEpisodesV1 = Effect.fn("RepositoryFoundry.readGitChangeEpisodes")(function* (input) {
|
|
131
|
+
const maximumEpisodes = Math.max(1, Math.min(input.maximumEpisodes ?? DEFAULT_HISTORY_EPISODES, 1_000));
|
|
132
|
+
const commits = (yield* git(input.snapshot.root, [
|
|
133
|
+
"rev-list",
|
|
134
|
+
"--reverse",
|
|
135
|
+
"--no-merges",
|
|
136
|
+
`--max-count=${String(maximumEpisodes)}`,
|
|
137
|
+
input.snapshot.commit
|
|
138
|
+
], "read-git-history"))
|
|
139
|
+
.split(/\r?\n/u)
|
|
140
|
+
.filter(Boolean);
|
|
141
|
+
return yield* Effect.forEach(commits, (commit) => readGitChangeEpisodeV1({
|
|
142
|
+
repositoryRoot: input.snapshot.root,
|
|
143
|
+
commit
|
|
144
|
+
}));
|
|
145
|
+
});
|
|
146
|
+
export const readGitChangeEpisodeV1 = Effect.fn("RepositoryFoundry.readGitChangeEpisode")(function* (input) {
|
|
147
|
+
const info = metadata(yield* git(input.repositoryRoot, ["show", "-s", "--format=%H%x00%P%x00%cI%x00%s%x00%b", input.commit], "read-git-history"));
|
|
148
|
+
const changedPaths = parseChangedPaths(yield* git(input.repositoryRoot, ["diff-tree", "--root", "--no-commit-id", "--name-status", "-r", "-z", "-M", input.commit], "read-git-history"));
|
|
149
|
+
const testPaths = changedPaths.filter((path) => path.kind === "test").map((path) => path.path);
|
|
150
|
+
const implementationPaths = changedPaths
|
|
151
|
+
.filter((path) => path.kind === "implementation")
|
|
152
|
+
.map((path) => path.path);
|
|
153
|
+
const protocolPaths = changedPaths
|
|
154
|
+
.filter((path) => path.kind === "protocol" || path.kind === "schema")
|
|
155
|
+
.map((path) => path.path);
|
|
156
|
+
const behaviorChanging = implementationPaths.length > 0 || protocolPaths.length > 0;
|
|
157
|
+
return {
|
|
158
|
+
id: `git-${info.commit}`,
|
|
159
|
+
commit: info.commit,
|
|
160
|
+
...(info.parentCommit === undefined ? {} : { parentCommit: info.parentCommit }),
|
|
161
|
+
occurredAt: info.occurredAt,
|
|
162
|
+
subject: info.subject,
|
|
163
|
+
body: info.body,
|
|
164
|
+
changedPaths,
|
|
165
|
+
testPaths,
|
|
166
|
+
implementationPaths,
|
|
167
|
+
protocolPaths,
|
|
168
|
+
behaviorChanging,
|
|
169
|
+
seedEligible: behaviorChanging && testPaths.length > 0 && info.parentCount === 1
|
|
170
|
+
};
|
|
171
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { RepositoryFoundryError } from "../errors.js";
|
|
3
|
+
import type { RepositoryChangeEpisodeV1 } from "../repository-behavior-protocol.js";
|
|
4
|
+
import { type RepositoryIntegratedHistoryProvenanceV1 } from "../repository-foundry-plan-protocol.js";
|
|
5
|
+
export type IntegratedRepositoryHistoryEpisodeV1 = {
|
|
6
|
+
readonly episode: RepositoryChangeEpisodeV1;
|
|
7
|
+
readonly provenance: RepositoryIntegratedHistoryProvenanceV1;
|
|
8
|
+
};
|
|
9
|
+
export declare const discoverIntegratedRepositoryHistoryV1: (input: {
|
|
10
|
+
readonly repositoryRoot: string;
|
|
11
|
+
readonly requestedRef: string;
|
|
12
|
+
readonly requestedTipCommit: string;
|
|
13
|
+
readonly requestedTipTree: string;
|
|
14
|
+
readonly integrationCommits: readonly string[];
|
|
15
|
+
}) => Effect.Effect<IntegratedRepositoryHistoryEpisodeV1[], RepositoryFoundryError, never>;
|
|
16
|
+
export declare const validateIntegratedRepositoryHistoryV1: (input: {
|
|
17
|
+
readonly repositoryRoot: string;
|
|
18
|
+
readonly referenceCommit: string;
|
|
19
|
+
readonly initialCommit: string;
|
|
20
|
+
readonly provenance: RepositoryIntegratedHistoryProvenanceV1;
|
|
21
|
+
}) => Effect.Effect<undefined, RepositoryFoundryError, never>;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import { Effect } from "effect";
|
|
4
|
+
import { RepositoryFoundryError } from "../errors.js";
|
|
5
|
+
import { REPOSITORY_INTEGRATED_HISTORY_MAXIMUM_PATHS, validIntegratedHistoryProvenanceV1 } from "../repository-foundry-plan-protocol.js";
|
|
6
|
+
import { readGitChangeEpisodeV1 } from "./git-task-history.js";
|
|
7
|
+
const execFilePromise = promisify(execFile);
|
|
8
|
+
const MAXIMUM_REFS = 64;
|
|
9
|
+
const MAXIMUM_EXTRA_EPISODES = 128;
|
|
10
|
+
const MAXIMUM_INTEGRATION_SNAPSHOTS = 200;
|
|
11
|
+
const MAXIMUM_BLOB_CHECKS = 131_072;
|
|
12
|
+
const objectId = /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/u;
|
|
13
|
+
const failure = (detail, cause) => new RepositoryFoundryError({
|
|
14
|
+
operation: "read-git-history",
|
|
15
|
+
detail,
|
|
16
|
+
...(cause === undefined ? {} : { cause })
|
|
17
|
+
});
|
|
18
|
+
const git = (root, args) => Effect.tryPromise({
|
|
19
|
+
try: async () => (await execFilePromise("git", ["-C", root, "--literal-pathspecs", ...args], {
|
|
20
|
+
encoding: "utf8",
|
|
21
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
22
|
+
timeout: 15_000,
|
|
23
|
+
windowsHide: true
|
|
24
|
+
})).stdout,
|
|
25
|
+
catch: (cause) => failure("failed to read immutable integrated history Git facts", cause)
|
|
26
|
+
});
|
|
27
|
+
const lines = (text) => text.trim().split(/\r?\n/u).filter(Boolean);
|
|
28
|
+
const behaviorPaths = (episode) => [
|
|
29
|
+
...new Set([...episode.implementationPaths, ...episode.protocolPaths, ...episode.testPaths])
|
|
30
|
+
].sort();
|
|
31
|
+
const recoverable = (episode) => episode.seedEligible &&
|
|
32
|
+
episode.parentCommit !== undefined &&
|
|
33
|
+
!episode.changedPaths.some(({ status }) => status === "deleted" || status === "renamed" || status === "copied") &&
|
|
34
|
+
behaviorPaths(episode).length <= REPOSITORY_INTEGRATED_HISTORY_MAXIMUM_PATHS &&
|
|
35
|
+
!behaviorPaths(episode).some((path) => path.length > 1_024 ||
|
|
36
|
+
path.includes("\0") ||
|
|
37
|
+
path.includes("\\") ||
|
|
38
|
+
path.split("/").some((part) => part === "" || part === "." || part === "..") ||
|
|
39
|
+
/(^|\/)(?:docs?|examples?)(\/|$)/iu.test(path));
|
|
40
|
+
// Read object IDs, never execute retained code or follow tree symlinks. Missing
|
|
41
|
+
// paths, submodules and symlinks cannot furnish regular-file integration proof.
|
|
42
|
+
const pathBlobs = Effect.fnUntraced(function* (root, commit, paths) {
|
|
43
|
+
const result = new Map();
|
|
44
|
+
if (paths.length === 0)
|
|
45
|
+
return result;
|
|
46
|
+
const requested = new Set(paths);
|
|
47
|
+
for (let offset = 0; offset < paths.length; offset += 128) {
|
|
48
|
+
const output = yield* git(root, [
|
|
49
|
+
"ls-tree",
|
|
50
|
+
"-r",
|
|
51
|
+
"-z",
|
|
52
|
+
commit,
|
|
53
|
+
"--",
|
|
54
|
+
...paths.slice(offset, offset + 128)
|
|
55
|
+
]);
|
|
56
|
+
for (const entry of output.split("\0")) {
|
|
57
|
+
const match = /^(100644|100755) blob ([a-f0-9]+)\t([\s\S]+)$/u.exec(entry);
|
|
58
|
+
if (match !== null && requested.has(match[3]) && objectId.test(match[2])) {
|
|
59
|
+
result.set(match[3], match[2]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
});
|
|
65
|
+
export const discoverIntegratedRepositoryHistoryV1 = Effect.fn("RepositoryFoundry.discoverIntegratedRepositoryHistory")(function* (input) {
|
|
66
|
+
if (!objectId.test(input.requestedTipCommit) || !objectId.test(input.requestedTipTree)) {
|
|
67
|
+
return yield* failure("integrated history discovery requires an immutable requested tip");
|
|
68
|
+
}
|
|
69
|
+
const root = input.repositoryRoot;
|
|
70
|
+
const tree = (yield* git(root, ["rev-parse", `${input.requestedTipCommit}^{tree}`])).trim();
|
|
71
|
+
if (tree !== input.requestedTipTree)
|
|
72
|
+
return yield* failure("requested tip tree does not match Git");
|
|
73
|
+
const reachable = lines(yield* git(root, [
|
|
74
|
+
"rev-list",
|
|
75
|
+
`--max-count=${MAXIMUM_INTEGRATION_SNAPSHOTS}`,
|
|
76
|
+
input.requestedTipCommit
|
|
77
|
+
]));
|
|
78
|
+
const permitted = new Set([input.requestedTipCommit, ...input.integrationCommits]);
|
|
79
|
+
const integrations = reachable.filter((commit) => permitted.has(commit));
|
|
80
|
+
// Recent retained local/remote branch tips are bounded, deterministic input
|
|
81
|
+
// candidates. A branch name or ancestry by itself never certifies integration.
|
|
82
|
+
const refs = [
|
|
83
|
+
...new Set(lines(yield* git(root, [
|
|
84
|
+
"for-each-ref",
|
|
85
|
+
"--sort=refname",
|
|
86
|
+
"--sort=-committerdate",
|
|
87
|
+
`--count=${MAXIMUM_REFS}`,
|
|
88
|
+
"--format=%(objectname)",
|
|
89
|
+
"refs/heads",
|
|
90
|
+
"refs/remotes"
|
|
91
|
+
])))
|
|
92
|
+
].filter((commit) => objectId.test(commit));
|
|
93
|
+
if (refs.length === 0)
|
|
94
|
+
return [];
|
|
95
|
+
const retained = lines(yield* git(root, [
|
|
96
|
+
"rev-list",
|
|
97
|
+
"--no-merges",
|
|
98
|
+
`--max-count=${MAXIMUM_EXTRA_EPISODES}`,
|
|
99
|
+
...refs,
|
|
100
|
+
"--not",
|
|
101
|
+
input.requestedTipCommit
|
|
102
|
+
]));
|
|
103
|
+
const candidates = [];
|
|
104
|
+
for (const commit of retained) {
|
|
105
|
+
const episode = yield* readGitChangeEpisodeV1({ repositoryRoot: root, commit });
|
|
106
|
+
if (!recoverable(episode))
|
|
107
|
+
continue;
|
|
108
|
+
const paths = behaviorPaths(episode);
|
|
109
|
+
const blobs = yield* pathBlobs(root, commit, paths);
|
|
110
|
+
if (blobs.size === paths.length)
|
|
111
|
+
candidates.push({ episode, blobs });
|
|
112
|
+
}
|
|
113
|
+
const allPaths = [...new Set(candidates.flatMap(({ episode }) => behaviorPaths(episode)))].sort();
|
|
114
|
+
const results = [];
|
|
115
|
+
const certified = new Set();
|
|
116
|
+
let blobChecks = retained.length * REPOSITORY_INTEGRATED_HISTORY_MAXIMUM_PATHS;
|
|
117
|
+
for (const integrationCommit of integrations) {
|
|
118
|
+
if (allPaths.length === 0 || blobChecks + allPaths.length > MAXIMUM_BLOB_CHECKS)
|
|
119
|
+
break;
|
|
120
|
+
blobChecks += allPaths.length;
|
|
121
|
+
const integrated = yield* pathBlobs(root, integrationCommit, allPaths);
|
|
122
|
+
for (const { episode, blobs } of candidates) {
|
|
123
|
+
if (certified.has(episode.commit) ||
|
|
124
|
+
![...blobs].every(([path, blob]) => integrated.get(path) === blob))
|
|
125
|
+
continue;
|
|
126
|
+
certified.add(episode.commit);
|
|
127
|
+
results.push({
|
|
128
|
+
episode,
|
|
129
|
+
provenance: {
|
|
130
|
+
method: "integrated-retained-history-v1",
|
|
131
|
+
requestedRef: input.requestedRef,
|
|
132
|
+
requestedTipCommit: input.requestedTipCommit,
|
|
133
|
+
requestedTipTree: input.requestedTipTree,
|
|
134
|
+
integrationCommit,
|
|
135
|
+
pathBlobs: [...blobs]
|
|
136
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
137
|
+
.map(([path, blob]) => ({ path, blob }))
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return results;
|
|
143
|
+
});
|
|
144
|
+
export const validateIntegratedRepositoryHistoryV1 = Effect.fn("RepositoryFoundry.validateIntegratedRepositoryHistory")(function* (input) {
|
|
145
|
+
const { provenance: proof, repositoryRoot: root } = input;
|
|
146
|
+
if (!validIntegratedHistoryProvenanceV1(proof) ||
|
|
147
|
+
!objectId.test(input.referenceCommit) ||
|
|
148
|
+
!objectId.test(input.initialCommit)) {
|
|
149
|
+
return yield* failure("integrated history provenance has invalid identifiers or path proof");
|
|
150
|
+
}
|
|
151
|
+
const tree = (yield* git(root, ["rev-parse", `${proof.requestedTipCommit}^{tree}`])).trim();
|
|
152
|
+
const ancestor = (yield* git(root, [
|
|
153
|
+
"merge-base",
|
|
154
|
+
proof.integrationCommit,
|
|
155
|
+
proof.requestedTipCommit
|
|
156
|
+
])).trim();
|
|
157
|
+
if (tree !== proof.requestedTipTree || ancestor !== proof.integrationCommit) {
|
|
158
|
+
return yield* failure("integrated history proof does not match the requested reachable snapshot");
|
|
159
|
+
}
|
|
160
|
+
const episode = yield* readGitChangeEpisodeV1({
|
|
161
|
+
repositoryRoot: root,
|
|
162
|
+
commit: input.referenceCommit
|
|
163
|
+
});
|
|
164
|
+
const paths = behaviorPaths(episode);
|
|
165
|
+
if (!recoverable(episode) ||
|
|
166
|
+
episode.parentCommit !== input.initialCommit ||
|
|
167
|
+
JSON.stringify(paths) !== JSON.stringify(proof.pathBlobs.map(({ path }) => path))) {
|
|
168
|
+
return yield* failure("integrated history proof does not cover the complete eligible historical change");
|
|
169
|
+
}
|
|
170
|
+
const reference = yield* pathBlobs(root, input.referenceCommit, paths);
|
|
171
|
+
const integrated = yield* pathBlobs(root, proof.integrationCommit, paths);
|
|
172
|
+
if (!proof.pathBlobs.every(({ path, blob }) => reference.get(path) === blob && integrated.get(path) === blob)) {
|
|
173
|
+
return yield* failure("integrated history path blob proof does not match Git objects");
|
|
174
|
+
}
|
|
175
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type RepositoryCommandDiagnosticV1 = Readonly<{
|
|
2
|
+
text: string;
|
|
3
|
+
truncated: boolean;
|
|
4
|
+
}>;
|
|
5
|
+
export declare function sanitizeRepositoryCommandOutputV1(source: string): string;
|
|
6
|
+
export declare function sanitizeRepositoryCommandDiagnosticV1(stdout: string, stderr: string, inputTruncated?: boolean): RepositoryCommandDiagnosticV1 | undefined;
|
|
7
|
+
export declare function encodeRepositoryCommandDiagnosticV1(diagnostic: string): string;
|
|
8
|
+
export declare function decodeRepositoryCommandDiagnosticV1(encoded: string): string | undefined;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const COMMAND_DIAGNOSTIC_LIMIT = 3_072;
|
|
2
|
+
const REDACTED = "[redacted]";
|
|
3
|
+
const redactSensitiveQueryParameters = (value) => value.replace(/([?&](?:access_token|api[_-]?key|auth|authorization|client_secret|credential|key|password|secret|signature|token)=)[^&#\s]*/giu, `$1${REDACTED}`);
|
|
4
|
+
export function sanitizeRepositoryCommandOutputV1(source) {
|
|
5
|
+
return (redactSensitiveQueryParameters(source)
|
|
6
|
+
.replace(/-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/gu, REDACTED)
|
|
7
|
+
.replace(/((?:https?|ssh):\/\/)[^/\s@]+@/giu, `$1${REDACTED}@`)
|
|
8
|
+
.replace(/\b(?:github_pat_[A-Za-z0-9_]{20,}|gh[pousr]_[A-Za-z0-9]{20,})\b/gu, REDACTED)
|
|
9
|
+
.replace(/\b(?:sk|pplx)-[A-Za-z0-9_-]{20,}\b|\bhf_[A-Za-z0-9]{20,}\b|\bnpm_[A-Za-z0-9]{20,}\b|\bxox[baprs]-[A-Za-z0-9-]{20,}\b/gu, REDACTED)
|
|
10
|
+
.replace(/\bAKIA[0-9A-Z]{16}\b/gu, REDACTED)
|
|
11
|
+
.replace(/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/gu, REDACTED)
|
|
12
|
+
.replace(/(\bBearer\s+)[^\s"',;]+/giu, `$1${REDACTED}`)
|
|
13
|
+
.replace(/(\bAuthorization\b\s*[:=]\s*)(?:"[^"\r\n]*"|'[^'\r\n]*'|[^\s,;]+)/giu, `$1${REDACTED}`)
|
|
14
|
+
.replace(/(\b(?:api[_-]?key|auth|client[_-]?secret|credential|password|passwd|secret|token)\b\s*[:=]\s*)(?:"[^"\r\n]*"|'[^'\r\n]*'|[^\s,;]+)/giu, `$1${REDACTED}`)
|
|
15
|
+
// Compiler and package-manager output commonly includes ANSI styling.
|
|
16
|
+
// Persist plain text so the same bounded output is readable in JSON,
|
|
17
|
+
// HTML, and OpenTelemetry log backends.
|
|
18
|
+
.replace(/\u001B(?:\[[0-?]*[ -/]*[@-~]|\][^\u0007]*(?:\u0007|\u001B\\))/gu, ""));
|
|
19
|
+
}
|
|
20
|
+
export function sanitizeRepositoryCommandDiagnosticV1(stdout, stderr, inputTruncated = false) {
|
|
21
|
+
const source = [stderr, stdout]
|
|
22
|
+
.map((value) => value.trim())
|
|
23
|
+
.filter(Boolean)
|
|
24
|
+
.join("\n");
|
|
25
|
+
if (source.length === 0)
|
|
26
|
+
return undefined;
|
|
27
|
+
const redacted = sanitizeRepositoryCommandOutputV1(source);
|
|
28
|
+
const truncated = inputTruncated || redacted.length > COMMAND_DIAGNOSTIC_LIMIT;
|
|
29
|
+
const text = redacted.slice(0, COMMAND_DIAGNOSTIC_LIMIT).trimEnd();
|
|
30
|
+
return text.length === 0 ? undefined : { text, truncated };
|
|
31
|
+
}
|
|
32
|
+
export function encodeRepositoryCommandDiagnosticV1(diagnostic) {
|
|
33
|
+
return Buffer.from(diagnostic, "utf8").toString("base64url");
|
|
34
|
+
}
|
|
35
|
+
export function decodeRepositoryCommandDiagnosticV1(encoded) {
|
|
36
|
+
try {
|
|
37
|
+
const bytes = Buffer.from(encoded, "base64url");
|
|
38
|
+
if (bytes.toString("base64url") !== encoded)
|
|
39
|
+
return undefined;
|
|
40
|
+
const decoded = bytes.toString("utf8");
|
|
41
|
+
return decoded.length > 0 && decoded.length <= COMMAND_DIAGNOSTIC_LIMIT ? decoded : undefined;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RepositoryCommandInvocationResultV1, RepositoryCommandResultV1 } from "../repository-execution-protocol.js";
|
|
2
|
+
/** Process completion and evidence completeness are prerequisites, not grades. */
|
|
3
|
+
export declare const repositoryCommandExecutionIncompleteV1: (result: RepositoryCommandInvocationResultV1) => boolean;
|
|
4
|
+
type RepositoryCommandTestEvidenceV1 = {
|
|
5
|
+
readonly outcome: "pass" | "fail" | "unknown";
|
|
6
|
+
readonly detail: string;
|
|
7
|
+
/** A repair hint only. This never turns an unclassified error into a semantic failure. */
|
|
8
|
+
readonly inconclusiveReason?: "unattributed-test-failure";
|
|
9
|
+
};
|
|
10
|
+
export declare const repositoryCommandTestEvidenceV1: (result: RepositoryCommandResultV1 | undefined, recipeId: string) => RepositoryCommandTestEvidenceV1;
|
|
11
|
+
/** A diagnostic probe uses the same evidence rules as admission, never exit status alone. */
|
|
12
|
+
export declare const repositoryCommandProbeOutcomeV1: (results: readonly RepositoryCommandResultV1[]) => "completed" | "scientific_rejection" | "environment_blocked";
|
|
13
|
+
export {};
|