audit-tools 0.28.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/README.audit.md +223 -0
- package/README.md +42 -0
- package/README.remediate.md +113 -0
- package/audit-code-wrapper-build.mjs +185 -0
- package/audit-code-wrapper-install-hosts.mjs +1079 -0
- package/audit-code-wrapper-install-renderers.mjs +58 -0
- package/audit-code-wrapper-io.mjs +155 -0
- package/audit-code-wrapper-legacy.mjs +125 -0
- package/audit-code-wrapper-lib.mjs +314 -0
- package/audit-code-wrapper-opencode.mjs +241 -0
- package/audit-code.mjs +12 -0
- package/dispatch/lens-definitions.json +46 -0
- package/dispatch/merge-results.mjs +110 -0
- package/dispatch/validate-result.mjs +59 -0
- package/dispatch/validate.mjs +16 -0
- package/dist/audit/adapters/coverageSummary.d.ts +9 -0
- package/dist/audit/adapters/coverageSummary.d.ts.map +1 -0
- package/dist/audit/adapters/coverageSummary.js +18 -0
- package/dist/audit/adapters/coverageSummary.js.map +1 -0
- package/dist/audit/adapters/eslint.d.ts +14 -0
- package/dist/audit/adapters/eslint.d.ts.map +1 -0
- package/dist/audit/adapters/eslint.js +28 -0
- package/dist/audit/adapters/eslint.js.map +1 -0
- package/dist/audit/adapters/normalizeExternal.d.ts +13 -0
- package/dist/audit/adapters/normalizeExternal.d.ts.map +1 -0
- package/dist/audit/adapters/normalizeExternal.js +44 -0
- package/dist/audit/adapters/normalizeExternal.js.map +1 -0
- package/dist/audit/adapters/npmAudit.d.ts +16 -0
- package/dist/audit/adapters/npmAudit.d.ts.map +1 -0
- package/dist/audit/adapters/npmAudit.js +24 -0
- package/dist/audit/adapters/npmAudit.js.map +1 -0
- package/dist/audit/adapters/semgrep.d.ts +23 -0
- package/dist/audit/adapters/semgrep.d.ts.map +1 -0
- package/dist/audit/adapters/semgrep.js +40 -0
- package/dist/audit/adapters/semgrep.js.map +1 -0
- package/dist/audit/cli/advanceAuditCommand.d.ts +2 -0
- package/dist/audit/cli/advanceAuditCommand.d.ts.map +1 -0
- package/dist/audit/cli/advanceAuditCommand.js +95 -0
- package/dist/audit/cli/advanceAuditCommand.js.map +1 -0
- package/dist/audit/cli/args.d.ts +95 -0
- package/dist/audit/cli/args.d.ts.map +1 -0
- package/dist/audit/cli/args.js +274 -0
- package/dist/audit/cli/args.js.map +1 -0
- package/dist/audit/cli/auditStep.d.ts +34 -0
- package/dist/audit/cli/auditStep.d.ts.map +1 -0
- package/dist/audit/cli/auditStep.js +162 -0
- package/dist/audit/cli/auditStep.js.map +1 -0
- package/dist/audit/cli/cleanup.d.ts +12 -0
- package/dist/audit/cli/cleanup.d.ts.map +1 -0
- package/dist/audit/cli/cleanup.js +44 -0
- package/dist/audit/cli/cleanup.js.map +1 -0
- package/dist/audit/cli/cleanupCommand.d.ts +2 -0
- package/dist/audit/cli/cleanupCommand.d.ts.map +1 -0
- package/dist/audit/cli/cleanupCommand.js +25 -0
- package/dist/audit/cli/cleanupCommand.js.map +1 -0
- package/dist/audit/cli/conceptualDispatch.d.ts +74 -0
- package/dist/audit/cli/conceptualDispatch.d.ts.map +1 -0
- package/dist/audit/cli/conceptualDispatch.js +118 -0
- package/dist/audit/cli/conceptualDispatch.js.map +1 -0
- package/dist/audit/cli/confirmIntentStep.d.ts +25 -0
- package/dist/audit/cli/confirmIntentStep.d.ts.map +1 -0
- package/dist/audit/cli/confirmIntentStep.js +210 -0
- package/dist/audit/cli/confirmIntentStep.js.map +1 -0
- package/dist/audit/cli/dispatch/packetFilter.d.ts +102 -0
- package/dist/audit/cli/dispatch/packetFilter.d.ts.map +1 -0
- package/dist/audit/cli/dispatch/packetFilter.js +148 -0
- package/dist/audit/cli/dispatch/packetFilter.js.map +1 -0
- package/dist/audit/cli/dispatch/packetPrompt.d.ts +48 -0
- package/dist/audit/cli/dispatch/packetPrompt.d.ts.map +1 -0
- package/dist/audit/cli/dispatch/packetPrompt.js +258 -0
- package/dist/audit/cli/dispatch/packetPrompt.js.map +1 -0
- package/dist/audit/cli/dispatch/paths.d.ts +7 -0
- package/dist/audit/cli/dispatch/paths.d.ts.map +1 -0
- package/dist/audit/cli/dispatch/paths.js +38 -0
- package/dist/audit/cli/dispatch/paths.js.map +1 -0
- package/dist/audit/cli/dispatch/quotaPool.d.ts +75 -0
- package/dist/audit/cli/dispatch/quotaPool.d.ts.map +1 -0
- package/dist/audit/cli/dispatch/quotaPool.js +163 -0
- package/dist/audit/cli/dispatch/quotaPool.js.map +1 -0
- package/dist/audit/cli/dispatch/tierRouting.d.ts +36 -0
- package/dist/audit/cli/dispatch/tierRouting.d.ts.map +1 -0
- package/dist/audit/cli/dispatch/tierRouting.js +121 -0
- package/dist/audit/cli/dispatch/tierRouting.js.map +1 -0
- package/dist/audit/cli/dispatch/types.d.ts +90 -0
- package/dist/audit/cli/dispatch/types.d.ts.map +1 -0
- package/dist/audit/cli/dispatch/types.js +15 -0
- package/dist/audit/cli/dispatch/types.js.map +1 -0
- package/dist/audit/cli/dispatch.d.ts +29 -0
- package/dist/audit/cli/dispatch.d.ts.map +1 -0
- package/dist/audit/cli/dispatch.js +303 -0
- package/dist/audit/cli/dispatch.js.map +1 -0
- package/dist/audit/cli/dispatchStatusCommand.d.ts +2 -0
- package/dist/audit/cli/dispatchStatusCommand.d.ts.map +1 -0
- package/dist/audit/cli/dispatchStatusCommand.js +81 -0
- package/dist/audit/cli/dispatchStatusCommand.js.map +1 -0
- package/dist/audit/cli/envelope.d.ts +50 -0
- package/dist/audit/cli/envelope.d.ts.map +1 -0
- package/dist/audit/cli/envelope.js +69 -0
- package/dist/audit/cli/envelope.js.map +1 -0
- package/dist/audit/cli/explainTaskCommand.d.ts +2 -0
- package/dist/audit/cli/explainTaskCommand.d.ts.map +1 -0
- package/dist/audit/cli/explainTaskCommand.js +34 -0
- package/dist/audit/cli/explainTaskCommand.js.map +1 -0
- package/dist/audit/cli/importExternalAnalyzerCommand.d.ts +2 -0
- package/dist/audit/cli/importExternalAnalyzerCommand.d.ts.map +1 -0
- package/dist/audit/cli/importExternalAnalyzerCommand.js +25 -0
- package/dist/audit/cli/importExternalAnalyzerCommand.js.map +1 -0
- package/dist/audit/cli/ingestResultsCommand.d.ts +2 -0
- package/dist/audit/cli/ingestResultsCommand.d.ts.map +1 -0
- package/dist/audit/cli/ingestResultsCommand.js +42 -0
- package/dist/audit/cli/ingestResultsCommand.js.map +1 -0
- package/dist/audit/cli/intakeCommand.d.ts +2 -0
- package/dist/audit/cli/intakeCommand.d.ts.map +1 -0
- package/dist/audit/cli/intakeCommand.js +18 -0
- package/dist/audit/cli/intakeCommand.js.map +1 -0
- package/dist/audit/cli/lineIndex.d.ts +5 -0
- package/dist/audit/cli/lineIndex.d.ts.map +1 -0
- package/dist/audit/cli/lineIndex.js +70 -0
- package/dist/audit/cli/lineIndex.js.map +1 -0
- package/dist/audit/cli/mergeAndIngestCommand.d.ts +46 -0
- package/dist/audit/cli/mergeAndIngestCommand.d.ts.map +1 -0
- package/dist/audit/cli/mergeAndIngestCommand.js +541 -0
- package/dist/audit/cli/mergeAndIngestCommand.js.map +1 -0
- package/dist/audit/cli/nextStepCommand.d.ts +22 -0
- package/dist/audit/cli/nextStepCommand.d.ts.map +1 -0
- package/dist/audit/cli/nextStepCommand.js +531 -0
- package/dist/audit/cli/nextStepCommand.js.map +1 -0
- package/dist/audit/cli/nextStepHelpers.d.ts +303 -0
- package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -0
- package/dist/audit/cli/nextStepHelpers.js +861 -0
- package/dist/audit/cli/nextStepHelpers.js.map +1 -0
- package/dist/audit/cli/paths.d.ts +2 -0
- package/dist/audit/cli/paths.d.ts.map +1 -0
- package/dist/audit/cli/paths.js +10 -0
- package/dist/audit/cli/paths.js.map +1 -0
- package/dist/audit/cli/planCommand.d.ts +2 -0
- package/dist/audit/cli/planCommand.d.ts.map +1 -0
- package/dist/audit/cli/planCommand.js +17 -0
- package/dist/audit/cli/planCommand.js.map +1 -0
- package/dist/audit/cli/prepareDispatchCommand.d.ts +2 -0
- package/dist/audit/cli/prepareDispatchCommand.d.ts.map +1 -0
- package/dist/audit/cli/prepareDispatchCommand.js +37 -0
- package/dist/audit/cli/prepareDispatchCommand.js.map +1 -0
- package/dist/audit/cli/prompts.d.ts +54 -0
- package/dist/audit/cli/prompts.d.ts.map +1 -0
- package/dist/audit/cli/prompts.js +324 -0
- package/dist/audit/cli/prompts.js.map +1 -0
- package/dist/audit/cli/quotaCommand.d.ts +2 -0
- package/dist/audit/cli/quotaCommand.d.ts.map +1 -0
- package/dist/audit/cli/quotaCommand.js +64 -0
- package/dist/audit/cli/quotaCommand.js.map +1 -0
- package/dist/audit/cli/requeueCommand.d.ts +2 -0
- package/dist/audit/cli/requeueCommand.d.ts.map +1 -0
- package/dist/audit/cli/requeueCommand.js +11 -0
- package/dist/audit/cli/requeueCommand.js.map +1 -0
- package/dist/audit/cli/resynthesizeCommand.d.ts +2 -0
- package/dist/audit/cli/resynthesizeCommand.d.ts.map +1 -0
- package/dist/audit/cli/resynthesizeCommand.js +57 -0
- package/dist/audit/cli/resynthesizeCommand.js.map +1 -0
- package/dist/audit/cli/reviewRun.d.ts +57 -0
- package/dist/audit/cli/reviewRun.d.ts.map +1 -0
- package/dist/audit/cli/reviewRun.js +180 -0
- package/dist/audit/cli/reviewRun.js.map +1 -0
- package/dist/audit/cli/rollingAuditDispatch.d.ts +119 -0
- package/dist/audit/cli/rollingAuditDispatch.d.ts.map +1 -0
- package/dist/audit/cli/rollingAuditDispatch.js +264 -0
- package/dist/audit/cli/rollingAuditDispatch.js.map +1 -0
- package/dist/audit/cli/sampleRunCommand.d.ts +2 -0
- package/dist/audit/cli/sampleRunCommand.d.ts.map +1 -0
- package/dist/audit/cli/sampleRunCommand.js +106 -0
- package/dist/audit/cli/sampleRunCommand.js.map +1 -0
- package/dist/audit/cli/semanticReviewStep.d.ts +23 -0
- package/dist/audit/cli/semanticReviewStep.d.ts.map +1 -0
- package/dist/audit/cli/semanticReviewStep.js +123 -0
- package/dist/audit/cli/semanticReviewStep.js.map +1 -0
- package/dist/audit/cli/statusCommand.d.ts +2 -0
- package/dist/audit/cli/statusCommand.d.ts.map +1 -0
- package/dist/audit/cli/statusCommand.js +133 -0
- package/dist/audit/cli/statusCommand.js.map +1 -0
- package/dist/audit/cli/steps.d.ts +204 -0
- package/dist/audit/cli/steps.d.ts.map +1 -0
- package/dist/audit/cli/steps.js +105 -0
- package/dist/audit/cli/steps.js.map +1 -0
- package/dist/audit/cli/submitPacketCommand.d.ts +2 -0
- package/dist/audit/cli/submitPacketCommand.d.ts.map +1 -0
- package/dist/audit/cli/submitPacketCommand.js +126 -0
- package/dist/audit/cli/submitPacketCommand.js.map +1 -0
- package/dist/audit/cli/synthesizeCommand.d.ts +2 -0
- package/dist/audit/cli/synthesizeCommand.d.ts.map +1 -0
- package/dist/audit/cli/synthesizeCommand.js +16 -0
- package/dist/audit/cli/synthesizeCommand.js.map +1 -0
- package/dist/audit/cli/updateRuntimeValidationCommand.d.ts +2 -0
- package/dist/audit/cli/updateRuntimeValidationCommand.d.ts.map +1 -0
- package/dist/audit/cli/updateRuntimeValidationCommand.js +17 -0
- package/dist/audit/cli/updateRuntimeValidationCommand.js.map +1 -0
- package/dist/audit/cli/validateCommand.d.ts +2 -0
- package/dist/audit/cli/validateCommand.d.ts.map +1 -0
- package/dist/audit/cli/validateCommand.js +42 -0
- package/dist/audit/cli/validateCommand.js.map +1 -0
- package/dist/audit/cli/validateResultCommand.d.ts +2 -0
- package/dist/audit/cli/validateResultCommand.d.ts.map +1 -0
- package/dist/audit/cli/validateResultCommand.js +92 -0
- package/dist/audit/cli/validateResultCommand.js.map +1 -0
- package/dist/audit/cli/validateResultsCommand.d.ts +2 -0
- package/dist/audit/cli/validateResultsCommand.d.ts.map +1 -0
- package/dist/audit/cli/validateResultsCommand.js +32 -0
- package/dist/audit/cli/validateResultsCommand.js.map +1 -0
- package/dist/audit/cli/waveManifest.d.ts +41 -0
- package/dist/audit/cli/waveManifest.d.ts.map +1 -0
- package/dist/audit/cli/waveManifest.js +42 -0
- package/dist/audit/cli/waveManifest.js.map +1 -0
- package/dist/audit/cli/workerResult.d.ts +19 -0
- package/dist/audit/cli/workerResult.d.ts.map +1 -0
- package/dist/audit/cli/workerResult.js +43 -0
- package/dist/audit/cli/workerResult.js.map +1 -0
- package/dist/audit/cli/workerRunCommand.d.ts +16 -0
- package/dist/audit/cli/workerRunCommand.d.ts.map +1 -0
- package/dist/audit/cli/workerRunCommand.js +132 -0
- package/dist/audit/cli/workerRunCommand.js.map +1 -0
- package/dist/audit/cli.d.ts +21 -0
- package/dist/audit/cli.d.ts.map +1 -0
- package/dist/audit/cli.js +137 -0
- package/dist/audit/cli.js.map +1 -0
- package/dist/audit/contracts/workerSchemas.d.ts +1448 -0
- package/dist/audit/contracts/workerSchemas.d.ts.map +1 -0
- package/dist/audit/contracts/workerSchemas.js +117 -0
- package/dist/audit/contracts/workerSchemas.js.map +1 -0
- package/dist/audit/contracts/wrapperResponse.d.ts +316 -0
- package/dist/audit/contracts/wrapperResponse.d.ts.map +1 -0
- package/dist/audit/contracts/wrapperResponse.js +96 -0
- package/dist/audit/contracts/wrapperResponse.js.map +1 -0
- package/dist/audit/coverage.d.ts +11 -0
- package/dist/audit/coverage.d.ts.map +1 -0
- package/dist/audit/coverage.js +78 -0
- package/dist/audit/coverage.js.map +1 -0
- package/dist/audit/extractors/analyzers/css.d.ts +3 -0
- package/dist/audit/extractors/analyzers/css.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/css.js +102 -0
- package/dist/audit/extractors/analyzers/css.js.map +1 -0
- package/dist/audit/extractors/analyzers/html.d.ts +3 -0
- package/dist/audit/extractors/analyzers/html.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/html.js +93 -0
- package/dist/audit/extractors/analyzers/html.js.map +1 -0
- package/dist/audit/extractors/analyzers/merge.d.ts +15 -0
- package/dist/audit/extractors/analyzers/merge.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/merge.js +86 -0
- package/dist/audit/extractors/analyzers/merge.js.map +1 -0
- package/dist/audit/extractors/analyzers/python.d.ts +3 -0
- package/dist/audit/extractors/analyzers/python.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/python.js +105 -0
- package/dist/audit/extractors/analyzers/python.js.map +1 -0
- package/dist/audit/extractors/analyzers/registry.d.ts +34 -0
- package/dist/audit/extractors/analyzers/registry.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/registry.js +82 -0
- package/dist/audit/extractors/analyzers/registry.js.map +1 -0
- package/dist/audit/extractors/analyzers/resourceUrl.d.ts +8 -0
- package/dist/audit/extractors/analyzers/resourceUrl.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/resourceUrl.js +26 -0
- package/dist/audit/extractors/analyzers/resourceUrl.js.map +1 -0
- package/dist/audit/extractors/analyzers/sql.d.ts +3 -0
- package/dist/audit/extractors/analyzers/sql.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/sql.js +23 -0
- package/dist/audit/extractors/analyzers/sql.js.map +1 -0
- package/dist/audit/extractors/analyzers/treeSitter.d.ts +44 -0
- package/dist/audit/extractors/analyzers/treeSitter.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/treeSitter.js +148 -0
- package/dist/audit/extractors/analyzers/treeSitter.js.map +1 -0
- package/dist/audit/extractors/analyzers/types.d.ts +54 -0
- package/dist/audit/extractors/analyzers/types.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/types.js +2 -0
- package/dist/audit/extractors/analyzers/types.js.map +1 -0
- package/dist/audit/extractors/analyzers/typescript.d.ts +3 -0
- package/dist/audit/extractors/analyzers/typescript.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/typescript.js +279 -0
- package/dist/audit/extractors/analyzers/typescript.js.map +1 -0
- package/dist/audit/extractors/browserExtension.d.ts +12 -0
- package/dist/audit/extractors/browserExtension.d.ts.map +1 -0
- package/dist/audit/extractors/browserExtension.js +388 -0
- package/dist/audit/extractors/browserExtension.js.map +1 -0
- package/dist/audit/extractors/bucketing.d.ts +12 -0
- package/dist/audit/extractors/bucketing.d.ts.map +1 -0
- package/dist/audit/extractors/bucketing.js +56 -0
- package/dist/audit/extractors/bucketing.js.map +1 -0
- package/dist/audit/extractors/designAssessment.d.ts +10 -0
- package/dist/audit/extractors/designAssessment.d.ts.map +1 -0
- package/dist/audit/extractors/designAssessment.js +280 -0
- package/dist/audit/extractors/designAssessment.js.map +1 -0
- package/dist/audit/extractors/disposition.d.ts +76 -0
- package/dist/audit/extractors/disposition.d.ts.map +1 -0
- package/dist/audit/extractors/disposition.js +265 -0
- package/dist/audit/extractors/disposition.js.map +1 -0
- package/dist/audit/extractors/fileInventory.d.ts +8 -0
- package/dist/audit/extractors/fileInventory.d.ts.map +1 -0
- package/dist/audit/extractors/fileInventory.js +36 -0
- package/dist/audit/extractors/fileInventory.js.map +1 -0
- package/dist/audit/extractors/flows.d.ts +9 -0
- package/dist/audit/extractors/flows.d.ts.map +1 -0
- package/dist/audit/extractors/flows.js +111 -0
- package/dist/audit/extractors/flows.js.map +1 -0
- package/dist/audit/extractors/fsIntake.d.ts +9 -0
- package/dist/audit/extractors/fsIntake.d.ts.map +1 -0
- package/dist/audit/extractors/fsIntake.js +95 -0
- package/dist/audit/extractors/fsIntake.js.map +1 -0
- package/dist/audit/extractors/graph.d.ts +11 -0
- package/dist/audit/extractors/graph.d.ts.map +1 -0
- package/dist/audit/extractors/graph.js +472 -0
- package/dist/audit/extractors/graph.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/cargo.d.ts +15 -0
- package/dist/audit/extractors/graphManifestEdges/cargo.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/cargo.js +74 -0
- package/dist/audit/extractors/graphManifestEdges/cargo.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/go.d.ts +6 -0
- package/dist/audit/extractors/graphManifestEdges/go.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/go.js +152 -0
- package/dist/audit/extractors/graphManifestEdges/go.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/index.d.ts +9 -0
- package/dist/audit/extractors/graphManifestEdges/index.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/index.js +12 -0
- package/dist/audit/extractors/graphManifestEdges/index.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/jsonc.d.ts +4 -0
- package/dist/audit/extractors/graphManifestEdges/jsonc.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/jsonc.js +98 -0
- package/dist/audit/extractors/graphManifestEdges/jsonc.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/maven.d.ts +4 -0
- package/dist/audit/extractors/graphManifestEdges/maven.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/maven.js +74 -0
- package/dist/audit/extractors/graphManifestEdges/maven.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/packageJson.d.ts +20 -0
- package/dist/audit/extractors/graphManifestEdges/packageJson.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/packageJson.js +205 -0
- package/dist/audit/extractors/graphManifestEdges/packageJson.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/pnpm.d.ts +10 -0
- package/dist/audit/extractors/graphManifestEdges/pnpm.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/pnpm.js +18 -0
- package/dist/audit/extractors/graphManifestEdges/pnpm.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/pyproject.d.ts +4 -0
- package/dist/audit/extractors/graphManifestEdges/pyproject.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/pyproject.js +45 -0
- package/dist/audit/extractors/graphManifestEdges/pyproject.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/toml.d.ts +25 -0
- package/dist/audit/extractors/graphManifestEdges/toml.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/toml.js +49 -0
- package/dist/audit/extractors/graphManifestEdges/toml.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/typescript.d.ts +4 -0
- package/dist/audit/extractors/graphManifestEdges/typescript.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/typescript.js +57 -0
- package/dist/audit/extractors/graphManifestEdges/typescript.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/workspace.d.ts +11 -0
- package/dist/audit/extractors/graphManifestEdges/workspace.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/workspace.js +73 -0
- package/dist/audit/extractors/graphManifestEdges/workspace.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/yaml.d.ts +24 -0
- package/dist/audit/extractors/graphManifestEdges/yaml.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/yaml.js +57 -0
- package/dist/audit/extractors/graphManifestEdges/yaml.js.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/yamlPaths.d.ts +5 -0
- package/dist/audit/extractors/graphManifestEdges/yamlPaths.d.ts.map +1 -0
- package/dist/audit/extractors/graphManifestEdges/yamlPaths.js +75 -0
- package/dist/audit/extractors/graphManifestEdges/yamlPaths.js.map +1 -0
- package/dist/audit/extractors/graphPathUtils.d.ts +34 -0
- package/dist/audit/extractors/graphPathUtils.d.ts.map +1 -0
- package/dist/audit/extractors/graphPathUtils.js +174 -0
- package/dist/audit/extractors/graphPathUtils.js.map +1 -0
- package/dist/audit/extractors/graphPythonImports.d.ts +19 -0
- package/dist/audit/extractors/graphPythonImports.d.ts.map +1 -0
- package/dist/audit/extractors/graphPythonImports.js +318 -0
- package/dist/audit/extractors/graphPythonImports.js.map +1 -0
- package/dist/audit/extractors/graphRoutes.d.ts +13 -0
- package/dist/audit/extractors/graphRoutes.d.ts.map +1 -0
- package/dist/audit/extractors/graphRoutes.js +447 -0
- package/dist/audit/extractors/graphRoutes.js.map +1 -0
- package/dist/audit/extractors/graphSuites.d.ts +5 -0
- package/dist/audit/extractors/graphSuites.d.ts.map +1 -0
- package/dist/audit/extractors/graphSuites.js +248 -0
- package/dist/audit/extractors/graphSuites.js.map +1 -0
- package/dist/audit/extractors/graphTestSources.d.ts +3 -0
- package/dist/audit/extractors/graphTestSources.d.ts.map +1 -0
- package/dist/audit/extractors/graphTestSources.js +103 -0
- package/dist/audit/extractors/graphTestSources.js.map +1 -0
- package/dist/audit/extractors/ignore.d.ts +2 -0
- package/dist/audit/extractors/ignore.d.ts.map +1 -0
- package/dist/audit/extractors/ignore.js +18 -0
- package/dist/audit/extractors/ignore.js.map +1 -0
- package/dist/audit/extractors/languageMap.generated.d.ts +2 -0
- package/dist/audit/extractors/languageMap.generated.d.ts.map +1 -0
- package/dist/audit/extractors/languageMap.generated.js +1456 -0
- package/dist/audit/extractors/languageMap.generated.js.map +1 -0
- package/dist/audit/extractors/pathPatterns.d.ts +55 -0
- package/dist/audit/extractors/pathPatterns.d.ts.map +1 -0
- package/dist/audit/extractors/pathPatterns.js +303 -0
- package/dist/audit/extractors/pathPatterns.js.map +1 -0
- package/dist/audit/extractors/risk.d.ts +5 -0
- package/dist/audit/extractors/risk.d.ts.map +1 -0
- package/dist/audit/extractors/risk.js +54 -0
- package/dist/audit/extractors/risk.js.map +1 -0
- package/dist/audit/extractors/surfaces.d.ts +10 -0
- package/dist/audit/extractors/surfaces.d.ts.map +1 -0
- package/dist/audit/extractors/surfaces.js +49 -0
- package/dist/audit/extractors/surfaces.js.map +1 -0
- package/dist/audit/index.d.ts +2 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +3 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/io/artifacts.d.ts +152 -0
- package/dist/audit/io/artifacts.d.ts.map +1 -0
- package/dist/audit/io/artifacts.js +239 -0
- package/dist/audit/io/artifacts.js.map +1 -0
- package/dist/audit/io/runArtifactTypes.d.ts +19 -0
- package/dist/audit/io/runArtifactTypes.d.ts.map +1 -0
- package/dist/audit/io/runArtifactTypes.js +2 -0
- package/dist/audit/io/runArtifactTypes.js.map +1 -0
- package/dist/audit/io/runArtifacts.d.ts +33 -0
- package/dist/audit/io/runArtifacts.d.ts.map +1 -0
- package/dist/audit/io/runArtifacts.js +254 -0
- package/dist/audit/io/runArtifacts.js.map +1 -0
- package/dist/audit/io/toolingManifest.d.ts +4 -0
- package/dist/audit/io/toolingManifest.d.ts.map +1 -0
- package/dist/audit/io/toolingManifest.js +79 -0
- package/dist/audit/io/toolingManifest.js.map +1 -0
- package/dist/audit/orchestrator/advance.d.ts +5 -0
- package/dist/audit/orchestrator/advance.d.ts.map +1 -0
- package/dist/audit/orchestrator/advance.js +172 -0
- package/dist/audit/orchestrator/advance.js.map +1 -0
- package/dist/audit/orchestrator/advanceTypes.d.ts +50 -0
- package/dist/audit/orchestrator/advanceTypes.d.ts.map +1 -0
- package/dist/audit/orchestrator/advanceTypes.js +2 -0
- package/dist/audit/orchestrator/advanceTypes.js.map +1 -0
- package/dist/audit/orchestrator/artifactFreshness.d.ts +4 -0
- package/dist/audit/orchestrator/artifactFreshness.d.ts.map +1 -0
- package/dist/audit/orchestrator/artifactFreshness.js +99 -0
- package/dist/audit/orchestrator/artifactFreshness.js.map +1 -0
- package/dist/audit/orchestrator/artifactMetadata.d.ts +6 -0
- package/dist/audit/orchestrator/artifactMetadata.d.ts.map +1 -0
- package/dist/audit/orchestrator/artifactMetadata.js +98 -0
- package/dist/audit/orchestrator/artifactMetadata.js.map +1 -0
- package/dist/audit/orchestrator/auditTaskUtils.d.ts +10 -0
- package/dist/audit/orchestrator/auditTaskUtils.d.ts.map +1 -0
- package/dist/audit/orchestrator/auditTaskUtils.js +53 -0
- package/dist/audit/orchestrator/auditTaskUtils.js.map +1 -0
- package/dist/audit/orchestrator/autoFixExecutor.d.ts +4 -0
- package/dist/audit/orchestrator/autoFixExecutor.d.ts.map +1 -0
- package/dist/audit/orchestrator/autoFixExecutor.js +152 -0
- package/dist/audit/orchestrator/autoFixExecutor.js.map +1 -0
- package/dist/audit/orchestrator/chunking.d.ts +6 -0
- package/dist/audit/orchestrator/chunking.d.ts.map +1 -0
- package/dist/audit/orchestrator/chunking.js +14 -0
- package/dist/audit/orchestrator/chunking.js.map +1 -0
- package/dist/audit/orchestrator/dependencyMap.d.ts +74 -0
- package/dist/audit/orchestrator/dependencyMap.d.ts.map +1 -0
- package/dist/audit/orchestrator/dependencyMap.js +193 -0
- package/dist/audit/orchestrator/dependencyMap.js.map +1 -0
- package/dist/audit/orchestrator/designReviewProjection.d.ts +66 -0
- package/dist/audit/orchestrator/designReviewProjection.d.ts.map +1 -0
- package/dist/audit/orchestrator/designReviewProjection.js +215 -0
- package/dist/audit/orchestrator/designReviewProjection.js.map +1 -0
- package/dist/audit/orchestrator/designReviewPrompt.d.ts +82 -0
- package/dist/audit/orchestrator/designReviewPrompt.d.ts.map +1 -0
- package/dist/audit/orchestrator/designReviewPrompt.js +474 -0
- package/dist/audit/orchestrator/designReviewPrompt.js.map +1 -0
- package/dist/audit/orchestrator/designReviewSnapshot.d.ts +69 -0
- package/dist/audit/orchestrator/designReviewSnapshot.d.ts.map +1 -0
- package/dist/audit/orchestrator/designReviewSnapshot.js +135 -0
- package/dist/audit/orchestrator/designReviewSnapshot.js.map +1 -0
- package/dist/audit/orchestrator/edgeReasoning.d.ts +40 -0
- package/dist/audit/orchestrator/edgeReasoning.d.ts.map +1 -0
- package/dist/audit/orchestrator/edgeReasoning.js +126 -0
- package/dist/audit/orchestrator/edgeReasoning.js.map +1 -0
- package/dist/audit/orchestrator/executorResult.d.ts +71 -0
- package/dist/audit/orchestrator/executorResult.d.ts.map +1 -0
- package/dist/audit/orchestrator/executorResult.js +2 -0
- package/dist/audit/orchestrator/executorResult.js.map +1 -0
- package/dist/audit/orchestrator/executorRunners.d.ts +34 -0
- package/dist/audit/orchestrator/executorRunners.d.ts.map +1 -0
- package/dist/audit/orchestrator/executorRunners.js +85 -0
- package/dist/audit/orchestrator/executorRunners.js.map +1 -0
- package/dist/audit/orchestrator/executors.d.ts +13 -0
- package/dist/audit/orchestrator/executors.d.ts.map +1 -0
- package/dist/audit/orchestrator/executors.js +114 -0
- package/dist/audit/orchestrator/executors.js.map +1 -0
- package/dist/audit/orchestrator/fileAnchors.d.ts +33 -0
- package/dist/audit/orchestrator/fileAnchors.d.ts.map +1 -0
- package/dist/audit/orchestrator/fileAnchors.js +242 -0
- package/dist/audit/orchestrator/fileAnchors.js.map +1 -0
- package/dist/audit/orchestrator/fileIntegrity.d.ts +9 -0
- package/dist/audit/orchestrator/fileIntegrity.d.ts.map +1 -0
- package/dist/audit/orchestrator/fileIntegrity.js +58 -0
- package/dist/audit/orchestrator/fileIntegrity.js.map +1 -0
- package/dist/audit/orchestrator/flowCoverage.d.ts +5 -0
- package/dist/audit/orchestrator/flowCoverage.d.ts.map +1 -0
- package/dist/audit/orchestrator/flowCoverage.js +46 -0
- package/dist/audit/orchestrator/flowCoverage.js.map +1 -0
- package/dist/audit/orchestrator/flowPlanning.d.ts +8 -0
- package/dist/audit/orchestrator/flowPlanning.d.ts.map +1 -0
- package/dist/audit/orchestrator/flowPlanning.js +65 -0
- package/dist/audit/orchestrator/flowPlanning.js.map +1 -0
- package/dist/audit/orchestrator/flowRequeue.d.ts +6 -0
- package/dist/audit/orchestrator/flowRequeue.d.ts.map +1 -0
- package/dist/audit/orchestrator/flowRequeue.js +73 -0
- package/dist/audit/orchestrator/flowRequeue.js.map +1 -0
- package/dist/audit/orchestrator/graphEnrichmentExecutor.d.ts +30 -0
- package/dist/audit/orchestrator/graphEnrichmentExecutor.d.ts.map +1 -0
- package/dist/audit/orchestrator/graphEnrichmentExecutor.js +227 -0
- package/dist/audit/orchestrator/graphEnrichmentExecutor.js.map +1 -0
- package/dist/audit/orchestrator/ingestionExecutors.d.ts +10 -0
- package/dist/audit/orchestrator/ingestionExecutors.d.ts.map +1 -0
- package/dist/audit/orchestrator/ingestionExecutors.js +262 -0
- package/dist/audit/orchestrator/ingestionExecutors.js.map +1 -0
- package/dist/audit/orchestrator/intakeExecutors.d.ts +26 -0
- package/dist/audit/orchestrator/intakeExecutors.d.ts.map +1 -0
- package/dist/audit/orchestrator/intakeExecutors.js +138 -0
- package/dist/audit/orchestrator/intakeExecutors.js.map +1 -0
- package/dist/audit/orchestrator/intentCheckpointExecutor.d.ts +89 -0
- package/dist/audit/orchestrator/intentCheckpointExecutor.d.ts.map +1 -0
- package/dist/audit/orchestrator/intentCheckpointExecutor.js +264 -0
- package/dist/audit/orchestrator/intentCheckpointExecutor.js.map +1 -0
- package/dist/audit/orchestrator/intentInterpreter.d.ts +49 -0
- package/dist/audit/orchestrator/intentInterpreter.d.ts.map +1 -0
- package/dist/audit/orchestrator/intentInterpreter.js +110 -0
- package/dist/audit/orchestrator/intentInterpreter.js.map +1 -0
- package/dist/audit/orchestrator/lensSelection.d.ts +35 -0
- package/dist/audit/orchestrator/lensSelection.d.ts.map +1 -0
- package/dist/audit/orchestrator/lensSelection.js +81 -0
- package/dist/audit/orchestrator/lensSelection.js.map +1 -0
- package/dist/audit/orchestrator/localCommands.d.ts +16 -0
- package/dist/audit/orchestrator/localCommands.d.ts.map +1 -0
- package/dist/audit/orchestrator/localCommands.js +113 -0
- package/dist/audit/orchestrator/localCommands.js.map +1 -0
- package/dist/audit/orchestrator/nextStep.d.ts +12 -0
- package/dist/audit/orchestrator/nextStep.d.ts.map +1 -0
- package/dist/audit/orchestrator/nextStep.js +63 -0
- package/dist/audit/orchestrator/nextStep.js.map +1 -0
- package/dist/audit/orchestrator/partitionTaskGraph.d.ts +32 -0
- package/dist/audit/orchestrator/partitionTaskGraph.d.ts.map +1 -0
- package/dist/audit/orchestrator/partitionTaskGraph.js +98 -0
- package/dist/audit/orchestrator/partitionTaskGraph.js.map +1 -0
- package/dist/audit/orchestrator/planning.d.ts +5 -0
- package/dist/audit/orchestrator/planning.d.ts.map +1 -0
- package/dist/audit/orchestrator/planning.js +81 -0
- package/dist/audit/orchestrator/planning.js.map +1 -0
- package/dist/audit/orchestrator/planningExecutors.d.ts +21 -0
- package/dist/audit/orchestrator/planningExecutors.d.ts.map +1 -0
- package/dist/audit/orchestrator/planningExecutors.js +228 -0
- package/dist/audit/orchestrator/planningExecutors.js.map +1 -0
- package/dist/audit/orchestrator/providerConfirmation.d.ts +21 -0
- package/dist/audit/orchestrator/providerConfirmation.d.ts.map +1 -0
- package/dist/audit/orchestrator/providerConfirmation.js +54 -0
- package/dist/audit/orchestrator/providerConfirmation.js.map +1 -0
- package/dist/audit/orchestrator/requeue.d.ts +4 -0
- package/dist/audit/orchestrator/requeue.d.ts.map +1 -0
- package/dist/audit/orchestrator/requeue.js +33 -0
- package/dist/audit/orchestrator/requeue.js.map +1 -0
- package/dist/audit/orchestrator/requeueCommand.d.ts +32 -0
- package/dist/audit/orchestrator/requeueCommand.d.ts.map +1 -0
- package/dist/audit/orchestrator/requeueCommand.js +45 -0
- package/dist/audit/orchestrator/requeueCommand.js.map +1 -0
- package/dist/audit/orchestrator/requeueUtils.d.ts +14 -0
- package/dist/audit/orchestrator/requeueUtils.d.ts.map +1 -0
- package/dist/audit/orchestrator/requeueUtils.js +22 -0
- package/dist/audit/orchestrator/requeueUtils.js.map +1 -0
- package/dist/audit/orchestrator/resultIngestion.d.ts +18 -0
- package/dist/audit/orchestrator/resultIngestion.d.ts.map +1 -0
- package/dist/audit/orchestrator/resultIngestion.js +63 -0
- package/dist/audit/orchestrator/resultIngestion.js.map +1 -0
- package/dist/audit/orchestrator/reviewPacketGraph.d.ts +5 -0
- package/dist/audit/orchestrator/reviewPacketGraph.d.ts.map +1 -0
- package/dist/audit/orchestrator/reviewPacketGraph.js +11 -0
- package/dist/audit/orchestrator/reviewPacketGraph.js.map +1 -0
- package/dist/audit/orchestrator/reviewPacketGraphClustering.d.ts +4 -0
- package/dist/audit/orchestrator/reviewPacketGraphClustering.d.ts.map +1 -0
- package/dist/audit/orchestrator/reviewPacketGraphClustering.js +481 -0
- package/dist/audit/orchestrator/reviewPacketGraphClustering.js.map +1 -0
- package/dist/audit/orchestrator/reviewPacketGraphContext.d.ts +10 -0
- package/dist/audit/orchestrator/reviewPacketGraphContext.d.ts.map +1 -0
- package/dist/audit/orchestrator/reviewPacketGraphContext.js +95 -0
- package/dist/audit/orchestrator/reviewPacketGraphContext.js.map +1 -0
- package/dist/audit/orchestrator/reviewPacketGraphEdges.d.ts +23 -0
- package/dist/audit/orchestrator/reviewPacketGraphEdges.d.ts.map +1 -0
- package/dist/audit/orchestrator/reviewPacketGraphEdges.js +169 -0
- package/dist/audit/orchestrator/reviewPacketGraphEdges.js.map +1 -0
- package/dist/audit/orchestrator/reviewPacketMetrics.d.ts +17 -0
- package/dist/audit/orchestrator/reviewPacketMetrics.d.ts.map +1 -0
- package/dist/audit/orchestrator/reviewPacketMetrics.js +322 -0
- package/dist/audit/orchestrator/reviewPacketMetrics.js.map +1 -0
- package/dist/audit/orchestrator/reviewPacketSizing.d.ts +27 -0
- package/dist/audit/orchestrator/reviewPacketSizing.d.ts.map +1 -0
- package/dist/audit/orchestrator/reviewPacketSizing.js +64 -0
- package/dist/audit/orchestrator/reviewPacketSizing.js.map +1 -0
- package/dist/audit/orchestrator/reviewPackets.d.ts +54 -0
- package/dist/audit/orchestrator/reviewPackets.d.ts.map +1 -0
- package/dist/audit/orchestrator/reviewPackets.js +318 -0
- package/dist/audit/orchestrator/reviewPackets.js.map +1 -0
- package/dist/audit/orchestrator/rollingDispatch.d.ts +45 -0
- package/dist/audit/orchestrator/rollingDispatch.d.ts.map +1 -0
- package/dist/audit/orchestrator/rollingDispatch.js +103 -0
- package/dist/audit/orchestrator/rollingDispatch.js.map +1 -0
- package/dist/audit/orchestrator/runtimeCommand.d.ts +10 -0
- package/dist/audit/orchestrator/runtimeCommand.d.ts.map +1 -0
- package/dist/audit/orchestrator/runtimeCommand.js +129 -0
- package/dist/audit/orchestrator/runtimeCommand.js.map +1 -0
- package/dist/audit/orchestrator/runtimeValidation.d.ts +13 -0
- package/dist/audit/orchestrator/runtimeValidation.d.ts.map +1 -0
- package/dist/audit/orchestrator/runtimeValidation.js +94 -0
- package/dist/audit/orchestrator/runtimeValidation.js.map +1 -0
- package/dist/audit/orchestrator/runtimeValidationUpdate.d.ts +3 -0
- package/dist/audit/orchestrator/runtimeValidationUpdate.d.ts.map +1 -0
- package/dist/audit/orchestrator/runtimeValidationUpdate.js +57 -0
- package/dist/audit/orchestrator/runtimeValidationUpdate.js.map +1 -0
- package/dist/audit/orchestrator/scope.d.ts +75 -0
- package/dist/audit/orchestrator/scope.d.ts.map +1 -0
- package/dist/audit/orchestrator/scope.js +268 -0
- package/dist/audit/orchestrator/scope.js.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/conflict.d.ts +9 -0
- package/dist/audit/orchestrator/selectiveDeepening/conflict.d.ts.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/conflict.js +72 -0
- package/dist/audit/orchestrator/selectiveDeepening/conflict.js.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.d.ts +11 -0
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.d.ts.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.js +53 -0
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.js.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.d.ts +8 -0
- package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.d.ts.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.js +46 -0
- package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.js.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/index.d.ts +25 -0
- package/dist/audit/orchestrator/selectiveDeepening/index.d.ts.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/index.js +157 -0
- package/dist/audit/orchestrator/selectiveDeepening/index.js.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/lensVerification.d.ts +13 -0
- package/dist/audit/orchestrator/selectiveDeepening/lensVerification.d.ts.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/lensVerification.js +269 -0
- package/dist/audit/orchestrator/selectiveDeepening/lensVerification.js.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.d.ts +14 -0
- package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.d.ts.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.js +58 -0
- package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.js.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/shared.d.ts +42 -0
- package/dist/audit/orchestrator/selectiveDeepening/shared.d.ts.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/shared.js +121 -0
- package/dist/audit/orchestrator/selectiveDeepening/shared.js.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.d.ts +7 -0
- package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.d.ts.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.js +73 -0
- package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.js.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening.d.ts +3 -0
- package/dist/audit/orchestrator/selectiveDeepening.d.ts.map +1 -0
- package/dist/audit/orchestrator/selectiveDeepening.js +7 -0
- package/dist/audit/orchestrator/selectiveDeepening.js.map +1 -0
- package/dist/audit/orchestrator/staleness.d.ts +3 -0
- package/dist/audit/orchestrator/staleness.d.ts.map +1 -0
- package/dist/audit/orchestrator/staleness.js +102 -0
- package/dist/audit/orchestrator/staleness.js.map +1 -0
- package/dist/audit/orchestrator/state.d.ts +4 -0
- package/dist/audit/orchestrator/state.d.ts.map +1 -0
- package/dist/audit/orchestrator/state.js +158 -0
- package/dist/audit/orchestrator/state.js.map +1 -0
- package/dist/audit/orchestrator/structureExecutors.d.ts +6 -0
- package/dist/audit/orchestrator/structureExecutors.d.ts.map +1 -0
- package/dist/audit/orchestrator/structureExecutors.js +116 -0
- package/dist/audit/orchestrator/structureExecutors.js.map +1 -0
- package/dist/audit/orchestrator/syntaxResolutionExecutor.d.ts +4 -0
- package/dist/audit/orchestrator/syntaxResolutionExecutor.d.ts.map +1 -0
- package/dist/audit/orchestrator/syntaxResolutionExecutor.js +260 -0
- package/dist/audit/orchestrator/syntaxResolutionExecutor.js.map +1 -0
- package/dist/audit/orchestrator/synthesisExecutors.d.ts +13 -0
- package/dist/audit/orchestrator/synthesisExecutors.d.ts.map +1 -0
- package/dist/audit/orchestrator/synthesisExecutors.js +107 -0
- package/dist/audit/orchestrator/synthesisExecutors.js.map +1 -0
- package/dist/audit/orchestrator/taskAffinityGraph.d.ts +154 -0
- package/dist/audit/orchestrator/taskAffinityGraph.d.ts.map +1 -0
- package/dist/audit/orchestrator/taskAffinityGraph.js +216 -0
- package/dist/audit/orchestrator/taskAffinityGraph.js.map +1 -0
- package/dist/audit/orchestrator/taskBuilder.d.ts +43 -0
- package/dist/audit/orchestrator/taskBuilder.d.ts.map +1 -0
- package/dist/audit/orchestrator/taskBuilder.js +355 -0
- package/dist/audit/orchestrator/taskBuilder.js.map +1 -0
- package/dist/audit/orchestrator/trivialAudit.d.ts +5 -0
- package/dist/audit/orchestrator/trivialAudit.d.ts.map +1 -0
- package/dist/audit/orchestrator/trivialAudit.js +50 -0
- package/dist/audit/orchestrator/trivialAudit.js.map +1 -0
- package/dist/audit/orchestrator/unionFind.d.ts +8 -0
- package/dist/audit/orchestrator/unionFind.d.ts.map +1 -0
- package/dist/audit/orchestrator/unionFind.js +43 -0
- package/dist/audit/orchestrator/unionFind.js.map +1 -0
- package/dist/audit/orchestrator/unitBuilder.d.ts +8 -0
- package/dist/audit/orchestrator/unitBuilder.d.ts.map +1 -0
- package/dist/audit/orchestrator/unitBuilder.js +171 -0
- package/dist/audit/orchestrator/unitBuilder.js.map +1 -0
- package/dist/audit/orchestrator.d.ts +7 -0
- package/dist/audit/orchestrator.d.ts.map +1 -0
- package/dist/audit/orchestrator.js +68 -0
- package/dist/audit/orchestrator.js.map +1 -0
- package/dist/audit/prompts/renderWorkerPrompt.d.ts +3 -0
- package/dist/audit/prompts/renderWorkerPrompt.d.ts.map +1 -0
- package/dist/audit/prompts/renderWorkerPrompt.js +87 -0
- package/dist/audit/prompts/renderWorkerPrompt.js.map +1 -0
- package/dist/audit/providers/claudeCodeProvider.d.ts +11 -0
- package/dist/audit/providers/claudeCodeProvider.d.ts.map +1 -0
- package/dist/audit/providers/claudeCodeProvider.js +23 -0
- package/dist/audit/providers/claudeCodeProvider.js.map +1 -0
- package/dist/audit/providers/constants.d.ts +2 -0
- package/dist/audit/providers/constants.d.ts.map +1 -0
- package/dist/audit/providers/constants.js +2 -0
- package/dist/audit/providers/constants.js.map +1 -0
- package/dist/audit/providers/index.d.ts +14 -0
- package/dist/audit/providers/index.d.ts.map +1 -0
- package/dist/audit/providers/index.js +21 -0
- package/dist/audit/providers/index.js.map +1 -0
- package/dist/audit/providers/opencodeProvider.d.ts +5 -0
- package/dist/audit/providers/opencodeProvider.d.ts.map +1 -0
- package/dist/audit/providers/opencodeProvider.js +10 -0
- package/dist/audit/providers/opencodeProvider.js.map +1 -0
- package/dist/audit/quota/discoveredLimits.d.ts +27 -0
- package/dist/audit/quota/discoveredLimits.d.ts.map +1 -0
- package/dist/audit/quota/discoveredLimits.js +91 -0
- package/dist/audit/quota/discoveredLimits.js.map +1 -0
- package/dist/audit/quota/headerExtraction.d.ts +9 -0
- package/dist/audit/quota/headerExtraction.d.ts.map +1 -0
- package/dist/audit/quota/headerExtraction.js +148 -0
- package/dist/audit/quota/headerExtraction.js.map +1 -0
- package/dist/audit/quota/headerExtractors/claudeCodeHeaderExtractor.d.ts +7 -0
- package/dist/audit/quota/headerExtractors/claudeCodeHeaderExtractor.d.ts.map +1 -0
- package/dist/audit/quota/headerExtractors/claudeCodeHeaderExtractor.js +27 -0
- package/dist/audit/quota/headerExtractors/claudeCodeHeaderExtractor.js.map +1 -0
- package/dist/audit/quota/headerExtractors/genericHeaderExtractor.d.ts +10 -0
- package/dist/audit/quota/headerExtractors/genericHeaderExtractor.d.ts.map +1 -0
- package/dist/audit/quota/headerExtractors/genericHeaderExtractor.js +8 -0
- package/dist/audit/quota/headerExtractors/genericHeaderExtractor.js.map +1 -0
- package/dist/audit/quota/headerExtractors/index.d.ts +6 -0
- package/dist/audit/quota/headerExtractors/index.d.ts.map +1 -0
- package/dist/audit/quota/headerExtractors/index.js +11 -0
- package/dist/audit/quota/headerExtractors/index.js.map +1 -0
- package/dist/audit/quota/hostLimits.d.ts +8 -0
- package/dist/audit/quota/hostLimits.d.ts.map +1 -0
- package/dist/audit/quota/hostLimits.js +9 -0
- package/dist/audit/quota/hostLimits.js.map +1 -0
- package/dist/audit/quota/index.d.ts +383 -0
- package/dist/audit/quota/index.d.ts.map +1 -0
- package/dist/audit/quota/index.js +45 -0
- package/dist/audit/quota/index.js.map +1 -0
- package/dist/audit/reporting/findingIdentity.d.ts +34 -0
- package/dist/audit/reporting/findingIdentity.d.ts.map +1 -0
- package/dist/audit/reporting/findingIdentity.js +64 -0
- package/dist/audit/reporting/findingIdentity.js.map +1 -0
- package/dist/audit/reporting/findingRanks.d.ts +2 -0
- package/dist/audit/reporting/findingRanks.d.ts.map +1 -0
- package/dist/audit/reporting/findingRanks.js +7 -0
- package/dist/audit/reporting/findingRanks.js.map +1 -0
- package/dist/audit/reporting/mergeFindings.d.ts +6 -0
- package/dist/audit/reporting/mergeFindings.d.ts.map +1 -0
- package/dist/audit/reporting/mergeFindings.js +326 -0
- package/dist/audit/reporting/mergeFindings.js.map +1 -0
- package/dist/audit/reporting/synthesis.d.ts +124 -0
- package/dist/audit/reporting/synthesis.d.ts.map +1 -0
- package/dist/audit/reporting/synthesis.js +369 -0
- package/dist/audit/reporting/synthesis.js.map +1 -0
- package/dist/audit/reporting/synthesisNarrativePrompt.d.ts +8 -0
- package/dist/audit/reporting/synthesisNarrativePrompt.d.ts.map +1 -0
- package/dist/audit/reporting/synthesisNarrativePrompt.js +66 -0
- package/dist/audit/reporting/synthesisNarrativePrompt.js.map +1 -0
- package/dist/audit/reporting/workBlocks.d.ts +10 -0
- package/dist/audit/reporting/workBlocks.d.ts.map +1 -0
- package/dist/audit/reporting/workBlocks.js +154 -0
- package/dist/audit/reporting/workBlocks.js.map +1 -0
- package/dist/audit/supervisor/operatorHandoff.d.ts +65 -0
- package/dist/audit/supervisor/operatorHandoff.d.ts.map +1 -0
- package/dist/audit/supervisor/operatorHandoff.js +277 -0
- package/dist/audit/supervisor/operatorHandoff.js.map +1 -0
- package/dist/audit/supervisor/runLedger.d.ts +4 -0
- package/dist/audit/supervisor/runLedger.d.ts.map +1 -0
- package/dist/audit/supervisor/runLedger.js +118 -0
- package/dist/audit/supervisor/runLedger.js.map +1 -0
- package/dist/audit/supervisor/sessionConfig.d.ts +12 -0
- package/dist/audit/supervisor/sessionConfig.d.ts.map +1 -0
- package/dist/audit/supervisor/sessionConfig.js +49 -0
- package/dist/audit/supervisor/sessionConfig.js.map +1 -0
- package/dist/audit/types/activeDispatch.d.ts +36 -0
- package/dist/audit/types/activeDispatch.d.ts.map +1 -0
- package/dist/audit/types/activeDispatch.js +3 -0
- package/dist/audit/types/activeDispatch.js.map +1 -0
- package/dist/audit/types/analyzerCapability.d.ts +17 -0
- package/dist/audit/types/analyzerCapability.d.ts.map +1 -0
- package/dist/audit/types/analyzerCapability.js +2 -0
- package/dist/audit/types/analyzerCapability.js.map +1 -0
- package/dist/audit/types/artifactMetadata.d.ts +9 -0
- package/dist/audit/types/artifactMetadata.d.ts.map +1 -0
- package/dist/audit/types/artifactMetadata.js +2 -0
- package/dist/audit/types/artifactMetadata.js.map +1 -0
- package/dist/audit/types/auditScope.d.ts +58 -0
- package/dist/audit/types/auditScope.d.ts.map +1 -0
- package/dist/audit/types/auditScope.js +15 -0
- package/dist/audit/types/auditScope.js.map +1 -0
- package/dist/audit/types/auditState.d.ts +18 -0
- package/dist/audit/types/auditState.d.ts.map +1 -0
- package/dist/audit/types/auditState.js +2 -0
- package/dist/audit/types/auditState.js.map +1 -0
- package/dist/audit/types/designAssessment.d.ts +22 -0
- package/dist/audit/types/designAssessment.d.ts.map +1 -0
- package/dist/audit/types/designAssessment.js +8 -0
- package/dist/audit/types/designAssessment.js.map +1 -0
- package/dist/audit/types/externalAnalyzer.d.ts +225 -0
- package/dist/audit/types/externalAnalyzer.d.ts.map +1 -0
- package/dist/audit/types/externalAnalyzer.js +56 -0
- package/dist/audit/types/externalAnalyzer.js.map +1 -0
- package/dist/audit/types/flowCoverage.d.ts +16 -0
- package/dist/audit/types/flowCoverage.d.ts.map +1 -0
- package/dist/audit/types/flowCoverage.js +6 -0
- package/dist/audit/types/flowCoverage.js.map +1 -0
- package/dist/audit/types/reviewPlanning.d.ts +513 -0
- package/dist/audit/types/reviewPlanning.d.ts.map +1 -0
- package/dist/audit/types/reviewPlanning.js +109 -0
- package/dist/audit/types/reviewPlanning.js.map +1 -0
- package/dist/audit/types/runtimeValidation.d.ts +155 -0
- package/dist/audit/types/runtimeValidation.d.ts.map +1 -0
- package/dist/audit/types/runtimeValidation.js +52 -0
- package/dist/audit/types/runtimeValidation.js.map +1 -0
- package/dist/audit/types/synthesisNarrative.d.ts +8 -0
- package/dist/audit/types/synthesisNarrative.d.ts.map +1 -0
- package/dist/audit/types/synthesisNarrative.js +6 -0
- package/dist/audit/types/synthesisNarrative.js.map +1 -0
- package/dist/audit/types/toolingManifest.d.ts +8 -0
- package/dist/audit/types/toolingManifest.d.ts.map +1 -0
- package/dist/audit/types/toolingManifest.js +2 -0
- package/dist/audit/types/toolingManifest.js.map +1 -0
- package/dist/audit/types/workerResult.d.ts +14 -0
- package/dist/audit/types/workerResult.d.ts.map +1 -0
- package/dist/audit/types/workerResult.js +2 -0
- package/dist/audit/types/workerResult.js.map +1 -0
- package/dist/audit/types/workerSession.d.ts +28 -0
- package/dist/audit/types/workerSession.d.ts.map +1 -0
- package/dist/audit/types/workerSession.js +5 -0
- package/dist/audit/types/workerSession.js.map +1 -0
- package/dist/audit/types.d.ts +1077 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/audit/types.js +160 -0
- package/dist/audit/types.js.map +1 -0
- package/dist/audit/validation/anchorGrounding.d.ts +49 -0
- package/dist/audit/validation/anchorGrounding.d.ts.map +1 -0
- package/dist/audit/validation/anchorGrounding.js +183 -0
- package/dist/audit/validation/anchorGrounding.js.map +1 -0
- package/dist/audit/validation/artifacts.d.ts +4 -0
- package/dist/audit/validation/artifacts.d.ts.map +1 -0
- package/dist/audit/validation/artifacts.js +313 -0
- package/dist/audit/validation/artifacts.js.map +1 -0
- package/dist/audit/validation/auditResults.d.ts +16 -0
- package/dist/audit/validation/auditResults.d.ts.map +1 -0
- package/dist/audit/validation/auditResults.js +619 -0
- package/dist/audit/validation/auditResults.js.map +1 -0
- package/dist/audit/validation/designFindingGrounding.d.ts +33 -0
- package/dist/audit/validation/designFindingGrounding.d.ts.map +1 -0
- package/dist/audit/validation/designFindingGrounding.js +43 -0
- package/dist/audit/validation/designFindingGrounding.js.map +1 -0
- package/dist/audit/validation/quoteGrounding.d.ts +18 -0
- package/dist/audit/validation/quoteGrounding.d.ts.map +1 -0
- package/dist/audit/validation/quoteGrounding.js +18 -0
- package/dist/audit/validation/quoteGrounding.js.map +1 -0
- package/dist/audit/validation/sessionConfig.d.ts +8 -0
- package/dist/audit/validation/sessionConfig.d.ts.map +1 -0
- package/dist/audit/validation/sessionConfig.js +334 -0
- package/dist/audit/validation/sessionConfig.js.map +1 -0
- package/dist/remediate/contractPipeline/artifactStore.d.ts +58 -0
- package/dist/remediate/contractPipeline/artifactStore.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/artifactStore.js +201 -0
- package/dist/remediate/contractPipeline/artifactStore.js.map +1 -0
- package/dist/remediate/contractPipeline/cyclicSeamResolution.d.ts +68 -0
- package/dist/remediate/contractPipeline/cyclicSeamResolution.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/cyclicSeamResolution.js +151 -0
- package/dist/remediate/contractPipeline/cyclicSeamResolution.js.map +1 -0
- package/dist/remediate/contractPipeline/derive.d.ts +88 -0
- package/dist/remediate/contractPipeline/derive.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/derive.js +216 -0
- package/dist/remediate/contractPipeline/derive.js.map +1 -0
- package/dist/remediate/contractPipeline/idRegistry.d.ts +49 -0
- package/dist/remediate/contractPipeline/idRegistry.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/idRegistry.js +57 -0
- package/dist/remediate/contractPipeline/idRegistry.js.map +1 -0
- package/dist/remediate/contractPipeline/reviewSnapshot.d.ts +52 -0
- package/dist/remediate/contractPipeline/reviewSnapshot.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/reviewSnapshot.js +116 -0
- package/dist/remediate/contractPipeline/reviewSnapshot.js.map +1 -0
- package/dist/remediate/contractPipeline/semanticProjection.d.ts +46 -0
- package/dist/remediate/contractPipeline/semanticProjection.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/semanticProjection.js +102 -0
- package/dist/remediate/contractPipeline/semanticProjection.js.map +1 -0
- package/dist/remediate/coverage/findingLedger.d.ts +99 -0
- package/dist/remediate/coverage/findingLedger.d.ts.map +1 -0
- package/dist/remediate/coverage/findingLedger.js +110 -0
- package/dist/remediate/coverage/findingLedger.js.map +1 -0
- package/dist/remediate/dedup/crossLensDedup.d.ts +9 -0
- package/dist/remediate/dedup/crossLensDedup.d.ts.map +1 -0
- package/dist/remediate/dedup/crossLensDedup.js +191 -0
- package/dist/remediate/dedup/crossLensDedup.js.map +1 -0
- package/dist/remediate/dispatch/amendmentClaim.d.ts +41 -0
- package/dist/remediate/dispatch/amendmentClaim.d.ts.map +1 -0
- package/dist/remediate/dispatch/amendmentClaim.js +60 -0
- package/dist/remediate/dispatch/amendmentClaim.js.map +1 -0
- package/dist/remediate/dispatch/ownershipRegistry.d.ts +97 -0
- package/dist/remediate/dispatch/ownershipRegistry.d.ts.map +1 -0
- package/dist/remediate/dispatch/ownershipRegistry.js +217 -0
- package/dist/remediate/dispatch/ownershipRegistry.js.map +1 -0
- package/dist/remediate/findingFilter.d.ts +42 -0
- package/dist/remediate/findingFilter.d.ts.map +1 -0
- package/dist/remediate/findingFilter.js +62 -0
- package/dist/remediate/findingFilter.js.map +1 -0
- package/dist/remediate/index.d.ts +45 -0
- package/dist/remediate/index.d.ts.map +1 -0
- package/dist/remediate/index.js +434 -0
- package/dist/remediate/index.js.map +1 -0
- package/dist/remediate/intake.d.ts +168 -0
- package/dist/remediate/intake.d.ts.map +1 -0
- package/dist/remediate/intake.js +340 -0
- package/dist/remediate/intake.js.map +1 -0
- package/dist/remediate/intent/checkpointFilter.d.ts +14 -0
- package/dist/remediate/intent/checkpointFilter.d.ts.map +1 -0
- package/dist/remediate/intent/checkpointFilter.js +111 -0
- package/dist/remediate/intent/checkpointFilter.js.map +1 -0
- package/dist/remediate/phases/close.d.ts +32 -0
- package/dist/remediate/phases/close.d.ts.map +1 -0
- package/dist/remediate/phases/close.js +992 -0
- package/dist/remediate/phases/close.js.map +1 -0
- package/dist/remediate/phases/constants.d.ts +3 -0
- package/dist/remediate/phases/constants.d.ts.map +1 -0
- package/dist/remediate/phases/constants.js +3 -0
- package/dist/remediate/phases/constants.js.map +1 -0
- package/dist/remediate/phases/grounding.d.ts +77 -0
- package/dist/remediate/phases/grounding.d.ts.map +1 -0
- package/dist/remediate/phases/grounding.js +153 -0
- package/dist/remediate/phases/grounding.js.map +1 -0
- package/dist/remediate/phases/plan.d.ts +113 -0
- package/dist/remediate/phases/plan.d.ts.map +1 -0
- package/dist/remediate/phases/plan.js +988 -0
- package/dist/remediate/phases/plan.js.map +1 -0
- package/dist/remediate/phases/triage.d.ts +4 -0
- package/dist/remediate/phases/triage.d.ts.map +1 -0
- package/dist/remediate/phases/triage.js +175 -0
- package/dist/remediate/phases/triage.js.map +1 -0
- package/dist/remediate/phases/workerTasks.d.ts +21 -0
- package/dist/remediate/phases/workerTasks.d.ts.map +1 -0
- package/dist/remediate/phases/workerTasks.js +31 -0
- package/dist/remediate/phases/workerTasks.js.map +1 -0
- package/dist/remediate/providers/claudeCodeProvider.d.ts +12 -0
- package/dist/remediate/providers/claudeCodeProvider.d.ts.map +1 -0
- package/dist/remediate/providers/claudeCodeProvider.js +24 -0
- package/dist/remediate/providers/claudeCodeProvider.js.map +1 -0
- package/dist/remediate/providers/constants.d.ts +2 -0
- package/dist/remediate/providers/constants.d.ts.map +1 -0
- package/dist/remediate/providers/constants.js +2 -0
- package/dist/remediate/providers/constants.js.map +1 -0
- package/dist/remediate/providers/index.d.ts +15 -0
- package/dist/remediate/providers/index.d.ts.map +1 -0
- package/dist/remediate/providers/index.js +22 -0
- package/dist/remediate/providers/index.js.map +1 -0
- package/dist/remediate/providers/opencodeProvider.d.ts +5 -0
- package/dist/remediate/providers/opencodeProvider.d.ts.map +1 -0
- package/dist/remediate/providers/opencodeProvider.js +10 -0
- package/dist/remediate/providers/opencodeProvider.js.map +1 -0
- package/dist/remediate/quota/hostLimits.d.ts +8 -0
- package/dist/remediate/quota/hostLimits.d.ts.map +1 -0
- package/dist/remediate/quota/hostLimits.js +9 -0
- package/dist/remediate/quota/hostLimits.js.map +1 -0
- package/dist/remediate/quota/index.d.ts +8 -0
- package/dist/remediate/quota/index.d.ts.map +1 -0
- package/dist/remediate/quota/index.js +12 -0
- package/dist/remediate/quota/index.js.map +1 -0
- package/dist/remediate/review/reviewGate.d.ts +72 -0
- package/dist/remediate/review/reviewGate.d.ts.map +1 -0
- package/dist/remediate/review/reviewGate.js +112 -0
- package/dist/remediate/review/reviewGate.js.map +1 -0
- package/dist/remediate/review/reviewNecessity.d.ts +53 -0
- package/dist/remediate/review/reviewNecessity.d.ts.map +1 -0
- package/dist/remediate/review/reviewNecessity.js +129 -0
- package/dist/remediate/review/reviewNecessity.js.map +1 -0
- package/dist/remediate/state/closingActions.d.ts +3 -0
- package/dist/remediate/state/closingActions.d.ts.map +1 -0
- package/dist/remediate/state/closingActions.js +10 -0
- package/dist/remediate/state/closingActions.js.map +1 -0
- package/dist/remediate/state/itemStatus.d.ts +40 -0
- package/dist/remediate/state/itemStatus.d.ts.map +1 -0
- package/dist/remediate/state/itemStatus.js +138 -0
- package/dist/remediate/state/itemStatus.js.map +1 -0
- package/dist/remediate/state/store.d.ts +65 -0
- package/dist/remediate/state/store.d.ts.map +1 -0
- package/dist/remediate/state/store.js +141 -0
- package/dist/remediate/state/store.js.map +1 -0
- package/dist/remediate/state/types.d.ts +766 -0
- package/dist/remediate/state/types.d.ts.map +1 -0
- package/dist/remediate/state/types.js +122 -0
- package/dist/remediate/state/types.js.map +1 -0
- package/dist/remediate/steps/contractPipeline.d.ts +173 -0
- package/dist/remediate/steps/contractPipeline.d.ts.map +1 -0
- package/dist/remediate/steps/contractPipeline.js +1229 -0
- package/dist/remediate/steps/contractPipeline.js.map +1 -0
- package/dist/remediate/steps/contractPipelinePrompts.d.ts +72 -0
- package/dist/remediate/steps/contractPipelinePrompts.d.ts.map +1 -0
- package/dist/remediate/steps/contractPipelinePrompts.js +438 -0
- package/dist/remediate/steps/contractPipelinePrompts.js.map +1 -0
- package/dist/remediate/steps/dispatch.d.ts +434 -0
- package/dist/remediate/steps/dispatch.d.ts.map +1 -0
- package/dist/remediate/steps/dispatch.js +2180 -0
- package/dist/remediate/steps/dispatch.js.map +1 -0
- package/dist/remediate/steps/intakeResolver.d.ts +32 -0
- package/dist/remediate/steps/intakeResolver.d.ts.map +1 -0
- package/dist/remediate/steps/intakeResolver.js +310 -0
- package/dist/remediate/steps/intakeResolver.js.map +1 -0
- package/dist/remediate/steps/leanFastPath.d.ts +49 -0
- package/dist/remediate/steps/leanFastPath.d.ts.map +1 -0
- package/dist/remediate/steps/leanFastPath.js +151 -0
- package/dist/remediate/steps/leanFastPath.js.map +1 -0
- package/dist/remediate/steps/nextStep.d.ts +323 -0
- package/dist/remediate/steps/nextStep.d.ts.map +1 -0
- package/dist/remediate/steps/nextStep.js +2721 -0
- package/dist/remediate/steps/nextStep.js.map +1 -0
- package/dist/remediate/steps/prompts.d.ts +26 -0
- package/dist/remediate/steps/prompts.d.ts.map +1 -0
- package/dist/remediate/steps/prompts.js +370 -0
- package/dist/remediate/steps/prompts.js.map +1 -0
- package/dist/remediate/steps/providerNodeDispatch.d.ts +42 -0
- package/dist/remediate/steps/providerNodeDispatch.d.ts.map +1 -0
- package/dist/remediate/steps/providerNodeDispatch.js +100 -0
- package/dist/remediate/steps/providerNodeDispatch.js.map +1 -0
- package/dist/remediate/steps/rollingSession.d.ts +84 -0
- package/dist/remediate/steps/rollingSession.d.ts.map +1 -0
- package/dist/remediate/steps/rollingSession.js +147 -0
- package/dist/remediate/steps/rollingSession.js.map +1 -0
- package/dist/remediate/steps/stepUtils.d.ts +63 -0
- package/dist/remediate/steps/stepUtils.d.ts.map +1 -0
- package/dist/remediate/steps/stepUtils.js +117 -0
- package/dist/remediate/steps/stepUtils.js.map +1 -0
- package/dist/remediate/steps/stepWriter.d.ts +27 -0
- package/dist/remediate/steps/stepWriter.d.ts.map +1 -0
- package/dist/remediate/steps/stepWriter.js +37 -0
- package/dist/remediate/steps/stepWriter.js.map +1 -0
- package/dist/remediate/steps/types.d.ts +83 -0
- package/dist/remediate/steps/types.d.ts.map +1 -0
- package/dist/remediate/steps/types.js +6 -0
- package/dist/remediate/steps/types.js.map +1 -0
- package/dist/remediate/types/options.d.ts +6 -0
- package/dist/remediate/types/options.d.ts.map +1 -0
- package/dist/remediate/types/options.js +2 -0
- package/dist/remediate/types/options.js.map +1 -0
- package/dist/remediate/types/workerSession.d.ts +36 -0
- package/dist/remediate/types/workerSession.d.ts.map +1 -0
- package/dist/remediate/types/workerSession.js +13 -0
- package/dist/remediate/types/workerSession.js.map +1 -0
- package/dist/remediate/utils/commands.d.ts +17 -0
- package/dist/remediate/utils/commands.d.ts.map +1 -0
- package/dist/remediate/utils/commands.js +26 -0
- package/dist/remediate/utils/commands.js.map +1 -0
- package/dist/remediate/utils/fileIntegrity.d.ts +27 -0
- package/dist/remediate/utils/fileIntegrity.d.ts.map +1 -0
- package/dist/remediate/utils/fileIntegrity.js +201 -0
- package/dist/remediate/utils/fileIntegrity.js.map +1 -0
- package/dist/remediate/utils/hostAssets.d.ts +18 -0
- package/dist/remediate/utils/hostAssets.d.ts.map +1 -0
- package/dist/remediate/utils/hostAssets.js +31 -0
- package/dist/remediate/utils/hostAssets.js.map +1 -0
- package/dist/remediate/validation/artifacts.d.ts +9 -0
- package/dist/remediate/validation/artifacts.d.ts.map +1 -0
- package/dist/remediate/validation/artifacts.js +316 -0
- package/dist/remediate/validation/artifacts.js.map +1 -0
- package/dist/remediate/validation/contractPipeline.d.ts +36 -0
- package/dist/remediate/validation/contractPipeline.d.ts.map +1 -0
- package/dist/remediate/validation/contractPipeline.js +569 -0
- package/dist/remediate/validation/contractPipeline.js.map +1 -0
- package/dist/remediate/validation/contractPipelineGates.d.ts +161 -0
- package/dist/remediate/validation/contractPipelineGates.d.ts.map +1 -0
- package/dist/remediate/validation/contractPipelineGates.js +739 -0
- package/dist/remediate/validation/contractPipelineGates.js.map +1 -0
- package/dist/remediate/validation/remediationState.d.ts +8 -0
- package/dist/remediate/validation/remediationState.d.ts.map +1 -0
- package/dist/remediate/validation/remediationState.js +187 -0
- package/dist/remediate/validation/remediationState.js.map +1 -0
- package/dist/shared/agentReflections.d.ts +61 -0
- package/dist/shared/agentReflections.d.ts.map +1 -0
- package/dist/shared/agentReflections.js +180 -0
- package/dist/shared/agentReflections.js.map +1 -0
- package/dist/shared/concurrency.d.ts +16 -0
- package/dist/shared/concurrency.d.ts.map +1 -0
- package/dist/shared/concurrency.js +34 -0
- package/dist/shared/concurrency.js.map +1 -0
- package/dist/shared/contracts.d.ts +2 -0
- package/dist/shared/contracts.d.ts.map +1 -0
- package/dist/shared/contracts.js +2 -0
- package/dist/shared/contracts.js.map +1 -0
- package/dist/shared/dispatch/rollingDispatch.d.ts +192 -0
- package/dist/shared/dispatch/rollingDispatch.d.ts.map +1 -0
- package/dist/shared/dispatch/rollingDispatch.js +389 -0
- package/dist/shared/dispatch/rollingDispatch.js.map +1 -0
- package/dist/shared/dispatch/tierRank.d.ts +53 -0
- package/dist/shared/dispatch/tierRank.d.ts.map +1 -0
- package/dist/shared/dispatch/tierRank.js +69 -0
- package/dist/shared/dispatch/tierRank.js.map +1 -0
- package/dist/shared/engine/obligationEngine.d.ts +159 -0
- package/dist/shared/engine/obligationEngine.d.ts.map +1 -0
- package/dist/shared/engine/obligationEngine.js +124 -0
- package/dist/shared/engine/obligationEngine.js.map +1 -0
- package/dist/shared/findingIdentitySignature.d.ts +82 -0
- package/dist/shared/findingIdentitySignature.d.ts.map +1 -0
- package/dist/shared/findingIdentitySignature.js +114 -0
- package/dist/shared/findingIdentitySignature.js.map +1 -0
- package/dist/shared/git.d.ts +18 -0
- package/dist/shared/git.d.ts.map +1 -0
- package/dist/shared/git.js +63 -0
- package/dist/shared/git.js.map +1 -0
- package/dist/shared/hash.d.ts +16 -0
- package/dist/shared/hash.d.ts.map +1 -0
- package/dist/shared/hash.js +36 -0
- package/dist/shared/hash.js.map +1 -0
- package/dist/shared/hostAssets.d.ts +40 -0
- package/dist/shared/hostAssets.d.ts.map +1 -0
- package/dist/shared/hostAssets.js +110 -0
- package/dist/shared/hostAssets.js.map +1 -0
- package/dist/shared/ids.d.ts +18 -0
- package/dist/shared/ids.d.ts.map +1 -0
- package/dist/shared/ids.js +27 -0
- package/dist/shared/ids.js.map +1 -0
- package/dist/shared/index.d.ts +150 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +112 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/intent/clauseInterpreter.d.ts +84 -0
- package/dist/shared/intent/clauseInterpreter.d.ts.map +1 -0
- package/dist/shared/intent/clauseInterpreter.js +183 -0
- package/dist/shared/intent/clauseInterpreter.js.map +1 -0
- package/dist/shared/intent/freeFormIntentInterpreter.d.ts +46 -0
- package/dist/shared/intent/freeFormIntentInterpreter.d.ts.map +1 -0
- package/dist/shared/intent/freeFormIntentInterpreter.js +126 -0
- package/dist/shared/intent/freeFormIntentInterpreter.js.map +1 -0
- package/dist/shared/intent/sharedIntentData.d.ts +16 -0
- package/dist/shared/intent/sharedIntentData.d.ts.map +1 -0
- package/dist/shared/intent/sharedIntentData.js +38 -0
- package/dist/shared/intent/sharedIntentData.js.map +1 -0
- package/dist/shared/io/auditToolsPaths.d.ts +36 -0
- package/dist/shared/io/auditToolsPaths.d.ts.map +1 -0
- package/dist/shared/io/auditToolsPaths.js +47 -0
- package/dist/shared/io/auditToolsPaths.js.map +1 -0
- package/dist/shared/io/json.d.ts +30 -0
- package/dist/shared/io/json.d.ts.map +1 -0
- package/dist/shared/io/json.js +183 -0
- package/dist/shared/io/json.js.map +1 -0
- package/dist/shared/io/stepContractWriter.d.ts +103 -0
- package/dist/shared/io/stepContractWriter.d.ts.map +1 -0
- package/dist/shared/io/stepContractWriter.js +85 -0
- package/dist/shared/io/stepContractWriter.js.map +1 -0
- package/dist/shared/observability/runLog.d.ts +37 -0
- package/dist/shared/observability/runLog.d.ts.map +1 -0
- package/dist/shared/observability/runLog.js +40 -0
- package/dist/shared/observability/runLog.js.map +1 -0
- package/dist/shared/opencodePermissions.d.ts +49 -0
- package/dist/shared/opencodePermissions.d.ts.map +1 -0
- package/dist/shared/opencodePermissions.js +118 -0
- package/dist/shared/opencodePermissions.js.map +1 -0
- package/dist/shared/parsing/stringAwareScanner.d.ts +32 -0
- package/dist/shared/parsing/stringAwareScanner.d.ts.map +1 -0
- package/dist/shared/parsing/stringAwareScanner.js +51 -0
- package/dist/shared/parsing/stringAwareScanner.js.map +1 -0
- package/dist/shared/prompts.d.ts +47 -0
- package/dist/shared/prompts.d.ts.map +1 -0
- package/dist/shared/prompts.js +41 -0
- package/dist/shared/prompts.js.map +1 -0
- package/dist/shared/providers/claudeCodeProvider.d.ts +56 -0
- package/dist/shared/providers/claudeCodeProvider.d.ts.map +1 -0
- package/dist/shared/providers/claudeCodeProvider.js +67 -0
- package/dist/shared/providers/claudeCodeProvider.js.map +1 -0
- package/dist/shared/providers/codexProvider.d.ts +37 -0
- package/dist/shared/providers/codexProvider.d.ts.map +1 -0
- package/dist/shared/providers/codexProvider.js +79 -0
- package/dist/shared/providers/codexProvider.js.map +1 -0
- package/dist/shared/providers/constants.d.ts +4 -0
- package/dist/shared/providers/constants.d.ts.map +1 -0
- package/dist/shared/providers/constants.js +4 -0
- package/dist/shared/providers/constants.js.map +1 -0
- package/dist/shared/providers/localSubprocessProvider.d.ts +10 -0
- package/dist/shared/providers/localSubprocessProvider.d.ts.map +1 -0
- package/dist/shared/providers/localSubprocessProvider.js +20 -0
- package/dist/shared/providers/localSubprocessProvider.js.map +1 -0
- package/dist/shared/providers/openAiCompatibleProvider.d.ts +62 -0
- package/dist/shared/providers/openAiCompatibleProvider.d.ts.map +1 -0
- package/dist/shared/providers/openAiCompatibleProvider.js +333 -0
- package/dist/shared/providers/openAiCompatibleProvider.js.map +1 -0
- package/dist/shared/providers/opencodeLaunch.d.ts +28 -0
- package/dist/shared/providers/opencodeLaunch.d.ts.map +1 -0
- package/dist/shared/providers/opencodeLaunch.js +39 -0
- package/dist/shared/providers/opencodeLaunch.js.map +1 -0
- package/dist/shared/providers/opencodeProvider.d.ts +19 -0
- package/dist/shared/providers/opencodeProvider.d.ts.map +1 -0
- package/dist/shared/providers/opencodeProvider.js +41 -0
- package/dist/shared/providers/opencodeProvider.js.map +1 -0
- package/dist/shared/providers/providerConfirmation.d.ts +56 -0
- package/dist/shared/providers/providerConfirmation.d.ts.map +1 -0
- package/dist/shared/providers/providerConfirmation.js +195 -0
- package/dist/shared/providers/providerConfirmation.js.map +1 -0
- package/dist/shared/providers/providerDiagnostics.d.ts +11 -0
- package/dist/shared/providers/providerDiagnostics.d.ts.map +1 -0
- package/dist/shared/providers/providerDiagnostics.js +28 -0
- package/dist/shared/providers/providerDiagnostics.js.map +1 -0
- package/dist/shared/providers/providerFactory.d.ts +72 -0
- package/dist/shared/providers/providerFactory.d.ts.map +1 -0
- package/dist/shared/providers/providerFactory.js +246 -0
- package/dist/shared/providers/providerFactory.js.map +1 -0
- package/dist/shared/providers/providerKeyedFactory.d.ts +14 -0
- package/dist/shared/providers/providerKeyedFactory.d.ts.map +1 -0
- package/dist/shared/providers/providerKeyedFactory.js +16 -0
- package/dist/shared/providers/providerKeyedFactory.js.map +1 -0
- package/dist/shared/providers/spawnLoggedCommand.d.ts +10 -0
- package/dist/shared/providers/spawnLoggedCommand.d.ts.map +1 -0
- package/dist/shared/providers/spawnLoggedCommand.js +304 -0
- package/dist/shared/providers/spawnLoggedCommand.js.map +1 -0
- package/dist/shared/providers/subprocessTemplateProvider.d.ts +19 -0
- package/dist/shared/providers/subprocessTemplateProvider.d.ts.map +1 -0
- package/dist/shared/providers/subprocessTemplateProvider.js +91 -0
- package/dist/shared/providers/subprocessTemplateProvider.js.map +1 -0
- package/dist/shared/providers/types.d.ts +43 -0
- package/dist/shared/providers/types.d.ts.map +1 -0
- package/dist/shared/providers/types.js +2 -0
- package/dist/shared/providers/types.js.map +1 -0
- package/dist/shared/providers/workerTaskLaunch.d.ts +32 -0
- package/dist/shared/providers/workerTaskLaunch.d.ts.map +1 -0
- package/dist/shared/providers/workerTaskLaunch.js +27 -0
- package/dist/shared/providers/workerTaskLaunch.js.map +1 -0
- package/dist/shared/quota/antigravityQuotaSource.d.ts +44 -0
- package/dist/shared/quota/antigravityQuotaSource.d.ts.map +1 -0
- package/dist/shared/quota/antigravityQuotaSource.js +101 -0
- package/dist/shared/quota/antigravityQuotaSource.js.map +1 -0
- package/dist/shared/quota/capacity.d.ts +283 -0
- package/dist/shared/quota/capacity.d.ts.map +1 -0
- package/dist/shared/quota/capacity.js +290 -0
- package/dist/shared/quota/capacity.js.map +1 -0
- package/dist/shared/quota/claudeCodeJsonLines.d.ts +15 -0
- package/dist/shared/quota/claudeCodeJsonLines.d.ts.map +1 -0
- package/dist/shared/quota/claudeCodeJsonLines.js +34 -0
- package/dist/shared/quota/claudeCodeJsonLines.js.map +1 -0
- package/dist/shared/quota/claudeOAuthQuotaSource.d.ts +56 -0
- package/dist/shared/quota/claudeOAuthQuotaSource.d.ts.map +1 -0
- package/dist/shared/quota/claudeOAuthQuotaSource.js +136 -0
- package/dist/shared/quota/claudeOAuthQuotaSource.js.map +1 -0
- package/dist/shared/quota/codexQuotaSource.d.ts +49 -0
- package/dist/shared/quota/codexQuotaSource.d.ts.map +1 -0
- package/dist/shared/quota/codexQuotaSource.js +96 -0
- package/dist/shared/quota/codexQuotaSource.js.map +1 -0
- package/dist/shared/quota/compositeQuotaSource.d.ts +29 -0
- package/dist/shared/quota/compositeQuotaSource.d.ts.map +1 -0
- package/dist/shared/quota/compositeQuotaSource.js +58 -0
- package/dist/shared/quota/compositeQuotaSource.js.map +1 -0
- package/dist/shared/quota/copilotQuotaSource.d.ts +57 -0
- package/dist/shared/quota/copilotQuotaSource.d.ts.map +1 -0
- package/dist/shared/quota/copilotQuotaSource.js +141 -0
- package/dist/shared/quota/copilotQuotaSource.js.map +1 -0
- package/dist/shared/quota/errorParsers/claudeCodeErrorParser.d.ts +7 -0
- package/dist/shared/quota/errorParsers/claudeCodeErrorParser.d.ts.map +1 -0
- package/dist/shared/quota/errorParsers/claudeCodeErrorParser.js +33 -0
- package/dist/shared/quota/errorParsers/claudeCodeErrorParser.js.map +1 -0
- package/dist/shared/quota/errorParsers/genericErrorParser.d.ts +10 -0
- package/dist/shared/quota/errorParsers/genericErrorParser.d.ts.map +1 -0
- package/dist/shared/quota/errorParsers/genericErrorParser.js +8 -0
- package/dist/shared/quota/errorParsers/genericErrorParser.js.map +1 -0
- package/dist/shared/quota/errorParsers/index.d.ts +6 -0
- package/dist/shared/quota/errorParsers/index.d.ts.map +1 -0
- package/dist/shared/quota/errorParsers/index.js +16 -0
- package/dist/shared/quota/errorParsers/index.js.map +1 -0
- package/dist/shared/quota/errorParsing.d.ts +8 -0
- package/dist/shared/quota/errorParsing.d.ts.map +1 -0
- package/dist/shared/quota/errorParsing.js +129 -0
- package/dist/shared/quota/errorParsing.js.map +1 -0
- package/dist/shared/quota/fileLock.d.ts +9 -0
- package/dist/shared/quota/fileLock.d.ts.map +1 -0
- package/dist/shared/quota/fileLock.js +202 -0
- package/dist/shared/quota/fileLock.js.map +1 -0
- package/dist/shared/quota/hostLimits.d.ts +16 -0
- package/dist/shared/quota/hostLimits.d.ts.map +1 -0
- package/dist/shared/quota/hostLimits.js +57 -0
- package/dist/shared/quota/hostLimits.js.map +1 -0
- package/dist/shared/quota/httpQuotaSource.d.ts +87 -0
- package/dist/shared/quota/httpQuotaSource.d.ts.map +1 -0
- package/dist/shared/quota/httpQuotaSource.js +90 -0
- package/dist/shared/quota/httpQuotaSource.js.map +1 -0
- package/dist/shared/quota/learnedQuotaSource.d.ts +8 -0
- package/dist/shared/quota/learnedQuotaSource.d.ts.map +1 -0
- package/dist/shared/quota/learnedQuotaSource.js +26 -0
- package/dist/shared/quota/learnedQuotaSource.js.map +1 -0
- package/dist/shared/quota/limits.d.ts +35 -0
- package/dist/shared/quota/limits.d.ts.map +1 -0
- package/dist/shared/quota/limits.js +110 -0
- package/dist/shared/quota/limits.js.map +1 -0
- package/dist/shared/quota/openCodeQuotaSource.d.ts +18 -0
- package/dist/shared/quota/openCodeQuotaSource.d.ts.map +1 -0
- package/dist/shared/quota/openCodeQuotaSource.js +84 -0
- package/dist/shared/quota/openCodeQuotaSource.js.map +1 -0
- package/dist/shared/quota/quotaSource.d.ts +29 -0
- package/dist/shared/quota/quotaSource.d.ts.map +1 -0
- package/dist/shared/quota/quotaSource.js +12 -0
- package/dist/shared/quota/quotaSource.js.map +1 -0
- package/dist/shared/quota/rollingEngine.d.ts +130 -0
- package/dist/shared/quota/rollingEngine.d.ts.map +1 -0
- package/dist/shared/quota/rollingEngine.js +153 -0
- package/dist/shared/quota/rollingEngine.js.map +1 -0
- package/dist/shared/quota/scheduler.d.ts +94 -0
- package/dist/shared/quota/scheduler.d.ts.map +1 -0
- package/dist/shared/quota/scheduler.js +313 -0
- package/dist/shared/quota/scheduler.js.map +1 -0
- package/dist/shared/quota/slidingWindow.d.ts +5 -0
- package/dist/shared/quota/slidingWindow.d.ts.map +1 -0
- package/dist/shared/quota/slidingWindow.js +29 -0
- package/dist/shared/quota/slidingWindow.js.map +1 -0
- package/dist/shared/quota/state.d.ts +27 -0
- package/dist/shared/quota/state.d.ts.map +1 -0
- package/dist/shared/quota/state.js +204 -0
- package/dist/shared/quota/state.js.map +1 -0
- package/dist/shared/quota/types.d.ts +109 -0
- package/dist/shared/quota/types.d.ts.map +1 -0
- package/dist/shared/quota/types.js +56 -0
- package/dist/shared/quota/types.js.map +1 -0
- package/dist/shared/reReview/projectionDiff.d.ts +65 -0
- package/dist/shared/reReview/projectionDiff.d.ts.map +1 -0
- package/dist/shared/reReview/projectionDiff.js +144 -0
- package/dist/shared/reReview/projectionDiff.js.map +1 -0
- package/dist/shared/rolling/pausedState.d.ts +109 -0
- package/dist/shared/rolling/pausedState.d.ts.map +1 -0
- package/dist/shared/rolling/pausedState.js +100 -0
- package/dist/shared/rolling/pausedState.js.map +1 -0
- package/dist/shared/tokens.d.ts +24 -0
- package/dist/shared/tokens.d.ts.map +1 -0
- package/dist/shared/tokens.js +54 -0
- package/dist/shared/tokens.js.map +1 -0
- package/dist/shared/tooling/allowlistedExec.d.ts +45 -0
- package/dist/shared/tooling/allowlistedExec.d.ts.map +1 -0
- package/dist/shared/tooling/allowlistedExec.js +340 -0
- package/dist/shared/tooling/allowlistedExec.js.map +1 -0
- package/dist/shared/tooling/analyzerDeps.d.ts +65 -0
- package/dist/shared/tooling/analyzerDeps.d.ts.map +1 -0
- package/dist/shared/tooling/analyzerDeps.js +130 -0
- package/dist/shared/tooling/analyzerDeps.js.map +1 -0
- package/dist/shared/tooling/exec.d.ts +99 -0
- package/dist/shared/tooling/exec.d.ts.map +1 -0
- package/dist/shared/tooling/exec.js +217 -0
- package/dist/shared/tooling/exec.js.map +1 -0
- package/dist/shared/tooling/repoConventions.d.ts +23 -0
- package/dist/shared/tooling/repoConventions.d.ts.map +1 -0
- package/dist/shared/tooling/repoConventions.js +177 -0
- package/dist/shared/tooling/repoConventions.js.map +1 -0
- package/dist/shared/tooling/testCommand.d.ts +17 -0
- package/dist/shared/tooling/testCommand.d.ts.map +1 -0
- package/dist/shared/tooling/testCommand.js +106 -0
- package/dist/shared/tooling/testCommand.js.map +1 -0
- package/dist/shared/types/accessDeclaration.d.ts +16 -0
- package/dist/shared/types/accessDeclaration.d.ts.map +1 -0
- package/dist/shared/types/accessDeclaration.js +9 -0
- package/dist/shared/types/accessDeclaration.js.map +1 -0
- package/dist/shared/types/contractPipeline/design.d.ts +74 -0
- package/dist/shared/types/contractPipeline/design.d.ts.map +1 -0
- package/dist/shared/types/contractPipeline/design.js +10 -0
- package/dist/shared/types/contractPipeline/design.js.map +1 -0
- package/dist/shared/types/contractPipeline/goal.d.ts +41 -0
- package/dist/shared/types/contractPipeline/goal.d.ts.map +1 -0
- package/dist/shared/types/contractPipeline/goal.js +10 -0
- package/dist/shared/types/contractPipeline/goal.js.map +1 -0
- package/dist/shared/types/contractPipeline/implementation.d.ts +64 -0
- package/dist/shared/types/contractPipeline/implementation.d.ts.map +1 -0
- package/dist/shared/types/contractPipeline/implementation.js +8 -0
- package/dist/shared/types/contractPipeline/implementation.js.map +1 -0
- package/dist/shared/types/contractPipeline/obligations.d.ts +141 -0
- package/dist/shared/types/contractPipeline/obligations.d.ts.map +1 -0
- package/dist/shared/types/contractPipeline/obligations.js +16 -0
- package/dist/shared/types/contractPipeline/obligations.js.map +1 -0
- package/dist/shared/types/contractPipeline/verification.d.ts +64 -0
- package/dist/shared/types/contractPipeline/verification.d.ts.map +1 -0
- package/dist/shared/types/contractPipeline/verification.js +10 -0
- package/dist/shared/types/contractPipeline/verification.js.map +1 -0
- package/dist/shared/types/contractPipeline.d.ts +36 -0
- package/dist/shared/types/contractPipeline.d.ts.map +1 -0
- package/dist/shared/types/contractPipeline.js +31 -0
- package/dist/shared/types/contractPipeline.js.map +1 -0
- package/dist/shared/types/disposition.d.ts +46 -0
- package/dist/shared/types/disposition.d.ts.map +1 -0
- package/dist/shared/types/disposition.js +22 -0
- package/dist/shared/types/disposition.js.map +1 -0
- package/dist/shared/types/finding.d.ts +1463 -0
- package/dist/shared/types/finding.d.ts.map +1 -0
- package/dist/shared/types/finding.js +234 -0
- package/dist/shared/types/finding.js.map +1 -0
- package/dist/shared/types/flows.d.ts +84 -0
- package/dist/shared/types/flows.d.ts.map +1 -0
- package/dist/shared/types/flows.js +23 -0
- package/dist/shared/types/flows.js.map +1 -0
- package/dist/shared/types/graph.d.ts +359 -0
- package/dist/shared/types/graph.d.ts.map +1 -0
- package/dist/shared/types/graph.js +38 -0
- package/dist/shared/types/graph.js.map +1 -0
- package/dist/shared/types/intentCheckpoint.d.ts +95 -0
- package/dist/shared/types/intentCheckpoint.d.ts.map +1 -0
- package/dist/shared/types/intentCheckpoint.js +2 -0
- package/dist/shared/types/intentCheckpoint.js.map +1 -0
- package/dist/shared/types/intentInterpretation.d.ts +57 -0
- package/dist/shared/types/intentInterpretation.d.ts.map +1 -0
- package/dist/shared/types/intentInterpretation.js +20 -0
- package/dist/shared/types/intentInterpretation.js.map +1 -0
- package/dist/shared/types/lens.d.ts +38 -0
- package/dist/shared/types/lens.d.ts.map +1 -0
- package/dist/shared/types/lens.js +80 -0
- package/dist/shared/types/lens.js.map +1 -0
- package/dist/shared/types/obligationLedger.d.ts +35 -0
- package/dist/shared/types/obligationLedger.d.ts.map +1 -0
- package/dist/shared/types/obligationLedger.js +77 -0
- package/dist/shared/types/obligationLedger.js.map +1 -0
- package/dist/shared/types/providerConfirmation.d.ts +51 -0
- package/dist/shared/types/providerConfirmation.d.ts.map +1 -0
- package/dist/shared/types/providerConfirmation.js +19 -0
- package/dist/shared/types/providerConfirmation.js.map +1 -0
- package/dist/shared/types/remediationOutcome.d.ts +41 -0
- package/dist/shared/types/remediationOutcome.d.ts.map +1 -0
- package/dist/shared/types/remediationOutcome.js +7 -0
- package/dist/shared/types/remediationOutcome.js.map +1 -0
- package/dist/shared/types/risk.d.ts +52 -0
- package/dist/shared/types/risk.d.ts.map +1 -0
- package/dist/shared/types/risk.js +17 -0
- package/dist/shared/types/risk.js.map +1 -0
- package/dist/shared/types/rollingDispatch.d.ts +61 -0
- package/dist/shared/types/rollingDispatch.d.ts.map +1 -0
- package/dist/shared/types/rollingDispatch.js +19 -0
- package/dist/shared/types/rollingDispatch.js.map +1 -0
- package/dist/shared/types/runLedger.d.ts +18 -0
- package/dist/shared/types/runLedger.d.ts.map +1 -0
- package/dist/shared/types/runLedger.js +7 -0
- package/dist/shared/types/runLedger.js.map +1 -0
- package/dist/shared/types/sessionConfig.d.ts +294 -0
- package/dist/shared/types/sessionConfig.d.ts.map +1 -0
- package/dist/shared/types/sessionConfig.js +44 -0
- package/dist/shared/types/sessionConfig.js.map +1 -0
- package/dist/shared/types/stepContract.d.ts +10 -0
- package/dist/shared/types/stepContract.d.ts.map +1 -0
- package/dist/shared/types/stepContract.js +4 -0
- package/dist/shared/types/stepContract.js.map +1 -0
- package/dist/shared/types/surfaces.d.ts +73 -0
- package/dist/shared/types/surfaces.d.ts.map +1 -0
- package/dist/shared/types/surfaces.js +21 -0
- package/dist/shared/types/surfaces.js.map +1 -0
- package/dist/shared/validation/basic.d.ts +24 -0
- package/dist/shared/validation/basic.d.ts.map +1 -0
- package/dist/shared/validation/basic.js +57 -0
- package/dist/shared/validation/basic.js.map +1 -0
- package/dist/shared/validation/findingGrounding.d.ts +45 -0
- package/dist/shared/validation/findingGrounding.d.ts.map +1 -0
- package/dist/shared/validation/findingGrounding.js +103 -0
- package/dist/shared/validation/findingGrounding.js.map +1 -0
- package/dist/shared/validation/findingsReport.d.ts +42 -0
- package/dist/shared/validation/findingsReport.d.ts.map +1 -0
- package/dist/shared/validation/findingsReport.js +76 -0
- package/dist/shared/validation/findingsReport.js.map +1 -0
- package/dist/shared/validation/sessionConfig.d.ts +22 -0
- package/dist/shared/validation/sessionConfig.d.ts.map +1 -0
- package/dist/shared/validation/sessionConfig.js +38 -0
- package/dist/shared/validation/sessionConfig.js.map +1 -0
- package/docs/audit-pkg/contracts.md +227 -0
- package/docs/audit-pkg/development.md +112 -0
- package/docs/audit-pkg/history.md +66 -0
- package/docs/audit-pkg/operator-guide.md +204 -0
- package/docs/audit-pkg/product.md +119 -0
- package/docs/audit-pkg/release.md +131 -0
- package/opencode.json +159 -0
- package/package.json +104 -0
- package/remediate-code.mjs +116 -0
- package/schemas/audit_result.schema.json +510 -0
- package/schemas/audit_results.schema.json +514 -0
- package/schemas/audit_task.schema.json +127 -0
- package/schemas/finding.schema.json +261 -0
- package/schemas/lens.schema.json +19 -0
- package/scripts/audit/postinstall.mjs +385 -0
- package/scripts/postinstall.mjs +24 -0
- package/scripts/remediate/postinstall.mjs +387 -0
- package/skills/audit-code/SKILL.md +166 -0
- package/skills/audit-code/agents/openai.yaml +4 -0
- package/skills/audit-code/audit-code.prompt.md +112 -0
- package/skills/audit-code/opencode-command-template.txt +13 -0
- package/skills/remediate-code/SKILL.md +90 -0
- package/skills/remediate-code/agents/openai.yaml +4 -0
- package/skills/remediate-code/remediate-code.prompt.md +94 -0
- package/templates/AGENTS.remediate-code.md +6 -0
|
@@ -0,0 +1,2180 @@
|
|
|
1
|
+
import { mkdir, rename } from "node:fs/promises";
|
|
2
|
+
import { existsSync, readdirSync, readFileSync, realpathSync, statSync, symlinkSync } from "node:fs";
|
|
3
|
+
import { join, relative, dirname, resolve } from "node:path";
|
|
4
|
+
import { OwnershipRegistry } from "../dispatch/ownershipRegistry.js";
|
|
5
|
+
import { routeAmendmentRequest } from "../dispatch/amendmentClaim.js";
|
|
6
|
+
import { toBlockId, fromBlockId } from "../contractPipeline/idRegistry.js";
|
|
7
|
+
import { spawnSync } from "node:child_process";
|
|
8
|
+
import { StateStore } from "../state/store.js";
|
|
9
|
+
import { REMEDIATION_STEP, } from "../state/types.js";
|
|
10
|
+
import { AGENT_FEEDBACK_FILENAME, readJsonFile, readOptionalJsonFile, writeJsonFile, writeTextFile, withFsRetry, formatValidationIssues, detectRepoConventions, formatRepoConventions, toPromptPathToken, estimateTokensFromBytes, buildQuotaSource, severityRank, findingNeedsVerificationBeforeFix, compareTier, mostCapableTier, normalizeRepoPath, hasConfiguredOpenAiCompatible, } from "audit-tools/shared";
|
|
11
|
+
import { validateImplementWorkerResult } from "../validation/artifacts.js";
|
|
12
|
+
import { REMEDIATION_DISPATCH_PLAN_CONTRACT_VERSION, REMEDIATION_DISPATCH_QUOTA_CONTRACT_VERSION, REMEDIATION_WORKER_RESULT_CONTRACT_VERSION, } from "./types.js";
|
|
13
|
+
import { classifyFindingRisk, specIndicatesNoChange, hasExecutableEvidence, dependencyVerifiedComplete, } from "./stepUtils.js";
|
|
14
|
+
import { isTerminalStatus, isVerifiedCompleteStatus, isSkipStatus, } from "../state/itemStatus.js";
|
|
15
|
+
import { resnapshotAffectedFileHashes } from "../utils/fileIntegrity.js";
|
|
16
|
+
import { computeDispatchCapacity, resolveHostActiveSubagentLimit, readQuotaState, buildProviderModelKey, computeBackoffCooldownMs, computeBackoffFailureWeight, summarizeDispatchCapacityPools, } from "../quota/index.js";
|
|
17
|
+
export { resolveHostActiveSubagentLimit };
|
|
18
|
+
export { detectHostActiveSubagentLimit as detectHostConcurrencyFromEnv, } from "../quota/hostLimits.js";
|
|
19
|
+
const DEFAULT_WAVE_SIZE = 5;
|
|
20
|
+
export function normalizeSlotTokens(tokens, count) {
|
|
21
|
+
if (!tokens || tokens.length === 0)
|
|
22
|
+
return new Array(count).fill(0);
|
|
23
|
+
if (tokens.length > count)
|
|
24
|
+
return tokens.slice(0, count);
|
|
25
|
+
if (tokens.length < count)
|
|
26
|
+
return [...tokens, ...new Array(count - tokens.length).fill(0)];
|
|
27
|
+
return tokens;
|
|
28
|
+
}
|
|
29
|
+
function averageSlotTokens(estimatedSlotTokens) {
|
|
30
|
+
if (!estimatedSlotTokens || estimatedSlotTokens.length === 0)
|
|
31
|
+
return 0;
|
|
32
|
+
const total = estimatedSlotTokens.reduce((a, b) => a + b, 0);
|
|
33
|
+
return Math.floor(total / estimatedSlotTokens.length);
|
|
34
|
+
}
|
|
35
|
+
export function resolveHostConcurrencyLimit(options) {
|
|
36
|
+
return resolveHostActiveSubagentLimit({
|
|
37
|
+
explicitLimit: options.hostMaxConcurrent,
|
|
38
|
+
sessionConfig: options.sessionConfig ?? {},
|
|
39
|
+
env: options.env,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function _capacityPoolSummary(poolId, slots, schedule) {
|
|
43
|
+
return {
|
|
44
|
+
pool_id: poolId,
|
|
45
|
+
slots,
|
|
46
|
+
model: schedule.model,
|
|
47
|
+
confidence: schedule.confidence,
|
|
48
|
+
source: schedule.source,
|
|
49
|
+
resolved_limits: schedule.resolved_limits,
|
|
50
|
+
host_concurrency_limit: schedule.host_concurrency_limit,
|
|
51
|
+
cooldown_until: schedule.cooldown_until,
|
|
52
|
+
estimated_wave_tokens: schedule.estimated_wave_tokens,
|
|
53
|
+
binding_cap: schedule.binding_cap ?? "none",
|
|
54
|
+
quota_source_snapshot: schedule.quota_source_snapshot ?? null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Most-capable rank first, so the largest pending items land on the rank with
|
|
59
|
+
* the largest window. Ordering comes from the single shared tier-rank authority
|
|
60
|
+
* (`compareTier`, negated for descending) — no local {small,standard,deep} copy.
|
|
61
|
+
*/
|
|
62
|
+
function sortRosterMostCapableFirst(roster) {
|
|
63
|
+
return [...roster].sort((a, b) => compareTier(b.rank, a.rank));
|
|
64
|
+
}
|
|
65
|
+
export async function scheduleWave(input) {
|
|
66
|
+
const sessionConfig = input.sessionConfig ?? {};
|
|
67
|
+
const providerName = input.providerName ?? sessionConfig.provider ?? "claude-code";
|
|
68
|
+
const hostModel = input.hostModel ?? sessionConfig.block_quota?.host_model ?? null;
|
|
69
|
+
// Quota-key identity: resolved model name, else the host's opaque id, else
|
|
70
|
+
// null → `provider/*`. Per-roster-rank `model_id` overrides per pool below.
|
|
71
|
+
const quotaModelKeySegment = hostModel ?? input.hostModelId ?? null;
|
|
72
|
+
const roster = input.hostModels?.length
|
|
73
|
+
? sortRosterMostCapableFirst(input.hostModels)
|
|
74
|
+
: null;
|
|
75
|
+
const hostLimit = resolveHostConcurrencyLimit({
|
|
76
|
+
hostMaxConcurrent: input.hostMaxConcurrent,
|
|
77
|
+
sessionConfig,
|
|
78
|
+
env: input.env,
|
|
79
|
+
});
|
|
80
|
+
// The capability handshake: the host reported its dispatch model's real
|
|
81
|
+
// context/output window this session (the roster's most capable entry under
|
|
82
|
+
// the multi-rank handshake). Carried into the pool's discoveredLimits so the
|
|
83
|
+
// shared discovered_capability rung sizes the budget to the real window
|
|
84
|
+
// instead of the conservative 32k floor. RPM/TPM stay null and fill from the
|
|
85
|
+
// learned quota state.
|
|
86
|
+
const hostContextTokens = input.hostContextTokens ?? roster?.[0]?.context_tokens ?? null;
|
|
87
|
+
const hostOutputTokens = input.hostOutputTokens ?? roster?.[0]?.output_tokens ?? null;
|
|
88
|
+
const hostCapabilityLimits = hostContextTokens != null || hostOutputTokens != null
|
|
89
|
+
? {
|
|
90
|
+
context_tokens: hostContextTokens,
|
|
91
|
+
output_tokens: hostOutputTokens,
|
|
92
|
+
}
|
|
93
|
+
: null;
|
|
94
|
+
const quota = sessionConfig.quota;
|
|
95
|
+
if (!quota || quota.enabled === false) {
|
|
96
|
+
const cap = hostLimit?.active_subagents ?? DEFAULT_WAVE_SIZE;
|
|
97
|
+
const waveSize = Math.max(1, Math.min(cap, input.itemCount));
|
|
98
|
+
const avgTokens = averageSlotTokens(input.estimatedSlotTokens);
|
|
99
|
+
const schedule = {
|
|
100
|
+
max_concurrent: waveSize,
|
|
101
|
+
estimated_wave_tokens: waveSize * avgTokens,
|
|
102
|
+
cooldown_until: null,
|
|
103
|
+
confidence: "low",
|
|
104
|
+
source: "default",
|
|
105
|
+
resolved_limits: {
|
|
106
|
+
// Honor a host-reported window even with quota disabled; fall back to the
|
|
107
|
+
// conservative floor only when nothing was discovered.
|
|
108
|
+
context_tokens: hostContextTokens ?? 32_000,
|
|
109
|
+
output_tokens: hostOutputTokens ?? 4_096,
|
|
110
|
+
requests_per_minute: null,
|
|
111
|
+
input_tokens_per_minute: null,
|
|
112
|
+
output_tokens_per_minute: null,
|
|
113
|
+
},
|
|
114
|
+
host_concurrency_limit: hostLimit,
|
|
115
|
+
model: hostModel,
|
|
116
|
+
binding_cap: hostLimit && waveSize < input.itemCount ? "host_concurrency" : "none",
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
...schedule,
|
|
120
|
+
capacity_pools: [_capacityPoolSummary(buildProviderModelKey(providerName, quotaModelKeySegment), waveSize, schedule)],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
let quotaEntries = {};
|
|
124
|
+
try {
|
|
125
|
+
const state = await readQuotaState();
|
|
126
|
+
quotaEntries = state.entries;
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
process.stderr.write(`[waveScheduler] readQuotaState failed; falling back to default wave size. ${err instanceof Error ? err.message : String(err)}\n`);
|
|
130
|
+
}
|
|
131
|
+
// The proactive quota snapshot (Claude OAuth source, then learned) so the
|
|
132
|
+
// scheduler can throttle/cooldown from live remaining quota — mirrors
|
|
133
|
+
// audit-code's buildDispatchPool. Cached per key, so one probe per burst.
|
|
134
|
+
const quotaSource = buildQuotaSource({
|
|
135
|
+
halfLifeHours: sessionConfig.quota
|
|
136
|
+
?.empirical_half_life_hours,
|
|
137
|
+
});
|
|
138
|
+
// One capacity pool per reported roster rank (most capable first), each with
|
|
139
|
+
// its own discovered window and quota key; a single pool for the scalar/
|
|
140
|
+
// absent handshake. A rank's opaque `model_id` keys that pool's quota.
|
|
141
|
+
const pools = await Promise.all((roster ?? [null]).map(async (entry) => {
|
|
142
|
+
const poolKey = buildProviderModelKey(providerName, entry?.model_id ?? quotaModelKeySegment);
|
|
143
|
+
const quotaSourceSnapshot = await quotaSource.queryCurrentUsage(poolKey).catch(() => null);
|
|
144
|
+
return {
|
|
145
|
+
id: poolKey,
|
|
146
|
+
providerName,
|
|
147
|
+
hostModel,
|
|
148
|
+
...(entry ? { rank: entry.rank } : {}),
|
|
149
|
+
hostConcurrencyLimit: hostLimit,
|
|
150
|
+
quotaStateEntry: quotaEntries[poolKey] ?? null,
|
|
151
|
+
discoveredLimits: entry
|
|
152
|
+
? {
|
|
153
|
+
context_tokens: entry.context_tokens,
|
|
154
|
+
output_tokens: entry.output_tokens,
|
|
155
|
+
}
|
|
156
|
+
: hostCapabilityLimits,
|
|
157
|
+
quotaSourceSnapshot,
|
|
158
|
+
};
|
|
159
|
+
}));
|
|
160
|
+
const capacity = computeDispatchCapacity({
|
|
161
|
+
pools,
|
|
162
|
+
sessionConfig,
|
|
163
|
+
pendingItemTokens: normalizeSlotTokens(input.estimatedSlotTokens, input.itemCount),
|
|
164
|
+
});
|
|
165
|
+
return {
|
|
166
|
+
...capacity.primary.schedule,
|
|
167
|
+
capacity_pools: summarizeDispatchCapacityPools(capacity),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Build the confirmed `CapacityPool[]` for a dispatch — one pool per reported
|
|
172
|
+
* roster rank (each with its own discovered window + quota key), or a single
|
|
173
|
+
* conservative pool for the scalar/absent handshake. This is the same pool shape
|
|
174
|
+
* `scheduleWave` constructs internally; it is exposed so the rolling dispatch
|
|
175
|
+
* engine (which is fed `confirmedPools` directly) sizes concurrency from the
|
|
176
|
+
* identical quota inputs, never from a raw host flag. Reused by
|
|
177
|
+
* `driveRollingImplementDispatch`.
|
|
178
|
+
*/
|
|
179
|
+
export async function buildConfirmedPools(input) {
|
|
180
|
+
const sessionConfig = input.sessionConfig ?? {};
|
|
181
|
+
const providerName = sessionConfig.provider ?? "claude-code";
|
|
182
|
+
const hostModel = sessionConfig.block_quota
|
|
183
|
+
?.host_model ?? null;
|
|
184
|
+
const quotaModelKeySegment = hostModel ?? input.hostModelId ?? null;
|
|
185
|
+
const roster = input.hostModels?.length
|
|
186
|
+
? sortRosterMostCapableFirst(input.hostModels)
|
|
187
|
+
: null;
|
|
188
|
+
const hostLimit = resolveHostConcurrencyLimit({
|
|
189
|
+
hostMaxConcurrent: input.hostMaxConcurrent,
|
|
190
|
+
sessionConfig,
|
|
191
|
+
env: input.env,
|
|
192
|
+
});
|
|
193
|
+
const hostContextTokens = input.hostContextTokens ?? roster?.[0]?.context_tokens ?? null;
|
|
194
|
+
const hostOutputTokens = input.hostOutputTokens ?? roster?.[0]?.output_tokens ?? null;
|
|
195
|
+
const hostCapabilityLimits = hostContextTokens != null || hostOutputTokens != null
|
|
196
|
+
? { context_tokens: hostContextTokens, output_tokens: hostOutputTokens }
|
|
197
|
+
: null;
|
|
198
|
+
let quotaEntries = {};
|
|
199
|
+
try {
|
|
200
|
+
const state = await readQuotaState();
|
|
201
|
+
quotaEntries = state.entries;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Non-fatal: a missing/locked quota state degrades to no learned entry.
|
|
205
|
+
}
|
|
206
|
+
const quotaSource = buildQuotaSource({
|
|
207
|
+
halfLifeHours: sessionConfig.quota
|
|
208
|
+
?.empirical_half_life_hours,
|
|
209
|
+
});
|
|
210
|
+
const primaryPools = await Promise.all((roster ?? [null]).map(async (entry) => {
|
|
211
|
+
const poolKey = buildProviderModelKey(providerName, entry?.model_id ?? quotaModelKeySegment);
|
|
212
|
+
const quotaSourceSnapshot = await quotaSource.queryCurrentUsage(poolKey).catch(() => null);
|
|
213
|
+
return {
|
|
214
|
+
id: poolKey,
|
|
215
|
+
providerName,
|
|
216
|
+
hostModel,
|
|
217
|
+
...(entry ? { rank: entry.rank } : {}),
|
|
218
|
+
hostConcurrencyLimit: hostLimit,
|
|
219
|
+
quotaStateEntry: quotaEntries[poolKey] ?? null,
|
|
220
|
+
discoveredLimits: entry
|
|
221
|
+
? { context_tokens: entry.context_tokens, output_tokens: entry.output_tokens }
|
|
222
|
+
: hostCapabilityLimits,
|
|
223
|
+
quotaSourceSnapshot,
|
|
224
|
+
};
|
|
225
|
+
}));
|
|
226
|
+
// A configured openai-compatible endpoint (NIM/vLLM/…) is a real, always-available
|
|
227
|
+
// API pool — surface it as a SECOND CapacityPool alongside the primary so the
|
|
228
|
+
// scheduler's proactive cross-pool spill (INV-QD-14, selectProvider) can route a
|
|
229
|
+
// node here when the primary pool is quota-degraded. Only when it isn't already
|
|
230
|
+
// the primary provider (no duplicate pool key). It's an independent API pool, so
|
|
231
|
+
// hostConcurrencyLimit is null (it doesn't draw on the host subagent budget) and
|
|
232
|
+
// it has no proactive quota source / capability handshake (discoveredLimits null;
|
|
233
|
+
// concurrency is governed by learned 429/RPM state).
|
|
234
|
+
if (providerName !== "openai-compatible" &&
|
|
235
|
+
hasConfiguredOpenAiCompatible(sessionConfig.openai_compatible)) {
|
|
236
|
+
const apiModel = sessionConfig.openai_compatible?.model ?? null;
|
|
237
|
+
const apiPoolKey = buildProviderModelKey("openai-compatible", apiModel);
|
|
238
|
+
const apiSnapshot = await quotaSource.queryCurrentUsage(apiPoolKey).catch(() => null);
|
|
239
|
+
primaryPools.push({
|
|
240
|
+
id: apiPoolKey,
|
|
241
|
+
providerName: "openai-compatible",
|
|
242
|
+
hostModel: apiModel,
|
|
243
|
+
hostConcurrencyLimit: null,
|
|
244
|
+
quotaStateEntry: quotaEntries[apiPoolKey] ?? null,
|
|
245
|
+
discoveredLimits: null,
|
|
246
|
+
quotaSourceSnapshot: apiSnapshot,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return primaryPools;
|
|
250
|
+
}
|
|
251
|
+
export function buildDispatchQuota(runId, phase, schedule, quotaStateEntry) {
|
|
252
|
+
let backoffState = null;
|
|
253
|
+
const count = quotaStateEntry?.consecutive_429_count ?? 0;
|
|
254
|
+
if (count > 0) {
|
|
255
|
+
backoffState = {
|
|
256
|
+
consecutive_429_count: count,
|
|
257
|
+
current_cooldown_ms: computeBackoffCooldownMs(count),
|
|
258
|
+
current_failure_weight: computeBackoffFailureWeight(count),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
contract_version: REMEDIATION_DISPATCH_QUOTA_CONTRACT_VERSION,
|
|
263
|
+
run_id: runId,
|
|
264
|
+
phase,
|
|
265
|
+
host_concurrency_limit: schedule.host_concurrency_limit,
|
|
266
|
+
max_concurrent_agents: schedule.max_concurrent,
|
|
267
|
+
estimated_wave_tokens: schedule.estimated_wave_tokens,
|
|
268
|
+
model: schedule.model,
|
|
269
|
+
confidence: schedule.confidence,
|
|
270
|
+
source: schedule.source,
|
|
271
|
+
resolved_limits: schedule.resolved_limits,
|
|
272
|
+
cooldown_until: schedule.cooldown_until,
|
|
273
|
+
binding_cap: schedule.binding_cap ?? "none",
|
|
274
|
+
capacity_pools: schedule.capacity_pools,
|
|
275
|
+
quota_source_snapshot: schedule.quota_source_snapshot ?? null,
|
|
276
|
+
backoff_state: backoffState,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
// ---------------------------------------------------------------------------
|
|
280
|
+
// Byte-based token estimation helpers
|
|
281
|
+
// ---------------------------------------------------------------------------
|
|
282
|
+
/** Fixed prompt overhead per dispatch slot (prompt instructions, JSON schema, etc.). */
|
|
283
|
+
const PROMPT_OVERHEAD_TOKENS = 2000;
|
|
284
|
+
/** Sum the byte sizes of a list of absolute or repo-relative file paths. */
|
|
285
|
+
function sumFileSizes(filePaths) {
|
|
286
|
+
let total = 0;
|
|
287
|
+
for (const p of filePaths) {
|
|
288
|
+
try {
|
|
289
|
+
total += statSync(p).size;
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// Missing file → 0 bytes; not an error for estimation purposes.
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return total;
|
|
296
|
+
}
|
|
297
|
+
/** Estimate slot tokens for an implement dispatch slot from readFiles byte sizes. */
|
|
298
|
+
function estimateImplementSlotTokens(readFiles, root) {
|
|
299
|
+
const absPaths = readFiles.map((f) => f.startsWith("/") || /^[A-Za-z]:[/\\]/.test(f) ? f : join(root, f));
|
|
300
|
+
const bytes = sumFileSizes(absPaths);
|
|
301
|
+
return estimateTokensFromBytes(bytes) + PROMPT_OVERHEAD_TOKENS;
|
|
302
|
+
}
|
|
303
|
+
// ---------------------------------------------------------------------------
|
|
304
|
+
// detectRepoConventions cache (one call per repo root per process)
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
/** Module-level cache: repo root → formatted conventions string. */
|
|
307
|
+
export const detectRepoConventionsCache = new Map();
|
|
308
|
+
function getCachedConventions(root) {
|
|
309
|
+
if (detectRepoConventionsCache.has(root)) {
|
|
310
|
+
return detectRepoConventionsCache.get(root);
|
|
311
|
+
}
|
|
312
|
+
const result = formatRepoConventions(detectRepoConventions(root));
|
|
313
|
+
detectRepoConventionsCache.set(root, result);
|
|
314
|
+
return result;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* The git top-level directory containing `cwd`, or `null` when `cwd` is not
|
|
318
|
+
* inside a git working tree (or git is unavailable). `git rev-parse
|
|
319
|
+
* --show-toplevel` emits a forward-slash absolute path on every platform.
|
|
320
|
+
*/
|
|
321
|
+
export function gitTopLevel(cwd) {
|
|
322
|
+
const result = spawnSync("git", ["rev-parse", "--show-toplevel"], {
|
|
323
|
+
cwd,
|
|
324
|
+
encoding: "utf8",
|
|
325
|
+
shell: false,
|
|
326
|
+
});
|
|
327
|
+
if (result.status !== 0)
|
|
328
|
+
return null;
|
|
329
|
+
const top = (result.stdout ?? "").trim();
|
|
330
|
+
return top.length > 0 ? top : null;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Canonical comparison key for a filesystem path. `realpathSync` resolves
|
|
334
|
+
* symlinks and platform short-names so it matches git's `--show-toplevel`
|
|
335
|
+
* output (macOS TMPDIR `/var`→`/private/var`, Windows 8.3 names); falls back to
|
|
336
|
+
* `resolve` for paths that don't exist on disk (e.g. mocked unit tests).
|
|
337
|
+
*/
|
|
338
|
+
function canonicalPathKey(p) {
|
|
339
|
+
try {
|
|
340
|
+
return normalizeRepoPath(realpathSync(p));
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
return normalizeRepoPath(resolve(p));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Create an isolated git worktree on a fresh branch at HEAD. Throws on non-zero exit.
|
|
348
|
+
*
|
|
349
|
+
* Refuses when `root` is not ITSELF a git top-level: a bare `git worktree add`
|
|
350
|
+
* with `cwd: root` walks UP to the nearest enclosing repo and silently creates
|
|
351
|
+
* the worktree/branch in that ancestor (observed polluting the monorepo with
|
|
352
|
+
* leaked `remediate-*` branches during the rolling_engine flip). The resolved
|
|
353
|
+
* top-level must equal the target root, or we refuse rather than escape.
|
|
354
|
+
*/
|
|
355
|
+
export function createWorktree(root, worktreePath, branchName) {
|
|
356
|
+
const top = gitTopLevel(root);
|
|
357
|
+
if (top === null) {
|
|
358
|
+
throw new Error(`Refusing to create a worktree: ${root} is not inside a git repository ` +
|
|
359
|
+
`(git rev-parse --show-toplevel failed). Rolling dispatch requires the target root to be a git repo.`);
|
|
360
|
+
}
|
|
361
|
+
if (canonicalPathKey(top) !== canonicalPathKey(root)) {
|
|
362
|
+
throw new Error(`Refusing to create a worktree: the git top-level for ${root} is ${top}, not the target root ` +
|
|
363
|
+
`itself, so 'git worktree add' would escape to an ancestor repo. Initialize a git repo at the ` +
|
|
364
|
+
`target root before rolling dispatch.`);
|
|
365
|
+
}
|
|
366
|
+
const result = spawnSync("git", ["worktree", "add", "-b", branchName, worktreePath, "HEAD"], { cwd: root, encoding: "utf8", shell: false });
|
|
367
|
+
if (result.status !== 0) {
|
|
368
|
+
const stderr = (result.stderr ?? "").trim();
|
|
369
|
+
const stdout = (result.stdout ?? "").trim();
|
|
370
|
+
throw new Error(`git worktree add failed (exit ${result.status ?? "unknown"}):\n${stderr || stdout}`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/** Remove a git worktree. Best-effort: logs but does not throw on failure. */
|
|
374
|
+
export function removeWorktree(root, worktreePath) {
|
|
375
|
+
const result = spawnSync("git", ["worktree", "remove", "--force", worktreePath], { cwd: root, encoding: "utf8", shell: false });
|
|
376
|
+
if (result.status !== 0) {
|
|
377
|
+
const stderr = (result.stderr ?? "").trim();
|
|
378
|
+
process.stderr.write(`[remediate-code] worktree remove failed (exit ${result.status ?? "unknown"}): ${stderr}\n`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Fully reset a node's isolated worktree + branch so a fresh `createWorktree -b`
|
|
383
|
+
* can run, even when a prior attempt left either behind. This is the idempotent
|
|
384
|
+
* cleanup the in-process driver needs across a `rate_limited` re-queue: the
|
|
385
|
+
* engine re-enters the dispatcher for the SAME block while its branch (and maybe
|
|
386
|
+
* a stale worktree admin entry) still exist, and `git worktree add -b <branch>`
|
|
387
|
+
* would otherwise fail with "branch already exists". Removing the worktree,
|
|
388
|
+
* pruning stale admin records, then force-deleting the branch makes every
|
|
389
|
+
* (re-)dispatch start clean from HEAD. All steps are best-effort (a missing
|
|
390
|
+
* worktree/branch is the expected first-attempt case, not an error). Any partial
|
|
391
|
+
* edits from a throttled prior attempt are intentionally discarded — the
|
|
392
|
+
* re-dispatch redoes the node from HEAD.
|
|
393
|
+
*/
|
|
394
|
+
export function resetNodeWorktreeAndBranch(root, worktreePath, branchName) {
|
|
395
|
+
removeWorktree(root, worktreePath);
|
|
396
|
+
// Prune stale worktree admin entries (e.g. a dir deleted out from under git),
|
|
397
|
+
// otherwise `git worktree add` can refuse a path it still thinks is registered.
|
|
398
|
+
spawnSync("git", ["worktree", "prune"], { cwd: root, shell: false });
|
|
399
|
+
// Force-delete the leftover branch from a prior attempt so `-b` recreates it.
|
|
400
|
+
spawnSync("git", ["branch", "-D", branchName], { cwd: root, shell: false });
|
|
401
|
+
}
|
|
402
|
+
/** Run each targeted command in the worktree directory. Returns pass/fail and combined output. */
|
|
403
|
+
export function verifyNodeInWorktree(worktreePath, targetedCommands) {
|
|
404
|
+
const outputs = [];
|
|
405
|
+
for (const cmd of targetedCommands) {
|
|
406
|
+
const [bin, ...args] = cmd.split(" ");
|
|
407
|
+
const r = spawnSync(bin, args, {
|
|
408
|
+
cwd: worktreePath,
|
|
409
|
+
encoding: "utf8",
|
|
410
|
+
shell: false,
|
|
411
|
+
});
|
|
412
|
+
const combined = [r.stdout ?? "", r.stderr ?? ""].filter(Boolean).join("\n");
|
|
413
|
+
outputs.push(`$ ${cmd}\n${combined}`);
|
|
414
|
+
if (r.status !== 0) {
|
|
415
|
+
return { passed: false, output: outputs.join("\n---\n") };
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return { passed: true, output: outputs.join("\n---\n") };
|
|
419
|
+
}
|
|
420
|
+
/** Merge the worktree branch into the current HEAD via cherry-pick. On failure, removes the worktree and returns the error. */
|
|
421
|
+
export function mergeWorktree(root, worktreePath, branchName) {
|
|
422
|
+
// Get the tip commit of the worktree branch
|
|
423
|
+
const revResult = spawnSync("git", ["rev-parse", branchName], {
|
|
424
|
+
cwd: root,
|
|
425
|
+
encoding: "utf8",
|
|
426
|
+
shell: false,
|
|
427
|
+
});
|
|
428
|
+
if (revResult.status !== 0) {
|
|
429
|
+
const errMsg = (revResult.stderr ?? "").trim();
|
|
430
|
+
removeWorktree(root, worktreePath);
|
|
431
|
+
return { success: false, error: `Failed to resolve worktree branch ${branchName}: ${errMsg}` };
|
|
432
|
+
}
|
|
433
|
+
const worktreeTip = revResult.stdout.trim();
|
|
434
|
+
const mergeResult = spawnSync("git", ["cherry-pick", worktreeTip], {
|
|
435
|
+
cwd: root,
|
|
436
|
+
encoding: "utf8",
|
|
437
|
+
shell: false,
|
|
438
|
+
});
|
|
439
|
+
if (mergeResult.status !== 0) {
|
|
440
|
+
const stderr = (mergeResult.stderr ?? "").trim();
|
|
441
|
+
// Abort the cherry-pick so the main tree stays clean
|
|
442
|
+
spawnSync("git", ["cherry-pick", "--abort"], { cwd: root, shell: false });
|
|
443
|
+
removeWorktree(root, worktreePath);
|
|
444
|
+
return { success: false, error: `cherry-pick failed: ${stderr}` };
|
|
445
|
+
}
|
|
446
|
+
removeWorktree(root, worktreePath);
|
|
447
|
+
return { success: true };
|
|
448
|
+
}
|
|
449
|
+
/** Worktree path for a remediation block. */
|
|
450
|
+
export function worktreePath(root, blockId, runId) {
|
|
451
|
+
return join(root, ".audit-tools", "worktrees", `remediate-${blockId}-${runId}`);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Stage and commit all of a worktree's edits onto its branch. The TOOL owns this
|
|
455
|
+
* commit (never the worker/host) so that the branch has a real commit for two
|
|
456
|
+
* downstream invariants: `gitEditedFilesForBranch` (the write-scope ground truth,
|
|
457
|
+
* `HEAD...<branch>`) and `mergeWorktree`'s cherry-pick both operate on the worker's
|
|
458
|
+
* changes rather than an empty diff against HEAD. Gitignored paths (node_modules,
|
|
459
|
+
* .audit-tools artifacts, the result file written to the main artifacts dir) are
|
|
460
|
+
* excluded by `git add -A` honoring .gitignore, so the commit captures exactly the
|
|
461
|
+
* source edits. Returns `committed:false` (not an error) when the worker made no
|
|
462
|
+
* tracked edits — there is then nothing to verify or merge.
|
|
463
|
+
*/
|
|
464
|
+
export function commitWorktree(worktreeRoot, message) {
|
|
465
|
+
const add = spawnSync("git", ["add", "-A"], {
|
|
466
|
+
cwd: worktreeRoot,
|
|
467
|
+
encoding: "utf8",
|
|
468
|
+
shell: false,
|
|
469
|
+
});
|
|
470
|
+
if (add.status !== 0) {
|
|
471
|
+
return { committed: false, error: `git add failed: ${(add.stderr ?? "").trim()}` };
|
|
472
|
+
}
|
|
473
|
+
// `git diff --cached --quiet` exits 0 when nothing is staged → no worker edits.
|
|
474
|
+
const staged = spawnSync("git", ["diff", "--cached", "--quiet"], {
|
|
475
|
+
cwd: worktreeRoot,
|
|
476
|
+
shell: false,
|
|
477
|
+
});
|
|
478
|
+
if (staged.status === 0) {
|
|
479
|
+
return { committed: false };
|
|
480
|
+
}
|
|
481
|
+
const commit = spawnSync("git", ["commit", "-m", message], {
|
|
482
|
+
cwd: worktreeRoot,
|
|
483
|
+
encoding: "utf8",
|
|
484
|
+
shell: false,
|
|
485
|
+
});
|
|
486
|
+
if (commit.status !== 0) {
|
|
487
|
+
return { committed: false, error: `git commit failed: ${(commit.stderr ?? "").trim()}` };
|
|
488
|
+
}
|
|
489
|
+
return { committed: true };
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Make the main checkout's installed `node_modules` available to a worktree. A
|
|
493
|
+
* fresh `git worktree add` checks out only tracked files, and `node_modules` is
|
|
494
|
+
* gitignored, so per-node verify commands (`npm run check`, focused tests) would
|
|
495
|
+
* otherwise fail with missing dependencies. Best-effort junction/symlink to the
|
|
496
|
+
* main root's `node_modules`; on failure it logs and the verify step surfaces the
|
|
497
|
+
* missing-deps error rather than crashing the dispatch. NOTE: workspace package
|
|
498
|
+
* symlinks inside `node_modules/@audit-tools/*` point back into the MAIN checkout,
|
|
499
|
+
* so cross-package runtime resolution sees the main tree — the authoritative
|
|
500
|
+
* cross-package re-check is the central post-merge build/gate, not this fast
|
|
501
|
+
* per-node verify (which gates obvious breakage early).
|
|
502
|
+
*/
|
|
503
|
+
export function ensureWorktreeNodeModules(mainRoot, worktreeRoot) {
|
|
504
|
+
const target = join(mainRoot, "node_modules");
|
|
505
|
+
const link = join(worktreeRoot, "node_modules");
|
|
506
|
+
if (!existsSync(target) || existsSync(link))
|
|
507
|
+
return;
|
|
508
|
+
try {
|
|
509
|
+
symlinkSync(target, link, "junction");
|
|
510
|
+
}
|
|
511
|
+
catch (err) {
|
|
512
|
+
process.stderr.write(`[remediate-code] worktree node_modules link failed (${worktreeRoot}): ${String(err)}\n`);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* The shared post-worker "accept node" lifecycle, extracted so BOTH rolling
|
|
517
|
+
* drivers reuse identical correctness: the in-process provider engine
|
|
518
|
+
* (`driveRollingImplementDispatch`) calls it inline once the worker returns; the
|
|
519
|
+
* host-subagent driver calls it from the `accept-node` callback once a host
|
|
520
|
+
* subagent finishes.
|
|
521
|
+
*
|
|
522
|
+
* Given a completed worker run in an isolated worktree, this: (1) TOOL-commits
|
|
523
|
+
* the worker's edits onto the branch (deterministic, never the worker/host) so
|
|
524
|
+
* the branch diff is the write-scope ground truth; (2) runs the per-node verify
|
|
525
|
+
* IN the worktree BEFORE accepting; (3) merges via cherry-pick only on a passing
|
|
526
|
+
* verify; and (4) drops the worktree on any failure so the main tree is never
|
|
527
|
+
* dirtied by an unverified change. It returns the LIFECYCLE outcome (which the
|
|
528
|
+
* caller records for the deterministic merge); the caller still returns the
|
|
529
|
+
* worker's TRANSPORT outcome to the rolling engine (so a `rate_limited` worker
|
|
530
|
+
* re-queues, while a verify-failure is adjudicated by the merge → triage).
|
|
531
|
+
*
|
|
532
|
+
* SAFETY: the main tree is touched only through `mergeWorktree` (cherry-pick of a
|
|
533
|
+
* verified branch, aborts cleanly on conflict). No state mutation here — the
|
|
534
|
+
* caller persists via `mergeImplementResults`.
|
|
535
|
+
*/
|
|
536
|
+
export function acceptNodeWorktree(params) {
|
|
537
|
+
const { root, runId, blockId, worktreeRoot: wt, branch, workerOutcome, targetedCommands } = params;
|
|
538
|
+
let verifyPassed = false;
|
|
539
|
+
let merged = false;
|
|
540
|
+
if (workerOutcome !== "success") {
|
|
541
|
+
// Worker failed / rate-limited: nothing to land; drop the worktree, preserve outcome.
|
|
542
|
+
removeWorktree(root, wt);
|
|
543
|
+
return { outcome: workerOutcome, verifyPassed, merged };
|
|
544
|
+
}
|
|
545
|
+
const commit = commitWorktree(wt, `remediate ${blockId} (${runId})`);
|
|
546
|
+
if (commit.error) {
|
|
547
|
+
// Could not commit the worker's edits → cannot safely land; drop it.
|
|
548
|
+
removeWorktree(root, wt);
|
|
549
|
+
return { outcome: "error", verifyPassed, merged };
|
|
550
|
+
}
|
|
551
|
+
if (!commit.committed) {
|
|
552
|
+
// Worker reported success but made no tracked edits — nothing to verify or merge.
|
|
553
|
+
// The deterministic merge adjudicates the result file (resolved_no_change needs evidence).
|
|
554
|
+
removeWorktree(root, wt);
|
|
555
|
+
return { outcome: "success", verifyPassed, merged };
|
|
556
|
+
}
|
|
557
|
+
const verify = targetedCommands.length > 0
|
|
558
|
+
? verifyNodeInWorktree(wt, targetedCommands)
|
|
559
|
+
: { passed: true, output: "" };
|
|
560
|
+
verifyPassed = verify.passed;
|
|
561
|
+
if (!verify.passed) {
|
|
562
|
+
// Verify failed: do not merge; drop the worktree so the main tree stays clean.
|
|
563
|
+
removeWorktree(root, wt);
|
|
564
|
+
return { outcome: "error", verifyPassed, merged };
|
|
565
|
+
}
|
|
566
|
+
// mergeWorktree cherry-picks the verified branch and removes the worktree (on
|
|
567
|
+
// success AND on conflict-abort), so no explicit cleanup is needed afterwards.
|
|
568
|
+
const mergeRes = mergeWorktree(root, wt, branch);
|
|
569
|
+
merged = mergeRes.success;
|
|
570
|
+
return { outcome: mergeRes.success ? "success" : "error", verifyPassed, merged };
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Sidecar path for a node's tool-owned accept (verify/merge) outcome. Written by
|
|
574
|
+
* BOTH rolling drivers as each node is accepted, read by `mergeImplementResults`.
|
|
575
|
+
* Block ids here follow the same filename-safe convention as the per-node result
|
|
576
|
+
* files in the same dir.
|
|
577
|
+
*/
|
|
578
|
+
export function nodeAcceptOutcomePath(artifactsDir, runId, blockId) {
|
|
579
|
+
return join(runDir(artifactsDir, runId, "implement"), `accept-outcome-${blockId}.json`);
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Persist a node's `acceptNodeWorktree` lifecycle outcome so finalization can tell
|
|
583
|
+
* a node whose edits actually LANDED (merged) from one that self-reported "resolved"
|
|
584
|
+
* but failed tool-owned verify / merge (OBL-DS-06: never trust the worker's self
|
|
585
|
+
* report). Both rolling drivers (host-subagent `advanceHostRolling` and in-process
|
|
586
|
+
* `driveRollingImplementDispatch`) call this; the interim main-tree path writes none,
|
|
587
|
+
* so the merge-state gate is inert there.
|
|
588
|
+
*/
|
|
589
|
+
export async function recordNodeAcceptOutcome(artifactsDir, runId, blockId, result) {
|
|
590
|
+
await writeJsonFile(nodeAcceptOutcomePath(artifactsDir, runId, blockId), {
|
|
591
|
+
schema_version: "remediate-code-implement/node-accept-outcome/v1alpha1",
|
|
592
|
+
block_id: blockId,
|
|
593
|
+
outcome: result.outcome,
|
|
594
|
+
verify_passed: result.verifyPassed,
|
|
595
|
+
merged: result.merged,
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
/** Load a node's recorded accept outcome, or null when none was written. */
|
|
599
|
+
export async function loadNodeAcceptOutcome(artifactsDir, runId, blockId) {
|
|
600
|
+
const raw = await readOptionalJsonFile(nodeAcceptOutcomePath(artifactsDir, runId, blockId));
|
|
601
|
+
if (!raw)
|
|
602
|
+
return null;
|
|
603
|
+
return { outcome: raw.outcome, verifyPassed: raw.verify_passed, merged: raw.merged };
|
|
604
|
+
}
|
|
605
|
+
/** Read the promoted DAG-node overlay fields off a Finding (all optional). */
|
|
606
|
+
function nodeFieldsOf(finding) {
|
|
607
|
+
return finding;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* The reconciliation expectations a node must honor (INV-DS-12): the explicit
|
|
611
|
+
* `reconciliation_expectations` when present, else the node's `preconditions`
|
|
612
|
+
* (upstream contracts' declared outputs). Returned as a deduped string list so
|
|
613
|
+
* the renderer can thread them and the disposition can record them.
|
|
614
|
+
*/
|
|
615
|
+
function reconciliationExpectationsOf(finding) {
|
|
616
|
+
const node = nodeFieldsOf(finding);
|
|
617
|
+
const explicit = Array.isArray(node.reconciliation_expectations)
|
|
618
|
+
? node.reconciliation_expectations
|
|
619
|
+
: [];
|
|
620
|
+
const preconditions = Array.isArray(node.preconditions) ? node.preconditions : [];
|
|
621
|
+
return [...new Set([...explicit, ...preconditions])].filter((s) => typeof s === "string" && s.trim().length > 0);
|
|
622
|
+
}
|
|
623
|
+
// ---------------------------------------------------------------------------
|
|
624
|
+
// Build-free per-node verification commands (residual CE-001)
|
|
625
|
+
// ---------------------------------------------------------------------------
|
|
626
|
+
/**
|
|
627
|
+
* The host manages the build centrally; a per-node verify command that runs
|
|
628
|
+
* `npm run build` (or a `npm test` whose package script prepends a build) races
|
|
629
|
+
* the central build's dist/ and is therefore forbidden. A command is build-free
|
|
630
|
+
* only when it neither builds nor invokes a build-prepending test script.
|
|
631
|
+
*
|
|
632
|
+
* Forbidden (return false):
|
|
633
|
+
* - `npm run build` / `npm run build -w ...` / `tsc` emit (`tsc -b`, `tsc --build`)
|
|
634
|
+
* - bare `npm test` / `npm t` / `npm run test` (the package script prepends build)
|
|
635
|
+
*
|
|
636
|
+
* Allowed (return true):
|
|
637
|
+
* - `npm run check` (no emit)
|
|
638
|
+
* - `npx vitest run <path>` / `vitest run <path>`
|
|
639
|
+
* - `node --test <path>`
|
|
640
|
+
*/
|
|
641
|
+
export function isBuildFreeVerifyCommand(cmd) {
|
|
642
|
+
const c = cmd.trim().toLowerCase().replace(/\s+/g, " ");
|
|
643
|
+
if (c.length === 0)
|
|
644
|
+
return false;
|
|
645
|
+
// Any explicit build step is forbidden.
|
|
646
|
+
if (/\bnpm\s+run\s+build\b/.test(c))
|
|
647
|
+
return false;
|
|
648
|
+
if (/\btsc\b.*(-b\b|--build\b)/.test(c))
|
|
649
|
+
return false;
|
|
650
|
+
if (/(^|\s)tsc(\s|$)/.test(c) && !/--noemit\b/.test(c)) {
|
|
651
|
+
// A bare `tsc` (or `tsc -p ...`) emits unless --noEmit is set.
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
// A build-prepending `npm test` / `npm t` / `npm run test` is forbidden; the
|
|
655
|
+
// build-free runner (vitest run / node --test) must be invoked directly.
|
|
656
|
+
if (/\bnpm\s+(test|t)\b/.test(c))
|
|
657
|
+
return false;
|
|
658
|
+
if (/\bnpm\s+run\s+test\b/.test(c))
|
|
659
|
+
return false;
|
|
660
|
+
return true;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Filter a node's `targeted_commands` to the build-free subset for the per-node
|
|
664
|
+
* verify section. Build-prepending or build commands are dropped (the host runs
|
|
665
|
+
* the build centrally) rather than emitted into the prompt.
|
|
666
|
+
*/
|
|
667
|
+
function buildFreeVerifyCommands(commands) {
|
|
668
|
+
if (!Array.isArray(commands))
|
|
669
|
+
return [];
|
|
670
|
+
return commands.filter((c) => typeof c === "string" && isBuildFreeVerifyCommand(c));
|
|
671
|
+
}
|
|
672
|
+
function markStarted(item) {
|
|
673
|
+
item.started_at ??= new Date().toISOString();
|
|
674
|
+
delete item.completed_at;
|
|
675
|
+
}
|
|
676
|
+
function markTerminal(item) {
|
|
677
|
+
const now = new Date().toISOString();
|
|
678
|
+
item.started_at ??= now;
|
|
679
|
+
item.completed_at = now;
|
|
680
|
+
}
|
|
681
|
+
async function tryLoadExistingImplementResult(resultPath) {
|
|
682
|
+
if (!existsSync(resultPath))
|
|
683
|
+
return undefined;
|
|
684
|
+
try {
|
|
685
|
+
const result = await readJsonFile(resultPath);
|
|
686
|
+
assertImplementWorkerResult(result, resultPath);
|
|
687
|
+
return result;
|
|
688
|
+
}
|
|
689
|
+
catch {
|
|
690
|
+
return undefined;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
function pendingOrDocumentedFindingIdsForBlock(block, state) {
|
|
694
|
+
return block.items.filter((findingId) => {
|
|
695
|
+
const item = state.items?.[findingId];
|
|
696
|
+
return item?.status === "pending" && !isTerminalStatus(item.status);
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
function implementResultCoversFindings(result, findingIds) {
|
|
700
|
+
const resultIds = new Set(result.item_results.map((item) => item.finding_id));
|
|
701
|
+
return findingIds.every((findingId) => resultIds.has(findingId));
|
|
702
|
+
}
|
|
703
|
+
async function archiveIncompleteImplementResult(resultPath) {
|
|
704
|
+
if (!existsSync(resultPath))
|
|
705
|
+
return;
|
|
706
|
+
const archivedPath = `${resultPath}.stale-${Date.now()}`;
|
|
707
|
+
await withFsRetry(() => rename(resultPath, archivedPath));
|
|
708
|
+
}
|
|
709
|
+
function runDir(artifactsDir, runId, phase) {
|
|
710
|
+
return join(artifactsDir, "runs", runId, phase);
|
|
711
|
+
}
|
|
712
|
+
function dispatchPlanPath(artifactsDir, runId, phase) {
|
|
713
|
+
return join(runDir(artifactsDir, runId, phase), "dispatch-plan.json");
|
|
714
|
+
}
|
|
715
|
+
const TEST_FILE_RE = /\.(test|spec)\.[cm]?[jt]sx?$/;
|
|
716
|
+
const WALK_SKIP_DIRS = new Set([
|
|
717
|
+
"node_modules", ".git", "dist", "build", "coverage", "out",
|
|
718
|
+
".next", ".turbo", ".audit-tools",
|
|
719
|
+
]);
|
|
720
|
+
/** Bounded recursive scan for test files under `root` (skips vendor/build dirs). */
|
|
721
|
+
function walkTestFiles(root, max = 400) {
|
|
722
|
+
const out = [];
|
|
723
|
+
const stack = [root];
|
|
724
|
+
let visited = 0;
|
|
725
|
+
while (stack.length > 0 && out.length < max) {
|
|
726
|
+
const dir = stack.pop();
|
|
727
|
+
let entries;
|
|
728
|
+
try {
|
|
729
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
730
|
+
}
|
|
731
|
+
catch {
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
for (const entry of entries) {
|
|
735
|
+
if (++visited > 20000)
|
|
736
|
+
return out;
|
|
737
|
+
if (entry.isDirectory()) {
|
|
738
|
+
if (WALK_SKIP_DIRS.has(entry.name) || entry.name.startsWith(".test-"))
|
|
739
|
+
continue;
|
|
740
|
+
stack.push(join(dir, entry.name));
|
|
741
|
+
}
|
|
742
|
+
else if (TEST_FILE_RE.test(entry.name)) {
|
|
743
|
+
out.push(join(dir, entry.name));
|
|
744
|
+
if (out.length >= max)
|
|
745
|
+
break;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return out;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Walk the repo ONCE and read every test file's content (bounded). Built once per
|
|
753
|
+
* dispatch and shared across all blocks so the filesystem walk + reads are not
|
|
754
|
+
* repeated per block.
|
|
755
|
+
*/
|
|
756
|
+
export function buildTestFileIndex(root) {
|
|
757
|
+
const index = [];
|
|
758
|
+
for (const testPath of walkTestFiles(root)) {
|
|
759
|
+
let content;
|
|
760
|
+
try {
|
|
761
|
+
content = readFileSync(testPath, "utf8");
|
|
762
|
+
}
|
|
763
|
+
catch {
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
index.push({ rel: relative(root, testPath).replace(/\\/g, "/"), content });
|
|
767
|
+
}
|
|
768
|
+
return index;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Collect test files from `index` that reference any of `sourceFiles` by
|
|
772
|
+
* module basename. When `packageRoot` is supplied (repo-relative prefix, e.g.
|
|
773
|
+
* `packages/foo`), only test files under that package are considered —
|
|
774
|
+
* otherwise all test files in the index are matched (existing behavior).
|
|
775
|
+
*/
|
|
776
|
+
export function collectReferencingTests(index, sourceFiles, packageRoot) {
|
|
777
|
+
if (sourceFiles.length === 0 || index.length === 0)
|
|
778
|
+
return [];
|
|
779
|
+
const basenames = sourceFiles
|
|
780
|
+
.map((f) => (f.split(/[/\\]/).pop() ?? f).replace(/\.[cm]?[jt]sx?$/, ""))
|
|
781
|
+
.filter((b) => b.length > 1);
|
|
782
|
+
if (basenames.length === 0)
|
|
783
|
+
return [];
|
|
784
|
+
const needles = basenames.map((b) => new RegExp(`\\b${b.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`));
|
|
785
|
+
const sourceSet = new Set(sourceFiles.map((f) => f.replace(/\\/g, "/")));
|
|
786
|
+
// Normalize packageRoot to forward slashes and ensure it ends without trailing slash
|
|
787
|
+
const pkgPrefix = packageRoot
|
|
788
|
+
? packageRoot.replace(/\\/g, "/").replace(/\/$/, "") + "/"
|
|
789
|
+
: null;
|
|
790
|
+
const result = [];
|
|
791
|
+
for (const { rel, content } of index) {
|
|
792
|
+
if (sourceSet.has(rel))
|
|
793
|
+
continue;
|
|
794
|
+
// If a package scope is set, skip files outside that package
|
|
795
|
+
if (pkgPrefix && !rel.startsWith(pkgPrefix))
|
|
796
|
+
continue;
|
|
797
|
+
if (needles.some((re) => re.test(content)))
|
|
798
|
+
result.push(rel);
|
|
799
|
+
}
|
|
800
|
+
return result;
|
|
801
|
+
}
|
|
802
|
+
function uniquePaths(paths) {
|
|
803
|
+
return [...new Set(paths)];
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Detect the nearest ancestor directory containing a `package.json` for the
|
|
807
|
+
* first source file in `sourceFiles` (walk up, stop at `root`). Returns the
|
|
808
|
+
* repo-relative path prefix (e.g. `packages/foo`) or undefined if none found.
|
|
809
|
+
*/
|
|
810
|
+
function detectPackageRoot(sourceFiles, root) {
|
|
811
|
+
if (sourceFiles.length === 0)
|
|
812
|
+
return undefined;
|
|
813
|
+
const first = sourceFiles[0];
|
|
814
|
+
// Resolve to absolute path relative to root if not already absolute
|
|
815
|
+
const absFirst = first.startsWith("/") || /^[A-Za-z]:[/\\]/.test(first)
|
|
816
|
+
? first
|
|
817
|
+
: join(root, first);
|
|
818
|
+
let dir = dirname(absFirst);
|
|
819
|
+
while (dir !== root && dir.length > root.length) {
|
|
820
|
+
if (existsSync(join(dir, "package.json"))) {
|
|
821
|
+
return relative(root, dir).replace(/\\/g, "/");
|
|
822
|
+
}
|
|
823
|
+
const parent = dirname(dir);
|
|
824
|
+
if (parent === dir)
|
|
825
|
+
break;
|
|
826
|
+
dir = parent;
|
|
827
|
+
}
|
|
828
|
+
return undefined;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* The files an implement worker should receive as context for a finding:
|
|
832
|
+
* pre-document affected_files PLUS any files the document phase declared in the
|
|
833
|
+
* item_spec's `touched_files`.
|
|
834
|
+
*/
|
|
835
|
+
function itemReadFiles(finding, spec) {
|
|
836
|
+
const files = finding.affected_files.map((f) => f.path);
|
|
837
|
+
if (spec?.touched_files)
|
|
838
|
+
files.push(...spec.touched_files);
|
|
839
|
+
return uniquePaths(files);
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* The files an implement worker is expected to write. The documented
|
|
843
|
+
* `touched_files` set is authoritative when present; affected_files are only a
|
|
844
|
+
* fallback for older or incomplete document results.
|
|
845
|
+
*/
|
|
846
|
+
function itemWriteFiles(finding, spec) {
|
|
847
|
+
if (Array.isArray(spec?.touched_files)) {
|
|
848
|
+
return uniquePaths(spec.touched_files);
|
|
849
|
+
}
|
|
850
|
+
return uniquePaths(finding.affected_files.map((f) => f.path));
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Repo-relative paths every finding in a block needs for context, deduped.
|
|
854
|
+
*/
|
|
855
|
+
function blockReadFiles(block, state) {
|
|
856
|
+
const files = block.items.flatMap((findingId) => {
|
|
857
|
+
const finding = state.plan?.findings.find((f) => f.id === findingId);
|
|
858
|
+
if (!finding)
|
|
859
|
+
return [];
|
|
860
|
+
return itemReadFiles(finding, state.items?.[findingId]?.item_spec);
|
|
861
|
+
});
|
|
862
|
+
return uniquePaths(files);
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Repo-relative paths every finding in a block may write, deduped. This is kept
|
|
866
|
+
* narrower than read context so a broad affected hub file does not serialize
|
|
867
|
+
* blocks whose documented write sets are actually disjoint.
|
|
868
|
+
*/
|
|
869
|
+
function blockWriteFiles(block, state) {
|
|
870
|
+
const files = block.items.flatMap((findingId) => {
|
|
871
|
+
const finding = state.plan?.findings.find((f) => f.id === findingId);
|
|
872
|
+
if (!finding)
|
|
873
|
+
return [];
|
|
874
|
+
return itemWriteFiles(finding, state.items?.[findingId]?.item_spec);
|
|
875
|
+
});
|
|
876
|
+
return uniquePaths(files);
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Construct the DispatchPlanItem for an implement task. Single source of truth
|
|
880
|
+
* so prepareImplementDispatch and mergeImplementResults stay in lockstep on item
|
|
881
|
+
* shape.
|
|
882
|
+
*/
|
|
883
|
+
function buildImplementDispatchItem(block, state, dir) {
|
|
884
|
+
const taskId = `implement-${block.block_id}`;
|
|
885
|
+
const readFiles = blockReadFiles(block, state);
|
|
886
|
+
const writeFiles = blockWriteFiles(block, state);
|
|
887
|
+
const resultPath = join(dir, `${taskId}.result.json`);
|
|
888
|
+
return {
|
|
889
|
+
task_id: taskId,
|
|
890
|
+
block_id: block.block_id,
|
|
891
|
+
prompt_path: join(dir, `${taskId}.md`),
|
|
892
|
+
result_path: resultPath,
|
|
893
|
+
model_hint: buildImplementModelHint(block, state),
|
|
894
|
+
access: {
|
|
895
|
+
read_paths: readFiles,
|
|
896
|
+
write_paths: [...writeFiles, resultPath],
|
|
897
|
+
},
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
export function buildImplementModelHint(block, state) {
|
|
901
|
+
// Prefer the node's own promoted `model_tier` (derived from contract-pipeline
|
|
902
|
+
// complexity signals) over a re-derived block heuristic. In the contract
|
|
903
|
+
// pipeline a block maps 1:1 to a DAG node, so the block's single finding
|
|
904
|
+
// carries the authoritative relative rank. Never collapse to a flat
|
|
905
|
+
// "standard" when the node declared a tier.
|
|
906
|
+
const nodeTiers = block.items
|
|
907
|
+
.map((findingId) => {
|
|
908
|
+
const finding = state.plan?.findings.find((f) => f.id === findingId);
|
|
909
|
+
return finding ? nodeFieldsOf(finding).model_tier : undefined;
|
|
910
|
+
})
|
|
911
|
+
.filter((t) => t !== undefined);
|
|
912
|
+
if (nodeTiers.length > 0) {
|
|
913
|
+
// Take the most-capable declared rank across the block's nodes so a deep
|
|
914
|
+
// node is never under-provisioned by a sibling's smaller rank. Ordering is
|
|
915
|
+
// the single shared tier-rank authority (`mostCapableTier`).
|
|
916
|
+
const tier = mostCapableTier(nodeTiers) ?? "standard";
|
|
917
|
+
return { tier, reasons: ["node_model_tier"] };
|
|
918
|
+
}
|
|
919
|
+
const deepReasons = [];
|
|
920
|
+
let allSafe = true;
|
|
921
|
+
let maxSeverityRank = 0;
|
|
922
|
+
for (const findingId of block.items) {
|
|
923
|
+
const item = state.items?.[findingId];
|
|
924
|
+
const finding = state.plan?.findings.find((f) => f.id === findingId);
|
|
925
|
+
if (!finding)
|
|
926
|
+
continue;
|
|
927
|
+
const rank = severityRank(finding.severity);
|
|
928
|
+
if (rank > maxSeverityRank)
|
|
929
|
+
maxSeverityRank = rank;
|
|
930
|
+
if (item?.item_spec) {
|
|
931
|
+
const { tier } = classifyFindingRisk(finding, item.item_spec);
|
|
932
|
+
if (tier === "context_dependent") {
|
|
933
|
+
deepReasons.push(`context_dependent_${findingId}`);
|
|
934
|
+
}
|
|
935
|
+
if (tier !== "safe") {
|
|
936
|
+
allSafe = false;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
else {
|
|
940
|
+
allSafe = false;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
if (maxSeverityRank >= 5) {
|
|
944
|
+
deepReasons.push("critical_severity");
|
|
945
|
+
}
|
|
946
|
+
if (block.items.length >= 5) {
|
|
947
|
+
deepReasons.push("large_block");
|
|
948
|
+
}
|
|
949
|
+
if (deepReasons.length > 0) {
|
|
950
|
+
return { tier: "deep", reasons: deepReasons };
|
|
951
|
+
}
|
|
952
|
+
if (allSafe && block.items.length === 1 && maxSeverityRank <= 2) {
|
|
953
|
+
return { tier: "small", reasons: ["all_safe_single_finding"] };
|
|
954
|
+
}
|
|
955
|
+
return { tier: "standard", reasons: ["default_implement_block"] };
|
|
956
|
+
}
|
|
957
|
+
function contractPipelineTraceLines(finding) {
|
|
958
|
+
const lines = [];
|
|
959
|
+
if (finding.contract_goal_id) {
|
|
960
|
+
lines.push(`Contract goal: ${finding.contract_goal_id}`);
|
|
961
|
+
}
|
|
962
|
+
if (finding.contract_obligation_ids?.length) {
|
|
963
|
+
lines.push(`Satisfies obligations: ${finding.contract_obligation_ids.join(", ")}`);
|
|
964
|
+
}
|
|
965
|
+
if (finding.verification_obligation_ids?.length) {
|
|
966
|
+
lines.push(`Verification obligations: ${finding.verification_obligation_ids.join(", ")}`);
|
|
967
|
+
}
|
|
968
|
+
if (finding.targeted_commands?.length) {
|
|
969
|
+
// Provenance only: the DAG's recorded targeted commands. This is the
|
|
970
|
+
// "Contract Pipeline Traceability" section (what the node's contract said),
|
|
971
|
+
// NOT a runnable directive. The runnable per-node verify commands the
|
|
972
|
+
// renderer emits are the build-free subset in `perNodeVerificationSection`
|
|
973
|
+
// (residual CE-001 is enforced there, where the worker is told to RUN them).
|
|
974
|
+
lines.push(`Targeted commands: ${finding.targeted_commands.join(" | ")}`);
|
|
975
|
+
}
|
|
976
|
+
return lines;
|
|
977
|
+
}
|
|
978
|
+
function contractPipelineTraceBullets(finding) {
|
|
979
|
+
const lines = contractPipelineTraceLines(finding);
|
|
980
|
+
if (lines.length === 0)
|
|
981
|
+
return "";
|
|
982
|
+
return `\n## Contract Pipeline Traceability\n\n${lines.map((line) => `- ${line}`).join("\n")}\n`;
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* G1 + INV-GND-02: a finding that the auditor's grounding pass marked ungrounded
|
|
986
|
+
* — or that carries NO grounding verdict (undefined → treated as ungrounded) —
|
|
987
|
+
* has not been positively re-verified against the cited code. Instruct the
|
|
988
|
+
* worker to VERIFY the claim against the source first and only then fix it (or
|
|
989
|
+
* resolve_no_change if the claim does not hold), rather than blindly applying a
|
|
990
|
+
* fix to a possibly-stale/hallucinated finding. A positively-grounded finding
|
|
991
|
+
* adds no bullet (it was already re-verified at ingest).
|
|
992
|
+
*/
|
|
993
|
+
function groundingVerificationBullet(finding) {
|
|
994
|
+
if (!findingNeedsVerificationBeforeFix(finding))
|
|
995
|
+
return "";
|
|
996
|
+
const reason = finding.grounding?.reason
|
|
997
|
+
? ` (${finding.grounding.reason})`
|
|
998
|
+
: " (no grounding verdict was recorded for this finding)";
|
|
999
|
+
return `- VERIFY BEFORE FIX: this finding is not positively grounded${reason}. Confirm the claim against the cited code first; if it holds, fix it, otherwise mark the item \`resolved_no_change\` with evidence. Do not apply a fix to an unverified claim.`;
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Opt-in meta-audit reflection invitation (parity with audit-code's worker
|
|
1003
|
+
* prompt). Rendered after the file-access section because it carves out one
|
|
1004
|
+
* extra append-only path. Shape: the shared `AgentReflectionSchema`;
|
|
1005
|
+
* the close phase aggregates the file into the report's "Process Feedback"
|
|
1006
|
+
* section. Best-effort by design — it must never compete with the obligation.
|
|
1007
|
+
*/
|
|
1008
|
+
function reflectionInvitation(feedbackDisplay, taskId, lens) {
|
|
1009
|
+
return `
|
|
1010
|
+
## Optional process feedback
|
|
1011
|
+
|
|
1012
|
+
Never let this delay or replace the required output above: if you hit task
|
|
1013
|
+
ambiguity, tool friction, or unclear instructions, you MAY append one JSON
|
|
1014
|
+
reflection line to \`${feedbackDisplay}\` with shape:
|
|
1015
|
+
{"task_id": "${taskId}"${lens ? `, "lens": "${lens}"` : ""}, "instruction_clarity": "clear|mostly_clear|ambiguous|unclear",
|
|
1016
|
+
"ambiguities": ["..."], "tool_friction": ["..."], "suggestions": ["..."],
|
|
1017
|
+
"severity": "info|low|medium|high"}
|
|
1018
|
+
One object per line; never overwrite existing lines. Appending to this file is
|
|
1019
|
+
allowed in addition to the file access above.
|
|
1020
|
+
`;
|
|
1021
|
+
}
|
|
1022
|
+
// ---------------------------------------------------------------------------
|
|
1023
|
+
// Infra-modifying block detection
|
|
1024
|
+
// ---------------------------------------------------------------------------
|
|
1025
|
+
/**
|
|
1026
|
+
* Canonical set of infra files whose modification can break the live dispatcher
|
|
1027
|
+
* while the run is in progress. Paths are repo-relative forward-slash strings.
|
|
1028
|
+
*/
|
|
1029
|
+
const INFRA_FILE_PATHS = new Set([
|
|
1030
|
+
"packages/remediate-code/src/steps/nextStep.ts",
|
|
1031
|
+
"packages/remediate-code/src/steps/dispatch.ts",
|
|
1032
|
+
"packages/remediate-code/src/state/store.ts",
|
|
1033
|
+
"packages/remediate-code/src/steps/contractPipeline.ts",
|
|
1034
|
+
"packages/remediate-code/src/steps/waveScheduler.ts",
|
|
1035
|
+
"packages/remediate-code/src/steps/stepWriter.ts",
|
|
1036
|
+
]);
|
|
1037
|
+
/**
|
|
1038
|
+
* Returns true when any path in `writePaths` matches the set of infra files
|
|
1039
|
+
* (normalised to repo-relative forward-slash strings). Used to gate the
|
|
1040
|
+
* live-surface verification section in the implement prompt.
|
|
1041
|
+
*/
|
|
1042
|
+
export function isInfraModifyingBlock(writePaths) {
|
|
1043
|
+
for (const p of writePaths) {
|
|
1044
|
+
const normalized = p.replace(/\\/g, "/");
|
|
1045
|
+
if (INFRA_FILE_PATHS.has(normalized))
|
|
1046
|
+
return true;
|
|
1047
|
+
// Also match if the path ends with the infra file's relative segment,
|
|
1048
|
+
// e.g. an absolute path like /abs/root/packages/remediate-code/src/steps/dispatch.ts
|
|
1049
|
+
for (const infraPath of INFRA_FILE_PATHS) {
|
|
1050
|
+
if (normalized.endsWith("/" + infraPath))
|
|
1051
|
+
return true;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
return false;
|
|
1055
|
+
}
|
|
1056
|
+
function infraModifyingSection(repoRoot) {
|
|
1057
|
+
const rootDisplay = toPromptPathToken(repoRoot);
|
|
1058
|
+
return `
|
|
1059
|
+
## Infra-modifying block
|
|
1060
|
+
|
|
1061
|
+
This block modifies the dispatch/orchestration engine that the current run
|
|
1062
|
+
executes. **The host builds the package centrally — do NOT run \`npm run build\`
|
|
1063
|
+
or \`npm test\` here** (a worker-side build races the central build's \`dist/\`).
|
|
1064
|
+
Verify build-free only and let the host re-exercise the live surface after its
|
|
1065
|
+
central build:
|
|
1066
|
+
|
|
1067
|
+
1. **Type-check (no emit):** After completing all edits, run:
|
|
1068
|
+
\`\`\`
|
|
1069
|
+
npm run check
|
|
1070
|
+
\`\`\`
|
|
1071
|
+
from \`${rootDisplay}\`. If type-check fails, mark the item blocked and record
|
|
1072
|
+
the failure in \`failure_reason\`.
|
|
1073
|
+
|
|
1074
|
+
2. **Targeted build-free tests:** Run this package's build-free test runner
|
|
1075
|
+
directly against the tests for your change — for remediate-code:
|
|
1076
|
+
\`\`\`
|
|
1077
|
+
npx vitest run <your-test-file>
|
|
1078
|
+
\`\`\`
|
|
1079
|
+
from \`${rootDisplay}\`. Never invoke \`npm test\`/\`npm run build\`: those
|
|
1080
|
+
prepend a build. If a targeted test fails, mark the item blocked and record
|
|
1081
|
+
the failure in \`failure_reason\`.
|
|
1082
|
+
|
|
1083
|
+
3. **Rollback is the host's job.** Because you do not build or republish the
|
|
1084
|
+
engine, you cannot brick the live dispatcher mid-run. The host owns the
|
|
1085
|
+
central build and any dist rollback; record the files you changed in your
|
|
1086
|
+
result evidence so the host can attribute a post-build failure.
|
|
1087
|
+
`;
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Per-item bullets threading what upstream/neighbor nodes agreed to provide
|
|
1091
|
+
* (INV-DS-12): the node's reconciliation_expectations / preconditions and its
|
|
1092
|
+
* expected_changes. Rendered inside each item so a dependent node implements
|
|
1093
|
+
* against the realized upstream surface rather than guessing.
|
|
1094
|
+
*/
|
|
1095
|
+
function upstreamExpectationsBullets(finding) {
|
|
1096
|
+
const node = nodeFieldsOf(finding);
|
|
1097
|
+
const expectations = reconciliationExpectationsOf(finding);
|
|
1098
|
+
const lines = [];
|
|
1099
|
+
if (expectations.length > 0) {
|
|
1100
|
+
lines.push(`- Upstream/neighbor contract provides (implement against these, do not redefine them): ${expectations.join("; ")}`);
|
|
1101
|
+
}
|
|
1102
|
+
if (typeof node.expected_changes === "string" && node.expected_changes.trim().length > 0) {
|
|
1103
|
+
lines.push(`- Expected changes: ${node.expected_changes.trim()}`);
|
|
1104
|
+
}
|
|
1105
|
+
if (Array.isArray(node.verification) && node.verification.length > 0) {
|
|
1106
|
+
lines.push(`- Verification checks: ${node.verification.join("; ")}`);
|
|
1107
|
+
}
|
|
1108
|
+
return lines.join("\n");
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* The build-free per-node verification section. Emits the node's own build-free
|
|
1112
|
+
* targeted commands (build/build-prepending commands filtered out — residual
|
|
1113
|
+
* CE-001) plus the standard build-free baseline (`npm run check` + the package's
|
|
1114
|
+
* build-free test runner). NON-EMITTING: it instructs the worker to run these to
|
|
1115
|
+
* gate its own result, never to emit further dispatch.
|
|
1116
|
+
*/
|
|
1117
|
+
function perNodeVerificationSection(block, state, rootDisplay) {
|
|
1118
|
+
const nodeCommands = uniquePaths(block.items.flatMap((findingId) => {
|
|
1119
|
+
const finding = state.plan?.findings.find((f) => f.id === findingId);
|
|
1120
|
+
return finding ? buildFreeVerifyCommands(finding.targeted_commands) : [];
|
|
1121
|
+
}));
|
|
1122
|
+
const commandBlock = nodeCommands.length > 0
|
|
1123
|
+
? `Run these node-targeted, build-free commands and record each command + result in the affected item's evidence:
|
|
1124
|
+
\`\`\`
|
|
1125
|
+
${nodeCommands.join("\n")}
|
|
1126
|
+
\`\`\`
|
|
1127
|
+
`
|
|
1128
|
+
: "";
|
|
1129
|
+
return `
|
|
1130
|
+
## Per-node verification (build-free)
|
|
1131
|
+
|
|
1132
|
+
The host builds the package centrally; do NOT run \`npm run build\` or \`npm test\`
|
|
1133
|
+
(either races the central build's \`dist/\`). Verify build-free only, from
|
|
1134
|
+
\`${rootDisplay}\`:
|
|
1135
|
+
|
|
1136
|
+
- Type-check with \`npm run check\` (no emit).
|
|
1137
|
+
- Run the package's build-free test runner directly against your change
|
|
1138
|
+
(remediate-code: \`npx vitest run <your-test-file>\`; node-test packages:
|
|
1139
|
+
\`node --test <your-test-file>\`).
|
|
1140
|
+
|
|
1141
|
+
${commandBlock}A node is verified-complete only when its declared outputs exist and these
|
|
1142
|
+
build-free checks pass; otherwise mark the item blocked with the failure in
|
|
1143
|
+
\`failure_reason\`.
|
|
1144
|
+
`;
|
|
1145
|
+
}
|
|
1146
|
+
function implementPrompt(block, state, resultPath, conventions, repoRoot, feedbackDisplay, worktreeRoot) {
|
|
1147
|
+
const items = block.items.flatMap((findingId) => {
|
|
1148
|
+
const item = state.items?.[findingId];
|
|
1149
|
+
const finding = state.plan?.findings.find((entry) => entry.id === findingId);
|
|
1150
|
+
if (!finding)
|
|
1151
|
+
return [];
|
|
1152
|
+
// Only render items that still need implementing — never a resolved item
|
|
1153
|
+
// from a prior wave or one the user skipped (deemed_inappropriate/ignored).
|
|
1154
|
+
if (!item || isTerminalStatus(item.status))
|
|
1155
|
+
return [];
|
|
1156
|
+
if (item.status !== "pending")
|
|
1157
|
+
return [];
|
|
1158
|
+
// item_spec may be pre-populated from the plan DAG node or absent;
|
|
1159
|
+
// either way the implementer receives finding context directly.
|
|
1160
|
+
return [{ finding, spec: item.item_spec }];
|
|
1161
|
+
});
|
|
1162
|
+
// When a worktreeRoot is supplied, the worker operates in the worktree, not
|
|
1163
|
+
// the main repo root. Source file paths are prefixed with the worktree root.
|
|
1164
|
+
// The result path always lives in the artifacts dir (outside the worktree).
|
|
1165
|
+
const effectiveRoot = worktreeRoot ?? repoRoot;
|
|
1166
|
+
// Normalize to forward slashes for host-facing prompt text; bash-like shells
|
|
1167
|
+
// on Windows treat backslashes as escape characters.
|
|
1168
|
+
const rootDisplay = toPromptPathToken(effectiveRoot);
|
|
1169
|
+
const resultDisplay = toPromptPathToken(resultPath);
|
|
1170
|
+
// Prefix each source file path with the worktree root when applicable.
|
|
1171
|
+
function resolveFilePath(rel) {
|
|
1172
|
+
if (!worktreeRoot)
|
|
1173
|
+
return rel;
|
|
1174
|
+
if (rel.startsWith("/") || /^[A-Za-z]:[/\\]/.test(rel))
|
|
1175
|
+
return rel;
|
|
1176
|
+
return toPromptPathToken(join(worktreeRoot, rel));
|
|
1177
|
+
}
|
|
1178
|
+
const worktreeNote = worktreeRoot
|
|
1179
|
+
? `\nYou are working in a worktree at ${toPromptPathToken(worktreeRoot)}; all file edits go here. Do not edit files outside this worktree.\n`
|
|
1180
|
+
: "";
|
|
1181
|
+
return `
|
|
1182
|
+
# Implement Remediation Block
|
|
1183
|
+
|
|
1184
|
+
You are implementing one bounded remediation block. Edit the files needed for the
|
|
1185
|
+
findings in this prompt, and you MAY create new files (e.g. a test file or an
|
|
1186
|
+
extracted module) within the SAME package as those files when a finding's change
|
|
1187
|
+
calls for it. Do not edit unrelated files in other packages, and do not change
|
|
1188
|
+
remediation state files directly.
|
|
1189
|
+
Repository root: ${rootDisplay}
|
|
1190
|
+
Set the shell/tool workdir to the repository root when running commands; do not rely on cwd state from prior shell calls.
|
|
1191
|
+
|
|
1192
|
+
## Block
|
|
1193
|
+
|
|
1194
|
+
- Block ID: ${block.block_id}
|
|
1195
|
+
- Findings: ${items.map(({ finding }) => finding.id).join(", ")}
|
|
1196
|
+
|
|
1197
|
+
## Items
|
|
1198
|
+
|
|
1199
|
+
${items
|
|
1200
|
+
.map(({ finding, spec }) => `
|
|
1201
|
+
### ${finding.id} - ${finding.title}
|
|
1202
|
+
|
|
1203
|
+
- Files: ${itemReadFiles(finding, spec).map(resolveFilePath).join(", ")}
|
|
1204
|
+
- Summary: ${finding.summary}
|
|
1205
|
+
${groundingVerificationBullet(finding)}
|
|
1206
|
+
${spec ? `- Concrete change: ${spec.concrete_change}
|
|
1207
|
+
- Tests to write: ${spec.tests_to_write
|
|
1208
|
+
.map((test) => `${test.name}: ${test.assertions.join("; ")}`)
|
|
1209
|
+
.join(" | ")}` : ""}
|
|
1210
|
+
${upstreamExpectationsBullets(finding)}
|
|
1211
|
+
${contractPipelineTraceBullets(finding)}
|
|
1212
|
+
`)
|
|
1213
|
+
.join("\n")}
|
|
1214
|
+
${conventions ? `\n${conventions}\n` : ""}${perNodeVerificationSection(block, state, rootDisplay)}${isInfraModifyingBlock(blockWriteFiles(block, state)) ? infraModifyingSection(repoRoot) : ""}
|
|
1215
|
+
## Verification
|
|
1216
|
+
${worktreeNote}
|
|
1217
|
+
Run changed or newly created tests by name when possible, and record the focused
|
|
1218
|
+
command and result in the affected item's evidence. If a broad or full-suite
|
|
1219
|
+
command fails in a dirty worktree and appears unrelated or pre-existing, record
|
|
1220
|
+
that broad failure separately instead of using it as the only verdict for this
|
|
1221
|
+
block. If a focused test for this block fails, the affected item remains blocked.
|
|
1222
|
+
If targeted commands are listed under an item, run them when applicable and
|
|
1223
|
+
include each command and result in that item's evidence.
|
|
1224
|
+
|
|
1225
|
+
Windows PowerShell: do not pipe an inline foreach statement directly into ConvertTo-Json.
|
|
1226
|
+
Assign the foreach output to a variable first, then pipe that variable to ConvertTo-Json.
|
|
1227
|
+
|
|
1228
|
+
## Output
|
|
1229
|
+
|
|
1230
|
+
After editing and verifying the block, write JSON to exactly:
|
|
1231
|
+
|
|
1232
|
+
\`${resultDisplay}\`
|
|
1233
|
+
|
|
1234
|
+
Emit **exactly one \`item_results\` entry per node id below — no more, no fewer**.
|
|
1235
|
+
Each entry's \`finding_id\` MUST be one of the exact ids: ${items
|
|
1236
|
+
.map(({ finding }) => `\`${finding.id}\``)
|
|
1237
|
+
.join(", ")}. Do not substitute a title, an obligation id, or a block id for
|
|
1238
|
+
the node id, and do not emit duplicate entries for the same node.
|
|
1239
|
+
|
|
1240
|
+
\`\`\`json
|
|
1241
|
+
{
|
|
1242
|
+
"contract_version": "${REMEDIATION_WORKER_RESULT_CONTRACT_VERSION}",
|
|
1243
|
+
"phase": "implement",
|
|
1244
|
+
"item_results": [
|
|
1245
|
+
${items
|
|
1246
|
+
.map(({ finding }) => ` {
|
|
1247
|
+
"finding_id": "${finding.id}",
|
|
1248
|
+
"status": "resolved",
|
|
1249
|
+
"evidence": ["test or verification evidence"]
|
|
1250
|
+
}`)
|
|
1251
|
+
.join(",\n")}
|
|
1252
|
+
]
|
|
1253
|
+
}
|
|
1254
|
+
\`\`\`
|
|
1255
|
+
|
|
1256
|
+
For an item you cannot safely finish, set \`status\` to \`blocked\` and include
|
|
1257
|
+
\`failure_reason\`. Stop after writing the result JSON.
|
|
1258
|
+
|
|
1259
|
+
## File access
|
|
1260
|
+
|
|
1261
|
+
Read: ${uniquePaths(items.flatMap(({ finding, spec }) => itemReadFiles(finding, spec))).join(", ")}
|
|
1262
|
+
Write: ${uniquePaths(items.flatMap(({ finding, spec }) => itemWriteFiles(finding, spec))).join(", ")}
|
|
1263
|
+
You may also create new files within the same package as those files (e.g. tests
|
|
1264
|
+
or extracted modules) when a finding requires it.
|
|
1265
|
+
If your change renames, moves, or removes a symbol, also update the existing test
|
|
1266
|
+
files that reference it — fixing tests for a changed surface is part of this
|
|
1267
|
+
block, not a later cleanup. Test files that reference these files are included in
|
|
1268
|
+
your write access.
|
|
1269
|
+
Write result: ${resultDisplay}
|
|
1270
|
+
Do not modify unrelated files outside these paths or files in other packages.
|
|
1271
|
+
${reflectionInvitation(feedbackDisplay, block.block_id)}`;
|
|
1272
|
+
}
|
|
1273
|
+
async function loadStateOrThrow(artifactsDir) {
|
|
1274
|
+
const state = await new StateStore(artifactsDir).loadState();
|
|
1275
|
+
if (!state) {
|
|
1276
|
+
throw new Error(`No remediation state found at ${join(artifactsDir, "state.json")}.`);
|
|
1277
|
+
}
|
|
1278
|
+
return state;
|
|
1279
|
+
}
|
|
1280
|
+
export async function prepareImplementDispatch(options, runId, onlyBlockId, waveOptions) {
|
|
1281
|
+
const state = await loadStateOrThrow(options.artifactsDir);
|
|
1282
|
+
if (!state.plan || !state.items) {
|
|
1283
|
+
throw new Error("Cannot prepare implement dispatch without plan and items.");
|
|
1284
|
+
}
|
|
1285
|
+
const dir = runDir(options.artifactsDir, runId, "implement");
|
|
1286
|
+
await mkdir(dir, { recursive: true });
|
|
1287
|
+
// Use the module-level cache so repeated calls within the same process do not
|
|
1288
|
+
// re-scan the filesystem for repo conventions.
|
|
1289
|
+
const conventions = getCachedConventions(options.root);
|
|
1290
|
+
const seenBlockIds = new Set();
|
|
1291
|
+
const candidateBlocks = state.plan.blocks.filter((block) => {
|
|
1292
|
+
if (onlyBlockId && block.block_id !== onlyBlockId)
|
|
1293
|
+
return false;
|
|
1294
|
+
if (seenBlockIds.has(block.block_id))
|
|
1295
|
+
return false;
|
|
1296
|
+
// Rolling eligibility (INV-RS-01): a dependent node is dispatched only once
|
|
1297
|
+
// every prerequisite reached a VERIFIED-COMPLETE disposition
|
|
1298
|
+
// (resolved / resolved_no_change). A skipped or blocked prerequisite never
|
|
1299
|
+
// satisfies the edge, so the dependent is held back rather than racing the
|
|
1300
|
+
// main tree against an upstream surface that never landed.
|
|
1301
|
+
if (!dependencyVerifiedComplete(block, state))
|
|
1302
|
+
return false;
|
|
1303
|
+
const hasWork = block.items.some((findingId) => {
|
|
1304
|
+
const item = state.items?.[findingId];
|
|
1305
|
+
return item?.status === "pending";
|
|
1306
|
+
});
|
|
1307
|
+
if (hasWork) {
|
|
1308
|
+
seenBlockIds.add(block.block_id);
|
|
1309
|
+
return true;
|
|
1310
|
+
}
|
|
1311
|
+
return false;
|
|
1312
|
+
});
|
|
1313
|
+
// Walk the repo for test files ONCE per dispatch (not once per block) and cache
|
|
1314
|
+
// their contents; collectReferencingTests then matches in memory.
|
|
1315
|
+
const testIndex = buildTestFileIndex(options.root);
|
|
1316
|
+
const items = [];
|
|
1317
|
+
const itemReadFileLists = [];
|
|
1318
|
+
let reconciledCount = 0;
|
|
1319
|
+
for (const block of candidateBlocks) {
|
|
1320
|
+
const item = buildImplementDispatchItem(block, state, dir);
|
|
1321
|
+
const readFiles = blockReadFiles(block, state);
|
|
1322
|
+
// Detect the package root from this block's source files: walk up from the
|
|
1323
|
+
// first source file to the nearest ancestor with a package.json (stop at root).
|
|
1324
|
+
const packageRoot = detectPackageRoot(readFiles, options.root);
|
|
1325
|
+
// Pull test files that reference this block's source into its access, so the
|
|
1326
|
+
// worker that changes or removes a symbol also fixes the tests that assert it
|
|
1327
|
+
// (otherwise their breakage is orphaned for a separate central mop-up).
|
|
1328
|
+
// Scoped to the block's package to avoid pulling in unrelated package tests.
|
|
1329
|
+
const referencingTests = collectReferencingTests(testIndex, readFiles, packageRoot);
|
|
1330
|
+
if (referencingTests.length > 0 && item.access) {
|
|
1331
|
+
item.access.read_paths = [
|
|
1332
|
+
...new Set([...item.access.read_paths, ...referencingTests]),
|
|
1333
|
+
];
|
|
1334
|
+
item.access.write_paths = [
|
|
1335
|
+
...new Set([...item.access.write_paths, ...referencingTests]),
|
|
1336
|
+
];
|
|
1337
|
+
}
|
|
1338
|
+
// Reconcile an already-produced result regardless of wave packing.
|
|
1339
|
+
const pendingFindingIds = pendingOrDocumentedFindingIdsForBlock(block, state);
|
|
1340
|
+
const existingResult = await tryLoadExistingImplementResult(item.result_path);
|
|
1341
|
+
if (existingResult) {
|
|
1342
|
+
if (implementResultCoversFindings(existingResult, pendingFindingIds)) {
|
|
1343
|
+
reconciledCount++;
|
|
1344
|
+
continue;
|
|
1345
|
+
}
|
|
1346
|
+
process.stderr.write(`[remediate-code] dispatch: existing implement result for block ${block.block_id} ` +
|
|
1347
|
+
`does not cover ${pendingFindingIds.length} still-pending item(s); re-dispatching\n`);
|
|
1348
|
+
await archiveIncompleteImplementResult(item.result_path);
|
|
1349
|
+
}
|
|
1350
|
+
// No wave-time file-conflict deferral heuristic: parallel blocks with
|
|
1351
|
+
// overlapping files are both dispatched. Parallel safety comes from the planner
|
|
1352
|
+
// (mergeBlocksSharingFiles) and rolling verified-complete dependency ordering
|
|
1353
|
+
// (dependencyVerifiedComplete). Workers operate in isolated worktrees;
|
|
1354
|
+
// verification prevents bad merges from dirtying the main tree.
|
|
1355
|
+
await writeTextFile(item.prompt_path, implementPrompt(block, state, item.result_path, conventions, options.root, toPromptPathToken(join(options.artifactsDir, AGENT_FEEDBACK_FILENAME)), waveOptions?.worktreeRootedPrompts
|
|
1356
|
+
? worktreePath(options.root, block.block_id, runId)
|
|
1357
|
+
: undefined));
|
|
1358
|
+
items.push(item);
|
|
1359
|
+
itemReadFileLists.push([...readFiles, ...referencingTests]);
|
|
1360
|
+
}
|
|
1361
|
+
if (reconciledCount > 0) {
|
|
1362
|
+
console.log(`Reconciliation: reused ${reconciledCount} existing implement results.`);
|
|
1363
|
+
}
|
|
1364
|
+
const plan = {
|
|
1365
|
+
contract_version: REMEDIATION_DISPATCH_PLAN_CONTRACT_VERSION,
|
|
1366
|
+
phase: "implement",
|
|
1367
|
+
run_id: runId,
|
|
1368
|
+
// Normalize to forward slashes so hosts running bash-like shells on Windows
|
|
1369
|
+
// receive paths that survive shell expansion (backslash is an escape char).
|
|
1370
|
+
repo_root: toPromptPathToken(options.root),
|
|
1371
|
+
artifacts_dir: toPromptPathToken(options.artifactsDir),
|
|
1372
|
+
items,
|
|
1373
|
+
};
|
|
1374
|
+
await writeJsonFile(dispatchPlanPath(options.artifactsDir, runId, "implement"), plan);
|
|
1375
|
+
const schedule = await scheduleWave({
|
|
1376
|
+
hostMaxConcurrent: waveOptions?.hostMaxConcurrent,
|
|
1377
|
+
sessionConfig: waveOptions?.sessionConfig ?? null,
|
|
1378
|
+
hostContextTokens: waveOptions?.hostContextTokens,
|
|
1379
|
+
hostOutputTokens: waveOptions?.hostOutputTokens,
|
|
1380
|
+
hostModels: waveOptions?.hostModels,
|
|
1381
|
+
hostModelId: waveOptions?.hostModelId,
|
|
1382
|
+
itemCount: items.length,
|
|
1383
|
+
estimatedSlotTokens: itemReadFileLists.map((files) => estimateImplementSlotTokens(files, options.root)),
|
|
1384
|
+
});
|
|
1385
|
+
process.stderr.write(`[remediate-code] dispatch: implement max_concurrent=${schedule.max_concurrent} of ${items.length} item(s) ` +
|
|
1386
|
+
`source=${schedule.source} cap=${schedule.binding_cap ?? "none"}\n`);
|
|
1387
|
+
const quota = buildDispatchQuota(runId, "implement", schedule);
|
|
1388
|
+
await writeJsonFile(join(dir, "dispatch-quota.json"), quota);
|
|
1389
|
+
return plan;
|
|
1390
|
+
}
|
|
1391
|
+
function assertImplementWorkerResult(value, path) {
|
|
1392
|
+
const issues = validateImplementWorkerResult(value, path).filter((i) => i.severity === "error");
|
|
1393
|
+
if (issues.length > 0) {
|
|
1394
|
+
throw new Error(formatValidationIssues(issues));
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
/** True when `root` is inside a git work tree (the git tool is present and it's a repo). */
|
|
1398
|
+
function isGitWorkTree(root) {
|
|
1399
|
+
const probe = spawnSync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: root, encoding: "utf8", shell: false });
|
|
1400
|
+
return !probe.error && probe.status === 0 && /true/.test(probe.stdout ?? "");
|
|
1401
|
+
}
|
|
1402
|
+
/** True when `branch` resolves to a commit in the repo at `root`. */
|
|
1403
|
+
function gitBranchExists(root, branch) {
|
|
1404
|
+
const probe = spawnSync("git", ["rev-parse", "--verify", "--quiet", `${branch}^{commit}`], { cwd: root, encoding: "utf8", shell: false });
|
|
1405
|
+
return !probe.error && probe.status === 0;
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* The set of repo-relative paths the worker ACTUALLY edited, read from git
|
|
1409
|
+
* (tracked modifications + staged + untracked-not-ignored). This is the ground
|
|
1410
|
+
* truth for write-scope enforcement; the worker's self-reported `amended_files`
|
|
1411
|
+
* is advisory only and is never trusted for the scope gate.
|
|
1412
|
+
*
|
|
1413
|
+
* Fail-closed: when `root` IS a git repo but a probe errors, returns
|
|
1414
|
+
* `{ available: false, reason: "probe_failed" }` so the caller blocks rather than
|
|
1415
|
+
* silently trusting an unverifiable edit set. When `root` is not a git repo at
|
|
1416
|
+
* all (no worktree workflow, no diff ground truth), returns
|
|
1417
|
+
* `{ available: false, reason: "not_a_repo" }` so the caller skips the gate.
|
|
1418
|
+
*/
|
|
1419
|
+
export function gitEditedFiles(root) {
|
|
1420
|
+
if (!isGitWorkTree(root)) {
|
|
1421
|
+
return { available: false, reason: "not_a_repo", error: "root is not a git work tree" };
|
|
1422
|
+
}
|
|
1423
|
+
// `git diff --name-only HEAD` covers tracked working-tree + staged changes
|
|
1424
|
+
// against the last commit; `ls-files --others --exclude-standard` adds new
|
|
1425
|
+
// untracked files that aren't gitignored.
|
|
1426
|
+
const diff = spawnSync("git", ["diff", "--name-only", "HEAD"], { cwd: root, encoding: "utf8", shell: false });
|
|
1427
|
+
if (diff.error || typeof diff.status !== "number" || diff.status !== 0) {
|
|
1428
|
+
const detail = (diff.stderr ?? diff.error?.message ?? "git diff failed").toString().trim();
|
|
1429
|
+
return { available: false, reason: "probe_failed", error: detail };
|
|
1430
|
+
}
|
|
1431
|
+
const others = spawnSync("git", ["ls-files", "--others", "--exclude-standard"], { cwd: root, encoding: "utf8", shell: false });
|
|
1432
|
+
if (others.error || typeof others.status !== "number" || others.status !== 0) {
|
|
1433
|
+
const detail = (others.stderr ?? others.error?.message ?? "git ls-files failed").toString().trim();
|
|
1434
|
+
return { available: false, reason: "probe_failed", error: detail };
|
|
1435
|
+
}
|
|
1436
|
+
const files = new Set();
|
|
1437
|
+
for (const line of `${diff.stdout}\n${others.stdout}`.split(/\r?\n/)) {
|
|
1438
|
+
const p = line.trim();
|
|
1439
|
+
if (p.length > 0)
|
|
1440
|
+
files.add(p.replace(/\\/g, "/"));
|
|
1441
|
+
}
|
|
1442
|
+
return { available: true, files };
|
|
1443
|
+
}
|
|
1444
|
+
/** Normalize a declared path (absolute, repo-relative, or back-slashed) to a repo-relative forward-slash string. */
|
|
1445
|
+
function toRepoRelative(p, root) {
|
|
1446
|
+
const normalizedRoot = root.replace(/\\/g, "/").replace(/\/$/, "");
|
|
1447
|
+
let s = p.replace(/\\/g, "/");
|
|
1448
|
+
if (s.startsWith(normalizedRoot + "/")) {
|
|
1449
|
+
s = s.slice(normalizedRoot.length + 1);
|
|
1450
|
+
}
|
|
1451
|
+
return s;
|
|
1452
|
+
}
|
|
1453
|
+
/**
|
|
1454
|
+
* Files the worker edited (from git) that fall OUTSIDE the block's declared
|
|
1455
|
+
* write scope. Result-file artifacts and the agent-feedback file are excluded
|
|
1456
|
+
* (they are sanctioned side outputs, never source edits). Returns the offending
|
|
1457
|
+
* repo-relative paths (empty when the edits are fully within scope).
|
|
1458
|
+
*/
|
|
1459
|
+
export function writeScopeViolations(declaredWritePaths, editedFiles, root) {
|
|
1460
|
+
const declared = new Set(declaredWritePaths.map((p) => toRepoRelative(p, root)));
|
|
1461
|
+
const violations = [];
|
|
1462
|
+
for (const edited of editedFiles) {
|
|
1463
|
+
const rel = toRepoRelative(edited, root);
|
|
1464
|
+
if (declared.has(rel))
|
|
1465
|
+
continue;
|
|
1466
|
+
// Sanctioned non-source outputs: result JSON files and the reflection file.
|
|
1467
|
+
if (rel.endsWith(".result.json"))
|
|
1468
|
+
continue;
|
|
1469
|
+
if (rel.endsWith(AGENT_FEEDBACK_FILENAME))
|
|
1470
|
+
continue;
|
|
1471
|
+
violations.push(rel);
|
|
1472
|
+
}
|
|
1473
|
+
return violations;
|
|
1474
|
+
}
|
|
1475
|
+
/** Branch name a block's isolated worktree is created on (mirrors `worktreePath`). */
|
|
1476
|
+
export function worktreeBranchForBlock(blockId, runId) {
|
|
1477
|
+
return `remediate-${blockId}-${runId}`;
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
* The files a worker's worktree branch changed relative to HEAD — the ground
|
|
1481
|
+
* truth for write-scope enforcement. Diffs `HEAD...<branch>` (the branch's own
|
|
1482
|
+
* commits). Fail-closed / not-a-repo semantics mirror `gitEditedFiles`.
|
|
1483
|
+
*/
|
|
1484
|
+
export function gitEditedFilesForBranch(root, branch) {
|
|
1485
|
+
if (!isGitWorkTree(root)) {
|
|
1486
|
+
return { available: false, reason: "not_a_repo", error: "root is not a git work tree" };
|
|
1487
|
+
}
|
|
1488
|
+
const diff = spawnSync("git", ["diff", "--name-only", `HEAD...${branch}`], { cwd: root, encoding: "utf8", shell: false });
|
|
1489
|
+
if (diff.error || typeof diff.status !== "number" || diff.status !== 0) {
|
|
1490
|
+
const detail = (diff.stderr ?? diff.error?.message ?? "git diff failed").toString().trim();
|
|
1491
|
+
return { available: false, reason: "probe_failed", error: detail };
|
|
1492
|
+
}
|
|
1493
|
+
const files = new Set();
|
|
1494
|
+
for (const line of (diff.stdout ?? "").split(/\r?\n/)) {
|
|
1495
|
+
const p = line.trim();
|
|
1496
|
+
if (p.length > 0)
|
|
1497
|
+
files.add(p.replace(/\\/g, "/"));
|
|
1498
|
+
}
|
|
1499
|
+
return { available: true, files };
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Pure write-scope gate decision (OBL-DS-06). Given the block's declared write
|
|
1503
|
+
* paths and the resolved git edit set:
|
|
1504
|
+
* - `not_a_repo` → no ground truth (no worktree workflow) → not blocked.
|
|
1505
|
+
* - `probe_failed` → git is a repo but the diff failed → FAIL CLOSED (blocked).
|
|
1506
|
+
* - available → block iff any edited file is outside declared scope.
|
|
1507
|
+
* The worker's self-reported `amended_files` is never an input here.
|
|
1508
|
+
*/
|
|
1509
|
+
export function enforceWriteScope(declaredWritePaths, edited, root) {
|
|
1510
|
+
if (!edited.available) {
|
|
1511
|
+
if (edited.reason === "not_a_repo") {
|
|
1512
|
+
return { blocked: false };
|
|
1513
|
+
}
|
|
1514
|
+
// probe_failed: git is present but could not be queried → fail closed.
|
|
1515
|
+
return {
|
|
1516
|
+
blocked: true,
|
|
1517
|
+
reason: `Write-scope could not be verified: git probe failed (${edited.error}). ` +
|
|
1518
|
+
`Failing closed rather than trusting self-reported edits.`,
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
const violations = writeScopeViolations(declaredWritePaths, edited.files, root);
|
|
1522
|
+
if (violations.length === 0)
|
|
1523
|
+
return { blocked: false };
|
|
1524
|
+
return {
|
|
1525
|
+
blocked: true,
|
|
1526
|
+
reason: `Worker edited files outside its declared write scope: ${violations.join(", ")}. ` +
|
|
1527
|
+
`Declared scope must be amended through the seam protocol; the self-reported ` +
|
|
1528
|
+
`amended_files set is not trusted for this gate.`,
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
1531
|
+
// ---------------------------------------------------------------------------
|
|
1532
|
+
// Merge-seam: obligation-id → node remap + multi-entry collapse (tolerance)
|
|
1533
|
+
// ---------------------------------------------------------------------------
|
|
1534
|
+
/**
|
|
1535
|
+
* Build the map from a known obligation/node alias to the finding id that owns
|
|
1536
|
+
* it, for one block. A worker that mislabels its `finding_id` as an obligation
|
|
1537
|
+
* id it was assigned (or a CP-BLOCK-prefixed/unprefixed node alias) is remapped
|
|
1538
|
+
* to the owning node's finding rather than dropped as an orphan — the tolerant
|
|
1539
|
+
* seam (the host is a variable of any strength). The map only ever points at
|
|
1540
|
+
* findings that belong to THIS block, so a mislabel can never resolve to an
|
|
1541
|
+
* unrelated node.
|
|
1542
|
+
*/
|
|
1543
|
+
export function buildBlockAliasMap(block, state) {
|
|
1544
|
+
const aliasToFinding = new Map();
|
|
1545
|
+
for (const findingId of block.items) {
|
|
1546
|
+
const finding = state.plan?.findings.find((f) => f.id === findingId);
|
|
1547
|
+
if (!finding)
|
|
1548
|
+
continue;
|
|
1549
|
+
// The node id itself, and its block-prefixed / unprefixed aliases.
|
|
1550
|
+
const register = (alias) => {
|
|
1551
|
+
if (!alias || alias === findingId)
|
|
1552
|
+
return;
|
|
1553
|
+
if (!aliasToFinding.has(alias))
|
|
1554
|
+
aliasToFinding.set(alias, findingId);
|
|
1555
|
+
};
|
|
1556
|
+
// CP-BLOCK- aliases are now resolved deterministically by the id registry in
|
|
1557
|
+
// `collapseItemResults` (S4); registering them here is defence-in-depth only.
|
|
1558
|
+
register(toBlockId(findingId));
|
|
1559
|
+
register(block.block_id);
|
|
1560
|
+
// The obligation ids the node satisfies/verifies — a worker may report one.
|
|
1561
|
+
for (const obl of [
|
|
1562
|
+
...(finding.contract_obligation_ids ?? []),
|
|
1563
|
+
...(finding.verification_obligation_ids ?? []),
|
|
1564
|
+
]) {
|
|
1565
|
+
register(obl);
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
return aliasToFinding;
|
|
1569
|
+
}
|
|
1570
|
+
/**
|
|
1571
|
+
* Collapse a worker result's `item_results` to one entry per resolved finding
|
|
1572
|
+
* id, applying the block alias map first (obligation/node-alias → finding). When
|
|
1573
|
+
* several entries collapse onto the same finding, a single `blocked` entry wins
|
|
1574
|
+
* over `resolved` (a node is not complete if any reported facet failed), and the
|
|
1575
|
+
* union of evidence / first failure_reason is preserved. Entries whose id is
|
|
1576
|
+
* neither a known finding nor a known alias are returned in `unresolved` so the
|
|
1577
|
+
* caller can record them as orphans.
|
|
1578
|
+
*/
|
|
1579
|
+
export function collapseItemResults(itemResults, aliasMap, knownFindingIds) {
|
|
1580
|
+
const byFinding = new Map();
|
|
1581
|
+
const unresolved = [];
|
|
1582
|
+
for (const entry of itemResults) {
|
|
1583
|
+
let targetId = entry.finding_id;
|
|
1584
|
+
if (!knownFindingIds.has(targetId)) {
|
|
1585
|
+
// Registry-authoritative (S4): a CP-BLOCK- block id maps deterministically
|
|
1586
|
+
// to its bare node id via the id registry, so the common "worker reported
|
|
1587
|
+
// the block id" mislabel resolves here without the tolerant alias remap —
|
|
1588
|
+
// the remap is defence-in-depth for non-block aliases (e.g. a mislabelled
|
|
1589
|
+
// obligation id) only.
|
|
1590
|
+
const nodeId = fromBlockId(targetId);
|
|
1591
|
+
if (nodeId && knownFindingIds.has(nodeId)) {
|
|
1592
|
+
targetId = nodeId;
|
|
1593
|
+
}
|
|
1594
|
+
else {
|
|
1595
|
+
const remapped = aliasMap.get(targetId);
|
|
1596
|
+
if (remapped) {
|
|
1597
|
+
targetId = remapped;
|
|
1598
|
+
}
|
|
1599
|
+
else {
|
|
1600
|
+
unresolved.push(entry);
|
|
1601
|
+
continue;
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
const normalized = { ...entry, finding_id: targetId };
|
|
1606
|
+
const existing = byFinding.get(targetId);
|
|
1607
|
+
if (!existing) {
|
|
1608
|
+
byFinding.set(targetId, normalized);
|
|
1609
|
+
continue;
|
|
1610
|
+
}
|
|
1611
|
+
// Collapse: blocked dominates; merge evidence; keep first failure_reason.
|
|
1612
|
+
const mergedEvidence = [
|
|
1613
|
+
...new Set([...(existing.evidence ?? []), ...(normalized.evidence ?? [])]),
|
|
1614
|
+
];
|
|
1615
|
+
const status = existing.status === "blocked" || normalized.status === "blocked"
|
|
1616
|
+
? "blocked"
|
|
1617
|
+
: "resolved";
|
|
1618
|
+
byFinding.set(targetId, {
|
|
1619
|
+
finding_id: targetId,
|
|
1620
|
+
status,
|
|
1621
|
+
evidence: mergedEvidence.length > 0 ? mergedEvidence : undefined,
|
|
1622
|
+
failure_reason: existing.failure_reason ?? normalized.failure_reason,
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
return { collapsed: [...byFinding.values()], unresolved };
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
* Build the per-node disposition for a block (INV-DS-15). A SKIP disposition
|
|
1629
|
+
* (user-skipped: `ignored` / `deemed_inappropriate`) is NEVER reported as
|
|
1630
|
+
* `verified_complete`. Each block maps 1:1 to a node, so the disposition keys on
|
|
1631
|
+
* the block's first finding (the node id).
|
|
1632
|
+
*/
|
|
1633
|
+
export function buildNodeDisposition(block, state) {
|
|
1634
|
+
const nodeId = block.items[0] ?? block.block_id;
|
|
1635
|
+
const finding = state.plan?.findings.find((f) => f.id === nodeId);
|
|
1636
|
+
// Resolve the block's overall status from its items.
|
|
1637
|
+
const statuses = block.items.map((id) => state.items?.[id]?.status ?? "pending");
|
|
1638
|
+
const isSkip = statuses.some((s) => isSkipStatus(s));
|
|
1639
|
+
const allResolved = statuses.length > 0 && statuses.every((s) => isVerifiedCompleteStatus(s));
|
|
1640
|
+
const anyBlocked = statuses.some((s) => s === "blocked");
|
|
1641
|
+
let disposition;
|
|
1642
|
+
if (isSkip) {
|
|
1643
|
+
// INV-DS-15: a skipped node is never verified_complete.
|
|
1644
|
+
disposition = "skipped";
|
|
1645
|
+
}
|
|
1646
|
+
else if (anyBlocked) {
|
|
1647
|
+
disposition = "blocked";
|
|
1648
|
+
}
|
|
1649
|
+
else if (allResolved) {
|
|
1650
|
+
disposition = "verified_complete";
|
|
1651
|
+
}
|
|
1652
|
+
else {
|
|
1653
|
+
disposition = "missing_result";
|
|
1654
|
+
}
|
|
1655
|
+
const reason = block.items
|
|
1656
|
+
.map((id) => state.items?.[id]?.failure_reason)
|
|
1657
|
+
.find((r) => typeof r === "string" && r.length > 0);
|
|
1658
|
+
return {
|
|
1659
|
+
node_id: nodeId,
|
|
1660
|
+
block_id: block.block_id,
|
|
1661
|
+
disposition,
|
|
1662
|
+
finding_status: statuses.join(","),
|
|
1663
|
+
reconciliation_expectations: finding ? reconciliationExpectationsOf(finding) : [],
|
|
1664
|
+
reason,
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
/**
|
|
1668
|
+
* Attribute a post-merge sibling-block failure (INV-DS-14). Given the repo-
|
|
1669
|
+
* relative paths implicated by a red sibling and the merged blocks' declared
|
|
1670
|
+
* write scopes, return the exactly-one block whose scope contains an implicated
|
|
1671
|
+
* file (attributable → route THAT sibling to triage). When zero or more than one
|
|
1672
|
+
* merged block could own the failure, the red is unattributable and is deferred
|
|
1673
|
+
* to the rolling-scheduler's coarse backstop (return null).
|
|
1674
|
+
*/
|
|
1675
|
+
export function attributeSiblingRed(implicatedFiles, mergedBlockScopes, root) {
|
|
1676
|
+
const implicated = new Set(implicatedFiles.map((p) => toRepoRelative(p, root)));
|
|
1677
|
+
const owners = new Set();
|
|
1678
|
+
for (const { block_id, write_paths } of mergedBlockScopes) {
|
|
1679
|
+
for (const wp of write_paths) {
|
|
1680
|
+
if (implicated.has(toRepoRelative(wp, root))) {
|
|
1681
|
+
owners.add(block_id);
|
|
1682
|
+
break;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
// Attributable only when a single merged block owns the implicated surface.
|
|
1687
|
+
return owners.size === 1 ? [...owners][0] : null;
|
|
1688
|
+
}
|
|
1689
|
+
/**
|
|
1690
|
+
* Detect lost-update hazards across concurrently-merged blocks (ARC-f378135d-2 /
|
|
1691
|
+
* ARC-c1693139). When the rolling engine dispatches multiple nodes in flight and
|
|
1692
|
+
* each worker edits in its own worktree, two workers can both modify the SAME
|
|
1693
|
+
* file; cherry-picking both branches silently drops one worker's change to that
|
|
1694
|
+
* file (lost update). This pure function returns every repo-relative path that
|
|
1695
|
+
* appears in more than one merged block's ACTUAL edit set, with the owning block
|
|
1696
|
+
* ids. The caller routes the involved blocks to triage so the conflict is
|
|
1697
|
+
* reconciled rather than silently losing an edit. Result-file artifacts and the
|
|
1698
|
+
* agent-feedback file are sanctioned side outputs and are never counted as
|
|
1699
|
+
* overlaps.
|
|
1700
|
+
*/
|
|
1701
|
+
export function detectOverlappingEdits(editedByBlock) {
|
|
1702
|
+
const pathToBlocks = new Map();
|
|
1703
|
+
for (const { block_id, files } of editedByBlock) {
|
|
1704
|
+
for (const file of files) {
|
|
1705
|
+
const rel = file.replace(/\\/g, "/");
|
|
1706
|
+
// Sanctioned non-source outputs never constitute a lost-update conflict.
|
|
1707
|
+
if (rel.endsWith(".result.json"))
|
|
1708
|
+
continue;
|
|
1709
|
+
if (rel.endsWith(AGENT_FEEDBACK_FILENAME))
|
|
1710
|
+
continue;
|
|
1711
|
+
let owners = pathToBlocks.get(rel);
|
|
1712
|
+
if (!owners) {
|
|
1713
|
+
owners = new Set();
|
|
1714
|
+
pathToBlocks.set(rel, owners);
|
|
1715
|
+
}
|
|
1716
|
+
owners.add(block_id);
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
const overlaps = [];
|
|
1720
|
+
for (const [path, owners] of pathToBlocks) {
|
|
1721
|
+
if (owners.size > 1) {
|
|
1722
|
+
overlaps.push({ path, block_ids: [...owners].sort() });
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
// Deterministic ordering so the diagnostic + tests are stable.
|
|
1726
|
+
return overlaps.sort((a, b) => a.path.localeCompare(b.path));
|
|
1727
|
+
}
|
|
1728
|
+
export async function mergeImplementResults(options, runId) {
|
|
1729
|
+
const plan = await readJsonFile(dispatchPlanPath(options.artifactsDir, runId, "implement"));
|
|
1730
|
+
if (plan.contract_version !== REMEDIATION_DISPATCH_PLAN_CONTRACT_VERSION ||
|
|
1731
|
+
plan.phase !== "implement") {
|
|
1732
|
+
throw new Error("Implement dispatch plan has an unsupported contract.");
|
|
1733
|
+
}
|
|
1734
|
+
const store = new StateStore(options.artifactsDir);
|
|
1735
|
+
// OBL-INV-RSD-02 / OBL-SEAM-RSD-04: the entire read-modify-write of state.json
|
|
1736
|
+
// is performed under a single held lock via StateStore.mutate, and committed
|
|
1737
|
+
// exactly once after the full item loop. No partial state.json write happens
|
|
1738
|
+
// mid-loop — a malformed/unknown finding_id no longer leaves a half-applied
|
|
1739
|
+
// state (and never throws past the loop; see OBL-INV-RSD-01 below). Evidence
|
|
1740
|
+
// artifacts (result_<id>_verify_code_against_documentation.json, the orphan
|
|
1741
|
+
// diagnostic) are separate sidecar files, not state.json, so writing them
|
|
1742
|
+
// inside the loop does not violate the single-state-commit invariant.
|
|
1743
|
+
return store.mutate(async (loaded) => {
|
|
1744
|
+
if (!loaded) {
|
|
1745
|
+
throw new Error(`No remediation state found at ${join(options.artifactsDir, "state.json")}.`);
|
|
1746
|
+
}
|
|
1747
|
+
const state = loaded;
|
|
1748
|
+
if (!state.items) {
|
|
1749
|
+
throw new Error("Cannot merge implement results without items.");
|
|
1750
|
+
}
|
|
1751
|
+
return mergeImplementResultsIntoState(options, runId, plan, state);
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
/**
|
|
1755
|
+
* Apply every dispatched implement worker result to `state` (mutated in place)
|
|
1756
|
+
* and return it. Runs inside the StateStore.mutate lock so the caller commits
|
|
1757
|
+
* the result exactly once (OBL-INV-RSD-02 / OBL-SEAM-RSD-04). Pure with respect
|
|
1758
|
+
* to state.json: it mutates the in-memory `state` and writes only sidecar
|
|
1759
|
+
* evidence/diagnostic artifacts.
|
|
1760
|
+
*/
|
|
1761
|
+
async function mergeImplementResultsIntoState(options, runId, plan, state) {
|
|
1762
|
+
if (!state.items) {
|
|
1763
|
+
throw new Error("Cannot merge implement results without items.");
|
|
1764
|
+
}
|
|
1765
|
+
const dir = runDir(options.artifactsDir, runId, "implement");
|
|
1766
|
+
const plannedBlockIds = new Set(plan.items.map((item) => item.block_id).filter((id) => typeof id === "string"));
|
|
1767
|
+
const itemsToMerge = [...plan.items];
|
|
1768
|
+
for (const block of state.plan?.blocks ?? []) {
|
|
1769
|
+
if (plannedBlockIds.has(block.block_id)) {
|
|
1770
|
+
continue;
|
|
1771
|
+
}
|
|
1772
|
+
const hasDocumentedWork = block.items.some((findingId) => {
|
|
1773
|
+
const stateItem = state.items?.[findingId];
|
|
1774
|
+
return stateItem?.status === "pending";
|
|
1775
|
+
});
|
|
1776
|
+
if (!hasDocumentedWork) {
|
|
1777
|
+
continue;
|
|
1778
|
+
}
|
|
1779
|
+
const item = buildImplementDispatchItem(block, state, dir);
|
|
1780
|
+
const existingResult = await tryLoadExistingImplementResult(item.result_path);
|
|
1781
|
+
const pendingFindingIds = pendingOrDocumentedFindingIdsForBlock(block, state);
|
|
1782
|
+
if (!existingResult ||
|
|
1783
|
+
!implementResultCoversFindings(existingResult, pendingFindingIds)) {
|
|
1784
|
+
continue;
|
|
1785
|
+
}
|
|
1786
|
+
itemsToMerge.push(item);
|
|
1787
|
+
}
|
|
1788
|
+
// Build a lightweight ownership registry seeded from each block's declared
|
|
1789
|
+
// write_paths so amended_files checks are correct even when no rolling-dispatch
|
|
1790
|
+
// registry was persisted (interim path, until rollingDispatch replaces this).
|
|
1791
|
+
const mergeRegistry = new OwnershipRegistry();
|
|
1792
|
+
const dagNodes = itemsToMerge.flatMap((item) => {
|
|
1793
|
+
if (!item.block_id || !item.access)
|
|
1794
|
+
return [];
|
|
1795
|
+
return [{ node_id: item.block_id, write_paths: item.access.write_paths }];
|
|
1796
|
+
});
|
|
1797
|
+
mergeRegistry.initialize(dagNodes);
|
|
1798
|
+
// OBL-INV-RSD-01: a worker result whose finding_id is not in state.items is
|
|
1799
|
+
// never silently dropped and never throws past the loop. Each such id is
|
|
1800
|
+
// recorded here; if it belongs to a known block (via the result's owning
|
|
1801
|
+
// task block_id) that block's non-terminal items are blocked, otherwise it is
|
|
1802
|
+
// a true orphan recorded in the diagnostic artifact below. Either way the run
|
|
1803
|
+
// cannot advance past an unaccounted result.
|
|
1804
|
+
const orphanResults = [];
|
|
1805
|
+
// Per-block ACTUAL edited file sets (resolved from each block's worktree
|
|
1806
|
+
// branch), collected for post-loop lost-update / overlapping-edit detection
|
|
1807
|
+
// (ARC-f378135d-2 / ARC-c1693139). Only blocks dispatched through an isolated
|
|
1808
|
+
// worktree (their branch exists) contribute; the interim main-tree path has no
|
|
1809
|
+
// per-worker diff to attribute, so it cannot be checked for cross-block overlap.
|
|
1810
|
+
const editedByBlock = [];
|
|
1811
|
+
for (const item of itemsToMerge) {
|
|
1812
|
+
if (!existsSync(item.result_path)) {
|
|
1813
|
+
console.warn(`Missing implement worker result: ${item.result_path} — marking items blocked.`);
|
|
1814
|
+
const block = item.block_id
|
|
1815
|
+
? state.plan?.blocks.find((b) => b.block_id === item.block_id)
|
|
1816
|
+
: undefined;
|
|
1817
|
+
for (const findingId of block?.items ?? []) {
|
|
1818
|
+
const stateItem = state.items[findingId];
|
|
1819
|
+
// Don't flip a terminal item (resolved, or user-skipped
|
|
1820
|
+
// deemed_inappropriate/ignored) to blocked — only items that were
|
|
1821
|
+
// actually awaiting this worker's result.
|
|
1822
|
+
if (!stateItem || isTerminalStatus(stateItem.status))
|
|
1823
|
+
continue;
|
|
1824
|
+
stateItem.status = "blocked";
|
|
1825
|
+
markTerminal(stateItem);
|
|
1826
|
+
stateItem.failure_reason =
|
|
1827
|
+
`Implementation worker did not produce a result file: ${item.result_path}`;
|
|
1828
|
+
}
|
|
1829
|
+
continue;
|
|
1830
|
+
}
|
|
1831
|
+
const result = await readJsonFile(item.result_path);
|
|
1832
|
+
assertImplementWorkerResult(result, item.result_path);
|
|
1833
|
+
// Gate amended_files through the ownership registry (N-R22).
|
|
1834
|
+
// Unowned amended paths are granted and added to this block's effective scope
|
|
1835
|
+
// for verification; owned/contended paths block the item with a seam conflict.
|
|
1836
|
+
const blockId = item.block_id ?? "";
|
|
1837
|
+
if (result.amended_files && result.amended_files.length > 0) {
|
|
1838
|
+
const { granted, seam_routed } = routeAmendmentRequest(mergeRegistry, blockId, result.amended_files);
|
|
1839
|
+
if (granted.length > 0 && item.access) {
|
|
1840
|
+
// Expand the block's effective write scope for downstream verification.
|
|
1841
|
+
item.access.write_paths = uniquePaths([...item.access.write_paths, ...granted]);
|
|
1842
|
+
}
|
|
1843
|
+
if (seam_routed.length > 0) {
|
|
1844
|
+
// Mark all non-terminal items in this block as blocked with seam conflict detail.
|
|
1845
|
+
const block = state.plan?.blocks.find((b) => b.block_id === blockId);
|
|
1846
|
+
for (const findingId of block?.items ?? []) {
|
|
1847
|
+
const stateItem = state.items[findingId];
|
|
1848
|
+
if (!stateItem || isTerminalStatus(stateItem.status))
|
|
1849
|
+
continue;
|
|
1850
|
+
stateItem.status = "blocked";
|
|
1851
|
+
markTerminal(stateItem);
|
|
1852
|
+
stateItem.failure_reason =
|
|
1853
|
+
`Seam conflict on amended_files: ${seam_routed
|
|
1854
|
+
.map((r) => {
|
|
1855
|
+
const reason = r.reason;
|
|
1856
|
+
if (reason.outcome === "owned") {
|
|
1857
|
+
return `${r.path} owned by ${reason.owner_node_id}`;
|
|
1858
|
+
}
|
|
1859
|
+
else if (reason.outcome === "contended") {
|
|
1860
|
+
return `${r.path} contended by ${reason.sibling_node_id}`;
|
|
1861
|
+
}
|
|
1862
|
+
return r.path;
|
|
1863
|
+
})
|
|
1864
|
+
.join("; ")}`;
|
|
1865
|
+
}
|
|
1866
|
+
// Release any grants we just made before moving on (best-effort cleanup).
|
|
1867
|
+
mergeRegistry.releaseAmendments(blockId);
|
|
1868
|
+
continue;
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
// Tolerant seam: remap an obligation/node-alias finding_id to the owning
|
|
1872
|
+
// node's finding, and collapse multi-entry results onto one entry per
|
|
1873
|
+
// finding (blocked dominates), before applying any status. A mislabel can
|
|
1874
|
+
// only ever resolve to a finding that belongs to THIS block.
|
|
1875
|
+
const owningBlock = blockId
|
|
1876
|
+
? state.plan?.blocks.find((b) => b.block_id === blockId)
|
|
1877
|
+
: undefined;
|
|
1878
|
+
const aliasMap = owningBlock
|
|
1879
|
+
? buildBlockAliasMap(owningBlock, state)
|
|
1880
|
+
: new Map();
|
|
1881
|
+
const knownFindingIds = new Set(Object.keys(state.items));
|
|
1882
|
+
const { collapsed, unresolved } = collapseItemResults(result.item_results, aliasMap, knownFindingIds);
|
|
1883
|
+
// Track which findings in this block this worker flipped to a resolved
|
|
1884
|
+
// status, so the write-scope gate below can re-block them if the worker's
|
|
1885
|
+
// ACTUAL git edits fall outside the declared scope.
|
|
1886
|
+
const resolvedFindingIds = [];
|
|
1887
|
+
for (const itemResult of unresolved) {
|
|
1888
|
+
// OBL-INV-RSD-01: do NOT throw on an unknown finding_id that did not remap
|
|
1889
|
+
// to a known node alias. Block the owning block's non-terminal items so the
|
|
1890
|
+
// run cannot advance past an unaccounted result; record a diagnostic.
|
|
1891
|
+
if (owningBlock) {
|
|
1892
|
+
for (const findingId of owningBlock.items) {
|
|
1893
|
+
const owningItem = state.items[findingId];
|
|
1894
|
+
if (!owningItem || isTerminalStatus(owningItem.status))
|
|
1895
|
+
continue;
|
|
1896
|
+
owningItem.status = "blocked";
|
|
1897
|
+
markTerminal(owningItem);
|
|
1898
|
+
owningItem.failure_reason =
|
|
1899
|
+
`Implementation worker for block ${blockId} reported an unknown ` +
|
|
1900
|
+
`finding_id "${itemResult.finding_id}" not present in this plan ` +
|
|
1901
|
+
`(and not a known obligation/node alias of this block); blocking the ` +
|
|
1902
|
+
`block's items so the run does not advance past an unaccounted result.`;
|
|
1903
|
+
}
|
|
1904
|
+
orphanResults.push({
|
|
1905
|
+
finding_id: itemResult.finding_id,
|
|
1906
|
+
result_path: item.result_path,
|
|
1907
|
+
owning_block_id: blockId,
|
|
1908
|
+
disposition: "blocked_owning_block",
|
|
1909
|
+
worker_status: itemResult.status,
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
else {
|
|
1913
|
+
orphanResults.push({
|
|
1914
|
+
finding_id: itemResult.finding_id,
|
|
1915
|
+
result_path: item.result_path,
|
|
1916
|
+
owning_block_id: null,
|
|
1917
|
+
disposition: "orphan",
|
|
1918
|
+
worker_status: itemResult.status,
|
|
1919
|
+
});
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
for (const itemResult of collapsed) {
|
|
1923
|
+
const stateItem = state.items[itemResult.finding_id];
|
|
1924
|
+
if (!stateItem)
|
|
1925
|
+
continue;
|
|
1926
|
+
// A worker may report a finding that is already terminal (user-skipped, or
|
|
1927
|
+
// resolved in a prior wave) — never let a result resurrect or overwrite it.
|
|
1928
|
+
if (isTerminalStatus(stateItem.status)) {
|
|
1929
|
+
continue;
|
|
1930
|
+
}
|
|
1931
|
+
if (itemResult.status === "resolved") {
|
|
1932
|
+
const spec = stateItem.item_spec;
|
|
1933
|
+
const isNoChange = specIndicatesNoChange(spec);
|
|
1934
|
+
if (isNoChange && !hasExecutableEvidence(itemResult.evidence)) {
|
|
1935
|
+
// No-prose closure: a "verified-already-satisfied" (no-change) claim must
|
|
1936
|
+
// be backed by an executable assertion (a test/build/check command +
|
|
1937
|
+
// result), not prose — otherwise a real requirement silently no-ops.
|
|
1938
|
+
// Route an unproven no-change claim to triage instead of closing it.
|
|
1939
|
+
stateItem.status = "blocked";
|
|
1940
|
+
markTerminal(stateItem);
|
|
1941
|
+
stateItem.failure_reason =
|
|
1942
|
+
"verified-already-satisfied requires an executable regression test proving " +
|
|
1943
|
+
"the behavior (a test/build/check command + result in evidence), not prose.";
|
|
1944
|
+
}
|
|
1945
|
+
else {
|
|
1946
|
+
stateItem.status = isNoChange ? "resolved_no_change" : "resolved";
|
|
1947
|
+
markTerminal(stateItem);
|
|
1948
|
+
// A no-change closure makes no edits, so it is exempt from the
|
|
1949
|
+
// git-diff write-scope gate; an actual fix is subject to it.
|
|
1950
|
+
if (!isNoChange) {
|
|
1951
|
+
resolvedFindingIds.push(itemResult.finding_id);
|
|
1952
|
+
}
|
|
1953
|
+
// OBL-INV-RSD-06 / OBL-SEAM-RSD-03: use the shared REMEDIATION_STEP
|
|
1954
|
+
// constant, never the bare string literal, so this path and any other
|
|
1955
|
+
// verify-against-documentation writer agree on one source of truth.
|
|
1956
|
+
stateItem.last_successful_step =
|
|
1957
|
+
REMEDIATION_STEP.VERIFY_AGAINST_DOCUMENTATION;
|
|
1958
|
+
if (itemResult.evidence?.length) {
|
|
1959
|
+
await writeJsonFile(join(options.artifactsDir, `result_${itemResult.finding_id}_verify_code_against_documentation.json`), {
|
|
1960
|
+
finding_id: itemResult.finding_id,
|
|
1961
|
+
passed: true,
|
|
1962
|
+
reason: itemResult.evidence,
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
else {
|
|
1968
|
+
stateItem.status = "blocked";
|
|
1969
|
+
markTerminal(stateItem);
|
|
1970
|
+
stateItem.failure_reason =
|
|
1971
|
+
itemResult.failure_reason ?? "Implementation worker blocked.";
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
// Write-scope enforcement against the worker's ACTUAL git edits
|
|
1975
|
+
// (OBL-DS-06): never trust self-reported amended_files for the gate. The
|
|
1976
|
+
// enforcement ground truth is the worker's worktree diff; it is applied when
|
|
1977
|
+
// this block was dispatched into an isolated worktree (the rolling-dispatch
|
|
1978
|
+
// flow). On the interim main-tree path there is no per-worker isolation to
|
|
1979
|
+
// diff against, so the gate is skipped here rather than mistaking ambient
|
|
1980
|
+
// working-tree state for this worker's edits. The decision is a pure function
|
|
1981
|
+
// (`enforceWriteScope`) so it is unit-tested directly against a known edit
|
|
1982
|
+
// set, and fail-closed semantics apply when git is a repo but the probe fails.
|
|
1983
|
+
const worktreeBranch = worktreeBranchForBlock(blockId, runId);
|
|
1984
|
+
// Resolve this block's ACTUAL worktree-branch edits ONCE when the branch
|
|
1985
|
+
// exists — reused for the write-scope gate below AND the post-loop
|
|
1986
|
+
// lost-update detection. A missing branch means the interim main-tree path
|
|
1987
|
+
// was used (no per-worker diff): skip both checks for this block.
|
|
1988
|
+
const branchEdited = gitBranchExists(options.root, worktreeBranch)
|
|
1989
|
+
? gitEditedFilesForBranch(options.root, worktreeBranch)
|
|
1990
|
+
: null;
|
|
1991
|
+
if (branchEdited?.available) {
|
|
1992
|
+
editedByBlock.push({ block_id: blockId, files: branchEdited.files });
|
|
1993
|
+
}
|
|
1994
|
+
// Activate the write-scope gate only when this block was actually dispatched
|
|
1995
|
+
// through an isolated worktree (its branch exists). A missing branch means
|
|
1996
|
+
// the interim main-tree path was used — there is no per-worker diff to
|
|
1997
|
+
// enforce against, so the gate is skipped (NOT fail-closed: fail-closed is
|
|
1998
|
+
// for a present repo whose diff genuinely errors).
|
|
1999
|
+
if (resolvedFindingIds.length > 0 && item.access && branchEdited) {
|
|
2000
|
+
const decision = enforceWriteScope(item.access.write_paths, branchEdited, options.root);
|
|
2001
|
+
if (decision.blocked) {
|
|
2002
|
+
for (const findingId of resolvedFindingIds) {
|
|
2003
|
+
const stateItem = state.items[findingId];
|
|
2004
|
+
if (!stateItem)
|
|
2005
|
+
continue;
|
|
2006
|
+
stateItem.status = "blocked";
|
|
2007
|
+
markTerminal(stateItem);
|
|
2008
|
+
stateItem.failure_reason = decision.reason;
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
// Merge-state gate (authoritative, OBL-DS-06): a node that self-reported a
|
|
2013
|
+
// finding "resolved" but whose tool-owned verify/merge did NOT land its edits
|
|
2014
|
+
// (acceptNodeWorktree returned merged:false — verify failed, a cherry-pick
|
|
2015
|
+
// conflict, or no actual edit) must never stand as resolved: its fix is not in
|
|
2016
|
+
// the main tree. The recorded per-node accept outcome is the ground truth, never
|
|
2017
|
+
// the worker's result file. Keyed on resolvedFindingIds, so a legitimate
|
|
2018
|
+
// no-change closure (which makes no edits by design, and is not in that set)
|
|
2019
|
+
// stays exempt. Worktree-dispatched blocks have a record; the interim main-tree
|
|
2020
|
+
// path writes none, so this gate is inert there.
|
|
2021
|
+
if (resolvedFindingIds.length > 0) {
|
|
2022
|
+
const acceptOutcome = await loadNodeAcceptOutcome(options.artifactsDir, runId, blockId);
|
|
2023
|
+
if (acceptOutcome && !acceptOutcome.merged) {
|
|
2024
|
+
for (const findingId of resolvedFindingIds) {
|
|
2025
|
+
const stateItem = state.items[findingId];
|
|
2026
|
+
if (!stateItem)
|
|
2027
|
+
continue;
|
|
2028
|
+
stateItem.status = "blocked";
|
|
2029
|
+
markTerminal(stateItem);
|
|
2030
|
+
stateItem.failure_reason =
|
|
2031
|
+
`Node ${blockId} reported finding ${findingId} resolved, but its tool-owned ` +
|
|
2032
|
+
`verify/merge did not land the edits (outcome=${acceptOutcome.outcome}, ` +
|
|
2033
|
+
`verify_passed=${acceptOutcome.verifyPassed}, merged=false); the fix is not in ` +
|
|
2034
|
+
`the main tree. Routed to triage.`;
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
// Release this block's amendment claims after it has been merged or blocked.
|
|
2039
|
+
mergeRegistry.releaseAmendments(blockId);
|
|
2040
|
+
}
|
|
2041
|
+
// OBL-INV-RSD-01: persist a deterministic diagnostic for every unmatched
|
|
2042
|
+
// worker result so an orphan is auditable and never silently dropped. This is
|
|
2043
|
+
// a sidecar artifact (not state.json), so it does not affect the single
|
|
2044
|
+
// state-commit invariant (RSD-02).
|
|
2045
|
+
if (orphanResults.length > 0) {
|
|
2046
|
+
await writeJsonFile(join(dir, "orphaned-implement-results.json"), {
|
|
2047
|
+
schema_version: "remediate-code-implement/orphaned-results/v1alpha1",
|
|
2048
|
+
run_id: runId,
|
|
2049
|
+
created_at: new Date().toISOString(),
|
|
2050
|
+
orphans: orphanResults,
|
|
2051
|
+
});
|
|
2052
|
+
process.stderr.write(`[remediate-code] dispatch: ${orphanResults.length} unmatched implement ` +
|
|
2053
|
+
`result finding_id(s) recorded as orphan dispositions (not dropped): ` +
|
|
2054
|
+
`${orphanResults.map((o) => o.finding_id).join(", ")}\n`);
|
|
2055
|
+
}
|
|
2056
|
+
// Lost-update / overlapping-edit detection (ARC-f378135d-2 / ARC-c1693139):
|
|
2057
|
+
// when the rolling engine had multiple nodes in flight, two workers can each
|
|
2058
|
+
// edit the SAME file in their own worktree; cherry-picking both would silently
|
|
2059
|
+
// drop one change. Any file edited by more than one merged block is a
|
|
2060
|
+
// lost-update hazard — block every involved block's still-non-terminal items
|
|
2061
|
+
// and route them to triage so the conflict is reconciled, never lost. Recorded
|
|
2062
|
+
// as a sidecar diagnostic. Single-block runs (the proven host-wave path)
|
|
2063
|
+
// produce zero overlaps, so this is inert on the current default path.
|
|
2064
|
+
const overlappingEdits = detectOverlappingEdits(editedByBlock);
|
|
2065
|
+
if (overlappingEdits.length > 0) {
|
|
2066
|
+
const involvedBlockIds = new Set(overlappingEdits.flatMap((o) => o.block_ids));
|
|
2067
|
+
for (const blockId of involvedBlockIds) {
|
|
2068
|
+
const block = state.plan?.blocks.find((b) => b.block_id === blockId);
|
|
2069
|
+
const conflictPaths = overlappingEdits
|
|
2070
|
+
.filter((o) => o.block_ids.includes(blockId))
|
|
2071
|
+
.map((o) => o.path);
|
|
2072
|
+
for (const findingId of block?.items ?? []) {
|
|
2073
|
+
const stateItem = state.items[findingId];
|
|
2074
|
+
if (!stateItem || isTerminalStatus(stateItem.status))
|
|
2075
|
+
continue;
|
|
2076
|
+
stateItem.status = "blocked";
|
|
2077
|
+
markTerminal(stateItem);
|
|
2078
|
+
stateItem.failure_reason =
|
|
2079
|
+
`Lost-update hazard: this block's worker edited file(s) also edited by ` +
|
|
2080
|
+
`another concurrently-dispatched block (${conflictPaths.join(", ")}). ` +
|
|
2081
|
+
`Blocking both so the overlapping change is reconciled in triage rather ` +
|
|
2082
|
+
`than silently dropped by a cherry-pick.`;
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
await writeJsonFile(join(dir, "overlapping-edits.json"), {
|
|
2086
|
+
schema_version: "remediate-code-implement/overlapping-edits/v1alpha1",
|
|
2087
|
+
run_id: runId,
|
|
2088
|
+
created_at: new Date().toISOString(),
|
|
2089
|
+
overlaps: overlappingEdits,
|
|
2090
|
+
});
|
|
2091
|
+
process.stderr.write(`[remediate-code] dispatch: ${overlappingEdits.length} overlapping-edit ` +
|
|
2092
|
+
`conflict(s) across concurrently-merged blocks; involved blocks routed to ` +
|
|
2093
|
+
`triage: ${[...involvedBlockIds].join(", ")}\n`);
|
|
2094
|
+
}
|
|
2095
|
+
// Re-baseline affected-file hashes: the implement phase legitimately rewrites
|
|
2096
|
+
// these files, so a later integrity check must not flag the run's own edits as
|
|
2097
|
+
// a stale plan when re-attempting any remaining blocked findings.
|
|
2098
|
+
if (state.plan?.findings?.length) {
|
|
2099
|
+
resnapshotAffectedFileHashes(options.root, state.plan.findings);
|
|
2100
|
+
}
|
|
2101
|
+
// Per-node dispositions (INV-DS-15). One disposition per merged block/node; a
|
|
2102
|
+
// SKIP disposition is never reported as verified_complete. This is a sidecar
|
|
2103
|
+
// artifact (not state.json).
|
|
2104
|
+
const mergedBlocks = itemsToMerge.flatMap((item) => {
|
|
2105
|
+
if (!item.block_id)
|
|
2106
|
+
return [];
|
|
2107
|
+
const block = state.plan?.blocks.find((b) => b.block_id === item.block_id);
|
|
2108
|
+
return block ? [{ block, item }] : [];
|
|
2109
|
+
});
|
|
2110
|
+
const dispositions = mergedBlocks.map(({ block }) => buildNodeDisposition(block, state));
|
|
2111
|
+
// Sibling-red routing (INV-DS-14). For each merged block that ended red
|
|
2112
|
+
// (blocked), attribute the failure against the OTHER merged blocks' write
|
|
2113
|
+
// scopes: an attributable red (exactly one sibling owns the implicated
|
|
2114
|
+
// surface) routes that sibling to triage; an unattributable red is deferred to
|
|
2115
|
+
// the rolling-scheduler's coarse backstop. The state already advances to
|
|
2116
|
+
// triage below; this records the attribution decision deterministically.
|
|
2117
|
+
const siblingRedRoutes = [];
|
|
2118
|
+
for (const { block, item } of mergedBlocks) {
|
|
2119
|
+
const disposition = dispositions.find((d) => d.block_id === block.block_id);
|
|
2120
|
+
if (!disposition || disposition.disposition !== "blocked")
|
|
2121
|
+
continue;
|
|
2122
|
+
// The files implicated by this red node = its declared write scope.
|
|
2123
|
+
const implicatedFiles = item.access?.write_paths ?? [];
|
|
2124
|
+
const siblingScopes = mergedBlocks
|
|
2125
|
+
.filter((m) => m.block.block_id !== block.block_id)
|
|
2126
|
+
.map((m) => ({
|
|
2127
|
+
block_id: m.block.block_id,
|
|
2128
|
+
write_paths: m.item.access?.write_paths ?? [],
|
|
2129
|
+
}));
|
|
2130
|
+
const attributed = attributeSiblingRed(implicatedFiles, siblingScopes, options.root);
|
|
2131
|
+
siblingRedRoutes.push({
|
|
2132
|
+
red_block_id: block.block_id,
|
|
2133
|
+
implicated_files: implicatedFiles.map((p) => toRepoRelative(p, options.root)),
|
|
2134
|
+
routed_to_triage_block_id: attributed,
|
|
2135
|
+
backstop: attributed ? null : "rolling_scheduler_coarse",
|
|
2136
|
+
});
|
|
2137
|
+
}
|
|
2138
|
+
if (dispositions.length > 0) {
|
|
2139
|
+
await writeJsonFile(join(dir, "node-dispositions.json"), {
|
|
2140
|
+
schema_version: "remediate-code-implement/node-dispositions/v1alpha1",
|
|
2141
|
+
run_id: runId,
|
|
2142
|
+
created_at: new Date().toISOString(),
|
|
2143
|
+
dispositions,
|
|
2144
|
+
sibling_red_routes: siblingRedRoutes,
|
|
2145
|
+
});
|
|
2146
|
+
}
|
|
2147
|
+
const mergedFindingIds = new Set(itemsToMerge.flatMap((item) => {
|
|
2148
|
+
if (!item.block_id)
|
|
2149
|
+
return [];
|
|
2150
|
+
const block = state.plan?.blocks.find((b) => b.block_id === item.block_id);
|
|
2151
|
+
return block?.items ?? [];
|
|
2152
|
+
}));
|
|
2153
|
+
let implementResolved = 0;
|
|
2154
|
+
let implementRejected = 0;
|
|
2155
|
+
for (const findingId of mergedFindingIds) {
|
|
2156
|
+
const status = state.items[findingId]?.status;
|
|
2157
|
+
if (isVerifiedCompleteStatus(status))
|
|
2158
|
+
implementResolved++;
|
|
2159
|
+
else if (status === "blocked")
|
|
2160
|
+
implementRejected++;
|
|
2161
|
+
}
|
|
2162
|
+
process.stderr.write(`[remediate-code] dispatch: merged ${implementResolved} implement result(s), ` +
|
|
2163
|
+
`${implementRejected} rejected\n`);
|
|
2164
|
+
// Route back to implementing while pending work remains (later dependency
|
|
2165
|
+
// waves, or blocks deferred this wave because a prerequisite was still
|
|
2166
|
+
// running) so the next next-step dispatches the now-ready blocks; otherwise
|
|
2167
|
+
// advance to implementing → triage.
|
|
2168
|
+
const moreToImplement = Object.values(state.items).some((it) => it.status === "pending");
|
|
2169
|
+
state.status = moreToImplement ? "implementing" : "triage";
|
|
2170
|
+
// Single commit: StateStore.mutate writes the returned state once, under the
|
|
2171
|
+
// lock it already holds (OBL-INV-RSD-02 / OBL-SEAM-RSD-04). No saveState here.
|
|
2172
|
+
return state;
|
|
2173
|
+
}
|
|
2174
|
+
export async function readExtractedPlanIfPresent(artifactsDir) {
|
|
2175
|
+
return readOptionalJsonFile(join(artifactsDir, "extracted-plan.json"));
|
|
2176
|
+
}
|
|
2177
|
+
export async function readDispatchPlan(artifactsDir, runId, phase) {
|
|
2178
|
+
return readJsonFile(dispatchPlanPath(artifactsDir, runId, phase));
|
|
2179
|
+
}
|
|
2180
|
+
//# sourceMappingURL=dispatch.js.map
|