audit-tools 0.50.21 → 0.51.1
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.md +1 -1
- package/dist/audit/cli/auditStep.d.ts +1 -1
- package/dist/audit/cli/charterExtractionPrompt.d.ts.map +1 -1
- package/dist/audit/cli/charterExtractionPrompt.js +14 -1
- package/dist/audit/cli/charterExtractionPrompt.js.map +1 -1
- package/dist/audit/cli/cleanup.d.ts +0 -1
- package/dist/audit/cli/cleanup.d.ts.map +1 -1
- package/dist/audit/cli/cleanup.js +32 -20
- package/dist/audit/cli/cleanup.js.map +1 -1
- package/dist/audit/cli/conceptualDispatch.d.ts.map +1 -1
- package/dist/audit/cli/conceptualDispatch.js +30 -5
- package/dist/audit/cli/conceptualDispatch.js.map +1 -1
- package/dist/audit/cli/dispatch/hostHandoff.d.ts +2 -0
- package/dist/audit/cli/dispatch/hostHandoff.d.ts.map +1 -1
- package/dist/audit/cli/dispatch/hostHandoff.js +48 -20
- package/dist/audit/cli/dispatch/hostHandoff.js.map +1 -1
- package/dist/audit/cli/fanoutLanes.d.ts +7 -0
- package/dist/audit/cli/fanoutLanes.d.ts.map +1 -1
- package/dist/audit/cli/fanoutLanes.js +9 -1
- package/dist/audit/cli/fanoutLanes.js.map +1 -1
- package/dist/audit/cli/forceSynthesisCommand.d.ts.map +1 -1
- package/dist/audit/cli/forceSynthesisCommand.js +2 -14
- package/dist/audit/cli/forceSynthesisCommand.js.map +1 -1
- package/dist/audit/cli/intakeCommand.d.ts.map +1 -1
- package/dist/audit/cli/intakeCommand.js +3 -13
- package/dist/audit/cli/intakeCommand.js.map +1 -1
- package/dist/audit/cli/laneSubmissions.d.ts +42 -57
- package/dist/audit/cli/laneSubmissions.d.ts.map +1 -1
- package/dist/audit/cli/laneSubmissions.js +116 -82
- package/dist/audit/cli/laneSubmissions.js.map +1 -1
- package/dist/audit/cli/nextStepCommand.d.ts.map +1 -1
- package/dist/audit/cli/nextStepCommand.js +132 -99
- package/dist/audit/cli/nextStepCommand.js.map +1 -1
- package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
- package/dist/audit/cli/nextStepHelpers.js +39 -46
- package/dist/audit/cli/nextStepHelpers.js.map +1 -1
- package/dist/audit/cli/resynthesizeCommand.d.ts.map +1 -1
- package/dist/audit/cli/resynthesizeCommand.js +5 -2
- package/dist/audit/cli/resynthesizeCommand.js.map +1 -1
- package/dist/audit/cli/sampleRunCommand.d.ts +3 -2
- package/dist/audit/cli/sampleRunCommand.d.ts.map +1 -1
- package/dist/audit/cli/stepScaffold.d.ts +21 -0
- package/dist/audit/cli/stepScaffold.d.ts.map +1 -0
- package/dist/audit/cli/stepScaffold.js +50 -0
- package/dist/audit/cli/stepScaffold.js.map +1 -0
- package/dist/audit/cli/steps.d.ts +6 -6
- package/dist/audit/cli/synthesizeCommand.d.ts.map +1 -1
- package/dist/audit/cli/synthesizeCommand.js +2 -14
- package/dist/audit/cli/synthesizeCommand.js.map +1 -1
- package/dist/audit/contracts/workerSchemas.d.ts +8 -8
- package/dist/audit/contracts/workerSchemas.d.ts.map +1 -1
- package/dist/audit/contracts/workerSchemas.js +12 -6
- package/dist/audit/contracts/workerSchemas.js.map +1 -1
- package/dist/audit/contracts/wrapperResponse.d.ts +7 -7
- package/dist/audit/contracts/wrapperResponse.d.ts.map +1 -1
- package/dist/audit/contracts/wrapperResponse.js +9 -1
- package/dist/audit/contracts/wrapperResponse.js.map +1 -1
- package/dist/audit/extractors/analyzers/merge.d.ts.map +1 -1
- package/dist/audit/extractors/analyzers/merge.js +2 -7
- package/dist/audit/extractors/analyzers/merge.js.map +1 -1
- package/dist/audit/extractors/commentDecomposition.d.ts +28 -0
- package/dist/audit/extractors/commentDecomposition.d.ts.map +1 -1
- package/dist/audit/extractors/commentDecomposition.js +151 -22
- package/dist/audit/extractors/commentDecomposition.js.map +1 -1
- package/dist/audit/extractors/graph.d.ts +1 -1
- package/dist/audit/extractors/graph.d.ts.map +1 -1
- package/dist/audit/extractors/graph.js +2 -6
- package/dist/audit/extractors/graph.js.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/cargo.d.ts.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/cargo.js +4 -4
- package/dist/audit/extractors/graphManifestEdges/cargo.js.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/pnpm.d.ts.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/pnpm.js +3 -3
- package/dist/audit/extractors/graphManifestEdges/pnpm.js.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/pyproject.d.ts.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/pyproject.js +3 -2
- package/dist/audit/extractors/graphManifestEdges/pyproject.js.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/toml.d.ts +0 -6
- package/dist/audit/extractors/graphManifestEdges/toml.d.ts.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/toml.js +0 -13
- package/dist/audit/extractors/graphManifestEdges/toml.js.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/workspace.d.ts +9 -0
- package/dist/audit/extractors/graphManifestEdges/workspace.d.ts.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/workspace.js +16 -0
- package/dist/audit/extractors/graphManifestEdges/workspace.js.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/yaml.d.ts +0 -2
- package/dist/audit/extractors/graphManifestEdges/yaml.d.ts.map +1 -1
- package/dist/audit/extractors/graphManifestEdges/yaml.js +0 -9
- package/dist/audit/extractors/graphManifestEdges/yaml.js.map +1 -1
- package/dist/audit/extractors/graphSignals.d.ts.map +1 -1
- package/dist/audit/extractors/graphSignals.js +16 -2
- package/dist/audit/extractors/graphSignals.js.map +1 -1
- package/dist/audit/io/artifacts.d.ts +19 -0
- package/dist/audit/io/artifacts.d.ts.map +1 -1
- package/dist/audit/io/artifacts.js +44 -2
- package/dist/audit/io/artifacts.js.map +1 -1
- package/dist/audit/orchestrator/advance.d.ts +0 -22
- package/dist/audit/orchestrator/advance.d.ts.map +1 -1
- package/dist/audit/orchestrator/advance.js +1 -43
- package/dist/audit/orchestrator/advance.js.map +1 -1
- package/dist/audit/orchestrator/charterDeltaExecutor.d.ts.map +1 -1
- package/dist/audit/orchestrator/charterDeltaExecutor.js +14 -0
- package/dist/audit/orchestrator/charterDeltaExecutor.js.map +1 -1
- package/dist/audit/orchestrator/charterExtractionExecutor.d.ts +16 -6
- package/dist/audit/orchestrator/charterExtractionExecutor.d.ts.map +1 -1
- package/dist/audit/orchestrator/charterExtractionExecutor.js +127 -9
- package/dist/audit/orchestrator/charterExtractionExecutor.js.map +1 -1
- package/dist/audit/orchestrator/charterPacketArchive.d.ts +51 -0
- package/dist/audit/orchestrator/charterPacketArchive.d.ts.map +1 -0
- package/dist/audit/orchestrator/charterPacketArchive.js +173 -0
- package/dist/audit/orchestrator/charterPacketArchive.js.map +1 -0
- package/dist/audit/orchestrator/charterPackets.d.ts +31 -13
- package/dist/audit/orchestrator/charterPackets.d.ts.map +1 -1
- package/dist/audit/orchestrator/charterPackets.js +299 -96
- package/dist/audit/orchestrator/charterPackets.js.map +1 -1
- package/dist/audit/orchestrator/designReviewPrompt.d.ts +20 -4
- package/dist/audit/orchestrator/designReviewPrompt.d.ts.map +1 -1
- package/dist/audit/orchestrator/designReviewPrompt.js +89 -12
- package/dist/audit/orchestrator/designReviewPrompt.js.map +1 -1
- package/dist/audit/orchestrator/edgeReasoning.d.ts.map +1 -1
- package/dist/audit/orchestrator/edgeReasoning.js +4 -9
- package/dist/audit/orchestrator/edgeReasoning.js.map +1 -1
- package/dist/audit/orchestrator/executorRunners.d.ts.map +1 -1
- package/dist/audit/orchestrator/executorRunners.js +17 -1
- package/dist/audit/orchestrator/executorRunners.js.map +1 -1
- package/dist/audit/orchestrator/graphEnrichmentExecutor.d.ts.map +1 -1
- package/dist/audit/orchestrator/graphEnrichmentExecutor.js +8 -1
- package/dist/audit/orchestrator/graphEnrichmentExecutor.js.map +1 -1
- package/dist/audit/orchestrator/intentCheckpointGate.d.ts.map +1 -1
- package/dist/audit/orchestrator/intentCheckpointGate.js +11 -2
- package/dist/audit/orchestrator/intentCheckpointGate.js.map +1 -1
- package/dist/audit/orchestrator/lineCounts.d.ts +44 -0
- package/dist/audit/orchestrator/lineCounts.d.ts.map +1 -0
- package/dist/audit/orchestrator/lineCounts.js +61 -0
- package/dist/audit/orchestrator/lineCounts.js.map +1 -0
- package/dist/audit/orchestrator/obligationDerive.d.ts +35 -0
- package/dist/audit/orchestrator/obligationDerive.d.ts.map +1 -0
- package/dist/audit/orchestrator/obligationDerive.js +50 -0
- package/dist/audit/orchestrator/obligationDerive.js.map +1 -0
- package/dist/audit/orchestrator/reviewPacketMetrics.d.ts.map +1 -1
- package/dist/audit/orchestrator/reviewPacketMetrics.js +3 -2
- package/dist/audit/orchestrator/reviewPacketMetrics.js.map +1 -1
- package/dist/audit/orchestrator/reviewPacketShared.d.ts +0 -2
- package/dist/audit/orchestrator/reviewPacketShared.d.ts.map +1 -1
- package/dist/audit/orchestrator/reviewPacketShared.js +0 -4
- package/dist/audit/orchestrator/reviewPacketShared.js.map +1 -1
- package/dist/audit/orchestrator/reviewPackets.d.ts.map +1 -1
- package/dist/audit/orchestrator/reviewPackets.js +3 -2
- package/dist/audit/orchestrator/reviewPackets.js.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/conflict.d.ts.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/conflict.js +3 -2
- package/dist/audit/orchestrator/selectiveDeepening/conflict.js.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.d.ts.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.js +3 -2
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.js.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.d.ts.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.js +3 -2
- package/dist/audit/orchestrator/selectiveDeepening/highRiskClean.js.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/lensVerification.d.ts.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/lensVerification.js +4 -3
- package/dist/audit/orchestrator/selectiveDeepening/lensVerification.js.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.d.ts.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.js +2 -1
- package/dist/audit/orchestrator/selectiveDeepening/runtimeValidation.js.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/shared.d.ts +0 -2
- package/dist/audit/orchestrator/selectiveDeepening/shared.d.ts.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/shared.js +0 -27
- package/dist/audit/orchestrator/selectiveDeepening/shared.js.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.d.ts.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.js +10 -1
- package/dist/audit/orchestrator/selectiveDeepening/stewardFollowup.js.map +1 -1
- package/dist/audit/orchestrator/state.d.ts.map +1 -1
- package/dist/audit/orchestrator/state.js +21 -14
- package/dist/audit/orchestrator/state.js.map +1 -1
- package/dist/audit/orchestrator/synthesisExecutors.d.ts +8 -0
- package/dist/audit/orchestrator/synthesisExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/synthesisExecutors.js +10 -0
- package/dist/audit/orchestrator/synthesisExecutors.js.map +1 -1
- package/dist/audit/reporting/synthesis.d.ts +42 -2
- package/dist/audit/reporting/synthesis.d.ts.map +1 -1
- package/dist/audit/reporting/synthesis.js +264 -12
- package/dist/audit/reporting/synthesis.js.map +1 -1
- package/dist/audit/supervisor/operatorHandoff.d.ts.map +1 -1
- package/dist/audit/supervisor/operatorHandoff.js +14 -6
- package/dist/audit/supervisor/operatorHandoff.js.map +1 -1
- package/dist/audit/systemic/secondOrderAdversaryPrompt.d.ts.map +1 -1
- package/dist/audit/systemic/secondOrderAdversaryPrompt.js +14 -0
- package/dist/audit/systemic/secondOrderAdversaryPrompt.js.map +1 -1
- package/dist/audit/types/analyzerCapability.d.ts +35 -11
- package/dist/audit/types/analyzerCapability.d.ts.map +1 -1
- package/dist/audit/types/analyzerCapability.js +83 -5
- package/dist/audit/types/analyzerCapability.js.map +1 -1
- package/dist/audit/types/auditState.d.ts +8 -8
- package/dist/audit/types/charterRegister.d.ts +33 -3
- package/dist/audit/types/charterRegister.d.ts.map +1 -1
- package/dist/audit/types/charterRegister.js +11 -1
- package/dist/audit/types/charterRegister.js.map +1 -1
- package/dist/audit/types/conceptualAdjudication.d.ts +395 -16
- package/dist/audit/types/conceptualAdjudication.d.ts.map +1 -1
- package/dist/audit/types/conceptualAdjudication.js +109 -5
- package/dist/audit/types/conceptualAdjudication.js.map +1 -1
- package/dist/audit/types/designAssessment.d.ts +1 -1
- package/dist/audit/types/designAssessment.d.ts.map +1 -1
- package/dist/audit/types.d.ts +9 -4
- package/dist/audit/types.d.ts.map +1 -1
- package/dist/remediate/droppedFindingsRecord.d.ts +13 -0
- package/dist/remediate/droppedFindingsRecord.d.ts.map +1 -0
- package/dist/remediate/droppedFindingsRecord.js +113 -0
- package/dist/remediate/droppedFindingsRecord.js.map +1 -0
- package/dist/remediate/intake.d.ts +17 -0
- package/dist/remediate/intake.d.ts.map +1 -1
- package/dist/remediate/intake.js +23 -0
- package/dist/remediate/intake.js.map +1 -1
- package/dist/remediate/intent/intentOrdering.d.ts.map +1 -1
- package/dist/remediate/intent/intentOrdering.js +29 -1
- package/dist/remediate/intent/intentOrdering.js.map +1 -1
- package/dist/remediate/phases/close.d.ts +1 -1
- package/dist/remediate/phases/close.d.ts.map +1 -1
- package/dist/remediate/phases/close.js +68 -6
- package/dist/remediate/phases/close.js.map +1 -1
- package/dist/remediate/phases/grounding.d.ts +12 -4
- package/dist/remediate/phases/grounding.d.ts.map +1 -1
- package/dist/remediate/phases/grounding.js +23 -60
- package/dist/remediate/phases/grounding.js.map +1 -1
- package/dist/remediate/state/types.d.ts +17 -6
- package/dist/remediate/state/types.d.ts.map +1 -1
- package/dist/remediate/state/types.js +3 -1
- package/dist/remediate/state/types.js.map +1 -1
- package/dist/remediate/steps/contractPipeline.d.ts.map +1 -1
- package/dist/remediate/steps/contractPipeline.js +10 -4
- package/dist/remediate/steps/contractPipeline.js.map +1 -1
- package/dist/remediate/steps/contractPipelinePrompts.d.ts +10 -2
- package/dist/remediate/steps/contractPipelinePrompts.d.ts.map +1 -1
- package/dist/remediate/steps/contractPipelinePrompts.js +56 -12
- package/dist/remediate/steps/contractPipelinePrompts.js.map +1 -1
- package/dist/remediate/steps/dispatch/hostHandoff.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch/hostHandoff.js +277 -146
- package/dist/remediate/steps/dispatch/hostHandoff.js.map +1 -1
- package/dist/remediate/steps/nextStep.d.ts.map +1 -1
- package/dist/remediate/steps/nextStep.js +253 -75
- package/dist/remediate/steps/nextStep.js.map +1 -1
- package/dist/remediate/steps/prompts.d.ts +14 -0
- package/dist/remediate/steps/prompts.d.ts.map +1 -1
- package/dist/remediate/steps/prompts.js +52 -4
- package/dist/remediate/steps/prompts.js.map +1 -1
- package/dist/remediate/steps/types.d.ts +1 -1
- package/dist/remediate/steps/types.d.ts.map +1 -1
- package/dist/remediate/steps/types.js.map +1 -1
- package/dist/remediate/validation/contractPipelineGates.d.ts +0 -34
- package/dist/remediate/validation/contractPipelineGates.d.ts.map +1 -1
- package/dist/remediate/validation/contractPipelineGates.js +181 -143
- package/dist/remediate/validation/contractPipelineGates.js.map +1 -1
- package/dist/shared/agentReflections.d.ts +44 -3
- package/dist/shared/agentReflections.d.ts.map +1 -1
- package/dist/shared/agentReflections.js +63 -4
- package/dist/shared/agentReflections.js.map +1 -1
- package/dist/shared/analyzers/acquisitionEngine.d.ts +20 -1
- package/dist/shared/analyzers/acquisitionEngine.d.ts.map +1 -1
- package/dist/shared/analyzers/acquisitionEngine.js +17 -3
- package/dist/shared/analyzers/acquisitionEngine.js.map +1 -1
- package/dist/shared/analyzers/candidates.d.ts.map +1 -1
- package/dist/shared/analyzers/candidates.js +13 -4
- package/dist/shared/analyzers/candidates.js.map +1 -1
- package/dist/shared/analyzers/types.d.ts +17 -6
- package/dist/shared/analyzers/types.d.ts.map +1 -1
- package/dist/shared/analyzers/types.js +6 -15
- package/dist/shared/analyzers/types.js.map +1 -1
- package/dist/shared/decompose/systemicChallenge.d.ts +116 -9
- package/dist/shared/decompose/systemicChallenge.d.ts.map +1 -1
- package/dist/shared/decompose/systemicChallenge.js +32 -1
- package/dist/shared/decompose/systemicChallenge.js.map +1 -1
- package/dist/shared/engine/obligationEngine.d.ts +23 -6
- package/dist/shared/engine/obligationEngine.d.ts.map +1 -1
- package/dist/shared/engine/obligationEngine.js +38 -3
- package/dist/shared/engine/obligationEngine.js.map +1 -1
- package/dist/shared/findings/dedupe.d.ts +10 -0
- package/dist/shared/findings/dedupe.d.ts.map +1 -1
- package/dist/shared/findings/dedupe.js +15 -0
- package/dist/shared/findings/dedupe.js.map +1 -1
- package/dist/shared/friction/triage.d.ts.map +1 -1
- package/dist/shared/friction/triage.js +5 -1
- package/dist/shared/friction/triage.js.map +1 -1
- package/dist/shared/git.d.ts +6 -0
- package/dist/shared/git.d.ts.map +1 -1
- package/dist/shared/git.js +8 -0
- package/dist/shared/git.js.map +1 -1
- package/dist/shared/graph/edgeConfidence.d.ts +12 -0
- package/dist/shared/graph/edgeConfidence.d.ts.map +1 -0
- package/dist/shared/graph/edgeConfidence.js +15 -0
- package/dist/shared/graph/edgeConfidence.js.map +1 -0
- package/dist/shared/index.d.ts +26 -9
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +20 -8
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/loopCorePaths.d.ts.map +1 -1
- package/dist/shared/loopCorePaths.js +4 -0
- package/dist/shared/loopCorePaths.js.map +1 -1
- package/dist/shared/measurement/measuredOutcome.d.ts +61 -0
- package/dist/shared/measurement/measuredOutcome.d.ts.map +1 -0
- package/dist/shared/measurement/measuredOutcome.js +109 -0
- package/dist/shared/measurement/measuredOutcome.js.map +1 -0
- package/dist/shared/reporting/findingDisplay.d.ts +14 -2
- package/dist/shared/reporting/findingDisplay.d.ts.map +1 -1
- package/dist/shared/reporting/findingDisplay.js +29 -2
- package/dist/shared/reporting/findingDisplay.js.map +1 -1
- package/dist/shared/reporting/lensCoverage.d.ts +70 -0
- package/dist/shared/reporting/lensCoverage.d.ts.map +1 -0
- package/dist/shared/reporting/lensCoverage.js +108 -0
- package/dist/shared/reporting/lensCoverage.js.map +1 -0
- package/dist/shared/submission/hostResultOutcomes.d.ts +42 -0
- package/dist/shared/submission/hostResultOutcomes.d.ts.map +1 -0
- package/dist/shared/submission/hostResultOutcomes.js +129 -0
- package/dist/shared/submission/hostResultOutcomes.js.map +1 -0
- package/dist/shared/submission/ingestionChecks.d.ts +146 -0
- package/dist/shared/submission/ingestionChecks.d.ts.map +1 -0
- package/dist/shared/submission/ingestionChecks.js +157 -0
- package/dist/shared/submission/ingestionChecks.js.map +1 -0
- package/dist/shared/submission/submissionClassifier.d.ts +8 -0
- package/dist/shared/submission/submissionClassifier.d.ts.map +1 -1
- package/dist/shared/submission/submissionClassifier.js.map +1 -1
- package/dist/shared/submission/submissionLedger.d.ts +24 -1
- package/dist/shared/submission/submissionLedger.d.ts.map +1 -1
- package/dist/shared/submission/submissionLedger.js +61 -0
- package/dist/shared/submission/submissionLedger.js.map +1 -1
- package/dist/shared/submission/submissionScan.d.ts +2 -0
- package/dist/shared/submission/submissionScan.d.ts.map +1 -1
- package/dist/shared/submission/submissionScan.js +4 -0
- package/dist/shared/submission/submissionScan.js.map +1 -1
- package/dist/shared/tooling/projectFacts.d.ts +71 -0
- package/dist/shared/tooling/projectFacts.d.ts.map +1 -0
- package/dist/shared/tooling/projectFacts.js +153 -0
- package/dist/shared/tooling/projectFacts.js.map +1 -0
- package/dist/shared/tooling/projectTestAdmission.d.ts +5 -15
- package/dist/shared/tooling/projectTestAdmission.d.ts.map +1 -1
- package/dist/shared/tooling/projectTestAdmission.js +14 -5
- package/dist/shared/tooling/projectTestAdmission.js.map +1 -1
- package/dist/shared/types/charterPacket.d.ts +156 -0
- package/dist/shared/types/charterPacket.d.ts.map +1 -0
- package/dist/shared/types/charterPacket.js +9 -0
- package/dist/shared/types/charterPacket.js.map +1 -0
- package/dist/shared/types/closingActions.d.ts +16 -0
- package/dist/shared/types/closingActions.d.ts.map +1 -0
- package/dist/shared/types/closingActions.js +25 -0
- package/dist/shared/types/closingActions.js.map +1 -0
- package/dist/shared/types/finding.d.ts +275 -40
- package/dist/shared/types/finding.d.ts.map +1 -1
- package/dist/shared/types/finding.js +87 -0
- package/dist/shared/types/finding.js.map +1 -1
- package/dist/shared/types/intentCheckpoint.d.ts +50 -0
- package/dist/shared/types/intentCheckpoint.d.ts.map +1 -1
- package/dist/shared/types/intentCheckpoint.js +31 -0
- package/dist/shared/types/intentCheckpoint.js.map +1 -1
- package/dist/shared/validation/citationGrounding.d.ts +115 -0
- package/dist/shared/validation/citationGrounding.d.ts.map +1 -0
- package/dist/shared/validation/citationGrounding.js +347 -0
- package/dist/shared/validation/citationGrounding.js.map +1 -0
- package/dist/shared/validation/findingsReport.d.ts.map +1 -1
- package/dist/shared/validation/findingsReport.js +62 -0
- package/dist/shared/validation/findingsReport.js.map +1 -1
- package/docs/audit-pkg/contracts.md +34 -12
- package/docs/audit-pkg/operator-guide.md +10 -7
- package/package.json +3 -2
- package/schemas/audit-code-v1alpha1.schema.json +2 -1
- package/skills/audit-code/audit-code.prompt.md +5 -3
- package/dist/remediate/state/closingActions.d.ts +0 -3
- package/dist/remediate/state/closingActions.d.ts.map +0 -1
- package/dist/remediate/state/closingActions.js +0 -10
- package/dist/remediate/state/closingActions.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mkdir } from "node:fs/promises";
|
|
2
2
|
import { isAbsolute } from "node:path";
|
|
3
|
-
import { AUDIT_TOOLS_DIRNAME, headCommit, commandLeavesDeclaredShape, FindingSchema, SUBMISSION_ISSUE_CODES, SUBMISSION_LEDGER_EVENT_CONTRACT_VERSION, appendSubmissionEvent, compareCodeUnits, contentSha256, hasExactKeys, hostHandoffResultPath, idsAreStrictlyAscending, isCommit, isGitRepo, isRecord, isSha256, normalizeRepoPath, parseAllWorkloadItems, parseCommandString, parseWorkloadEnvelope, promptSha256, readSubmissionDocument, readSubmissionLedger, repoRelativePath, resolveContainedPath, resolveHostHandoffPaths, resultIdentityIsBound, runTrackedAsync, sameStrings, scanBoundSubmission, stringArray, stableStringify, TRACKED_CHILD_DEADLINE_MS, writeJsonFile, } from "audit-tools/shared";
|
|
3
|
+
import { AUDIT_TOOLS_DIRNAME, headCommit, commandLeavesDeclaredShape, FindingSchema, SUBMISSION_ISSUE_CODES, SUBMISSION_LEDGER_EVENT_CONTRACT_VERSION, appendSubmissionEvent, enrichMissingSubmissionIssues, compareCodeUnits, contentSha256, hasExactKeys, hostHandoffResultPath, idsAreStrictlyAscending, isCommit, isGitRepo, isRecord, isSha256, normalizeRepoPath, parseAllWorkloadItems, parseCommandString, parseWorkloadEnvelope, promptSha256, readSubmissionDocument, readSubmissionLedger, readTrailingSubmissionRefusals, recordHostResultOutcomes, repoRelativePath, resolveContainedPath, resolveHostHandoffPaths, resultIdentityIsBound, runTrackedAsync, sameStrings, scanBoundSubmission, stringArray, stableStringify, TRACKED_CHILD_DEADLINE_MS, writeJsonFile, } from "audit-tools/shared";
|
|
4
4
|
import { StateStore } from "../../state/store.js";
|
|
5
5
|
import { REMEDIATION_HOST_HANDOFF_RECORD_V1ALPHA1, REMEDIATION_HOST_HANDOFF_RECORD_V1ALPHA2, REMEDIATION_HOST_SCOPE_SEMANTICS, RemediationHostHandoffRecordSchema, RemediationPlanSchema, isClarificationCategory, } from "../../state/types.js";
|
|
6
6
|
import { ITEM_STATUSES, isTerminalStatus, isVerifiedCompleteStatus, } from "../../state/itemStatus.js";
|
|
@@ -481,7 +481,7 @@ export async function remediationSubmissionBinding(params) {
|
|
|
481
481
|
const parsed = parseResult(value, params.runId, validationWorkItem, paths.root);
|
|
482
482
|
return parsed.ok
|
|
483
483
|
? null
|
|
484
|
-
: { code: "submission_contract_invalid", message: parsed.reason };
|
|
484
|
+
: { code: "submission_contract_invalid", check: parsed.check, message: parsed.reason };
|
|
485
485
|
},
|
|
486
486
|
};
|
|
487
487
|
}
|
|
@@ -799,8 +799,9 @@ function parseWorkload(value, paths, runId, state) {
|
|
|
799
799
|
}
|
|
800
800
|
return value;
|
|
801
801
|
}
|
|
802
|
-
|
|
803
|
-
|
|
802
|
+
/** `check` names the registered ingestion check that failed; `reason` is its prose. */
|
|
803
|
+
function invalidResult(check, reason) {
|
|
804
|
+
return { ok: false, check, reason };
|
|
804
805
|
}
|
|
805
806
|
/**
|
|
806
807
|
* This draw's refusal vocabulary for {@link scanBoundSubmission}. The scan owns
|
|
@@ -817,6 +818,8 @@ const remediationScanMessages = {
|
|
|
817
818
|
};
|
|
818
819
|
function parseResult(value, runId, workItem, root) {
|
|
819
820
|
if (isRecord(value) && value.contract_version === DECISION_CONTRACT_VERSION) {
|
|
821
|
+
// Envelope first, identity second: one message (the host repairs the same
|
|
822
|
+
// file either way), two registered checks, so the issue names which failed.
|
|
820
823
|
if (!hasExactKeys(value, [
|
|
821
824
|
"contract_version",
|
|
822
825
|
"result_id",
|
|
@@ -825,14 +828,16 @@ function parseResult(value, runId, workItem, root) {
|
|
|
825
828
|
"prompt_sha256",
|
|
826
829
|
"outcome",
|
|
827
830
|
]) ||
|
|
828
|
-
!resultIdentityIsBound(value, {
|
|
829
|
-
runId,
|
|
830
|
-
workItemId: workItem.id,
|
|
831
|
-
promptSha256: workItem.prompt.sha256,
|
|
832
|
-
}) ||
|
|
833
831
|
!isRecord(value.outcome) ||
|
|
834
832
|
typeof value.outcome.status !== "string") {
|
|
835
|
-
return invalidResult("decision must match the exact current run, work-item, and prompt binding");
|
|
833
|
+
return invalidResult("result_envelope", "decision must match the exact current run, work-item, and prompt binding");
|
|
834
|
+
}
|
|
835
|
+
if (!resultIdentityIsBound(value, {
|
|
836
|
+
runId,
|
|
837
|
+
workItemId: workItem.id,
|
|
838
|
+
promptSha256: workItem.prompt.sha256,
|
|
839
|
+
})) {
|
|
840
|
+
return invalidResult("identity_binding", "decision must match the exact current run, work-item, and prompt binding");
|
|
836
841
|
}
|
|
837
842
|
const outcome = value.outcome;
|
|
838
843
|
if (outcome.status === "resolved_no_change") {
|
|
@@ -841,14 +846,14 @@ function parseResult(value, runId, workItem, root) {
|
|
|
841
846
|
!evidence ||
|
|
842
847
|
evidence.length === 0 ||
|
|
843
848
|
evidence.some((entry) => entry.trim().length === 0)) {
|
|
844
|
-
return invalidResult("resolved_no_change requires a non-empty evidence string array");
|
|
849
|
+
return invalidResult("outcome_shape", "resolved_no_change requires a non-empty evidence string array");
|
|
845
850
|
}
|
|
846
851
|
}
|
|
847
852
|
else if (outcome.status === "blocked") {
|
|
848
853
|
if (!hasExactKeys(outcome, ["status", "failure_reason"]) ||
|
|
849
854
|
typeof outcome.failure_reason !== "string" ||
|
|
850
855
|
outcome.failure_reason.trim().length === 0) {
|
|
851
|
-
return invalidResult("blocked requires a non-empty failure_reason");
|
|
856
|
+
return invalidResult("outcome_shape", "blocked requires a non-empty failure_reason");
|
|
852
857
|
}
|
|
853
858
|
}
|
|
854
859
|
else if (outcome.status === "needs_clarification") {
|
|
@@ -857,11 +862,11 @@ function parseResult(value, runId, workItem, root) {
|
|
|
857
862
|
outcome.question.trim().length === 0 ||
|
|
858
863
|
(outcome.category !== undefined &&
|
|
859
864
|
!isClarificationCategory(outcome.category))) {
|
|
860
|
-
return invalidResult("needs_clarification requires a non-empty question and optional canonical category");
|
|
865
|
+
return invalidResult("outcome_shape", "needs_clarification requires a non-empty question and optional canonical category");
|
|
861
866
|
}
|
|
862
867
|
}
|
|
863
868
|
else {
|
|
864
|
-
return invalidResult("decision outcome.status must be resolved_no_change, blocked, or needs_clarification");
|
|
869
|
+
return invalidResult("outcome_shape", "decision outcome.status must be resolved_no_change, blocked, or needs_clarification");
|
|
865
870
|
}
|
|
866
871
|
return {
|
|
867
872
|
ok: true,
|
|
@@ -884,13 +889,15 @@ function parseResult(value, runId, workItem, root) {
|
|
|
884
889
|
"work_item_id",
|
|
885
890
|
"worktree_evidence",
|
|
886
891
|
]) ||
|
|
887
|
-
value.contract_version !== RESULT_CONTRACT_VERSION
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
892
|
+
value.contract_version !== RESULT_CONTRACT_VERSION) {
|
|
893
|
+
return invalidResult("result_envelope", "result must match the exact current contract, run, work-item, and prompt binding");
|
|
894
|
+
}
|
|
895
|
+
if (!resultIdentityIsBound(value, {
|
|
896
|
+
runId,
|
|
897
|
+
workItemId: workItem.id,
|
|
898
|
+
promptSha256: workItem.prompt.sha256,
|
|
899
|
+
})) {
|
|
900
|
+
return invalidResult("identity_binding", "result must match the exact current contract, run, work-item, and prompt binding");
|
|
894
901
|
}
|
|
895
902
|
const changedFiles = stringArray(value.changed_files);
|
|
896
903
|
if (!changedFiles ||
|
|
@@ -898,25 +905,25 @@ function parseResult(value, runId, workItem, root) {
|
|
|
898
905
|
new Set(changedFiles).size !== changedFiles.length ||
|
|
899
906
|
!sameStrings([...changedFiles].sort(compareCodeUnits), changedFiles) ||
|
|
900
907
|
changedFiles.some((path) => !pathIsAllowedByWriteScope(root, path, workItem.allowed_files))) {
|
|
901
|
-
return invalidResult("changed_files must be non-empty, sorted, unique, normalized paths within allowed_files");
|
|
908
|
+
return invalidResult("write_scope", "changed_files must be non-empty, sorted, unique, normalized paths within allowed_files");
|
|
902
909
|
}
|
|
903
910
|
if (!isRecord(value.commit_evidence) ||
|
|
904
911
|
!hasExactKeys(value.commit_evidence, ["after", "before"]) ||
|
|
905
912
|
value.commit_evidence.before !== workItem.baseline_commit ||
|
|
906
913
|
!isCommit(value.commit_evidence.after) ||
|
|
907
914
|
value.commit_evidence.after === value.commit_evidence.before) {
|
|
908
|
-
return invalidResult("commit_evidence must bind the workload baseline to a distinct full commit id");
|
|
915
|
+
return invalidResult("commit_evidence", "commit_evidence must bind the workload baseline to a distinct full commit id");
|
|
909
916
|
}
|
|
910
917
|
if (!Array.isArray(value.test_evidence) ||
|
|
911
918
|
value.test_evidence.length !== workItem.required_tests.length) {
|
|
912
|
-
return invalidResult("test_evidence must contain exactly one entry for every required test");
|
|
919
|
+
return invalidResult("test_evidence", "test_evidence must contain exactly one entry for every required test");
|
|
913
920
|
}
|
|
914
921
|
for (const [index, evidence] of value.test_evidence.entries()) {
|
|
915
922
|
if (!isRecord(evidence) ||
|
|
916
923
|
!hasExactKeys(evidence, ["command", "status"]) ||
|
|
917
924
|
evidence.command !== workItem.required_tests[index] ||
|
|
918
925
|
evidence.status !== "passed") {
|
|
919
|
-
return invalidResult(`test_evidence[${index}] must echo the bound command with status passed`);
|
|
926
|
+
return invalidResult("test_evidence", `test_evidence[${index}] must echo the bound command with status passed`);
|
|
920
927
|
}
|
|
921
928
|
}
|
|
922
929
|
// The evidence-coverage floor: the cited obligation set must equal the
|
|
@@ -924,7 +931,7 @@ function parseResult(value, runId, workItem, root) {
|
|
|
924
931
|
// whether a citation SUFFICES is the per-run conformance review's job.
|
|
925
932
|
const obligationEvidence = value.obligation_evidence;
|
|
926
933
|
if (!Array.isArray(obligationEvidence)) {
|
|
927
|
-
return invalidResult("obligation_evidence must be an array with one entry per bound obligation");
|
|
934
|
+
return invalidResult("obligation_evidence", "obligation_evidence must be an array with one entry per bound obligation");
|
|
928
935
|
}
|
|
929
936
|
const citedIds = [];
|
|
930
937
|
for (const [index, entry] of obligationEvidence.entries()) {
|
|
@@ -939,7 +946,7 @@ function parseResult(value, runId, workItem, root) {
|
|
|
939
946
|
const named = isRecord(entry) && typeof entry.obligation_id === "string"
|
|
940
947
|
? ` (obligation_id: ${entry.obligation_id})`
|
|
941
948
|
: "";
|
|
942
|
-
return invalidResult(`obligation_evidence[${index}] must cite at least one non-empty evidence string for a named obligation${named}`);
|
|
949
|
+
return invalidResult("obligation_evidence", `obligation_evidence[${index}] must cite at least one non-empty evidence string for a named obligation${named}`);
|
|
943
950
|
}
|
|
944
951
|
citedIds.push(entry.obligation_id);
|
|
945
952
|
}
|
|
@@ -948,24 +955,24 @@ function parseResult(value, runId, workItem, root) {
|
|
|
948
955
|
const duplicates = [
|
|
949
956
|
...new Set(citedIds.filter((id, i) => citedIds.indexOf(id) !== i)),
|
|
950
957
|
];
|
|
951
|
-
return invalidResult(`obligation_evidence cites an obligation more than once: ${duplicates.join(", ")}`);
|
|
958
|
+
return invalidResult("obligation_evidence", `obligation_evidence cites an obligation more than once: ${duplicates.join(", ")}`);
|
|
952
959
|
}
|
|
953
960
|
const uncovered = workItem.obligation_ids.filter((id) => !cited.has(id));
|
|
954
961
|
if (uncovered.length > 0) {
|
|
955
|
-
return invalidResult(`obligation_evidence must cover every prompt-bound obligation; uncovered: ${uncovered.join(", ")}`);
|
|
962
|
+
return invalidResult("obligation_evidence", `obligation_evidence must cover every prompt-bound obligation; uncovered: ${uncovered.join(", ")}`);
|
|
956
963
|
}
|
|
957
964
|
const unknown = citedIds.filter((id) => !workItem.obligation_ids.includes(id));
|
|
958
965
|
if (unknown.length > 0) {
|
|
959
|
-
return invalidResult(`obligation_evidence cites obligations the work item does not bind: ${unknown.join(", ")}`);
|
|
966
|
+
return invalidResult("obligation_evidence", `obligation_evidence cites obligations the work item does not bind: ${unknown.join(", ")}`);
|
|
960
967
|
}
|
|
961
968
|
if (!isRecord(value.worktree_evidence) ||
|
|
962
969
|
!hasExactKeys(value.worktree_evidence, ["baseline_commit", "changed_files"]) ||
|
|
963
970
|
value.worktree_evidence.baseline_commit !== workItem.baseline_commit) {
|
|
964
|
-
return invalidResult("worktree_evidence must bind the workload baseline and changed-file list");
|
|
971
|
+
return invalidResult("worktree_evidence", "worktree_evidence must bind the workload baseline and changed-file list");
|
|
965
972
|
}
|
|
966
973
|
const worktreeFiles = stringArray(value.worktree_evidence.changed_files);
|
|
967
974
|
if (!worktreeFiles || !sameStrings(worktreeFiles, changedFiles)) {
|
|
968
|
-
return invalidResult("worktree_evidence.changed_files must exactly equal changed_files");
|
|
975
|
+
return invalidResult("worktree_evidence", "worktree_evidence.changed_files must exactly equal changed_files");
|
|
969
976
|
}
|
|
970
977
|
if (!isRecord(value.acceptance) ||
|
|
971
978
|
!hasExactKeys(value.acceptance, ["status"]) ||
|
|
@@ -973,7 +980,7 @@ function parseResult(value, runId, workItem, root) {
|
|
|
973
980
|
!isRecord(value.merge) ||
|
|
974
981
|
!hasExactKeys(value.merge, ["status"]) ||
|
|
975
982
|
value.merge.status !== "merged") {
|
|
976
|
-
return invalidResult("acceptance and merge must both attest a completed landing");
|
|
983
|
+
return invalidResult("landing_attestation", "acceptance and merge must both attest a completed landing");
|
|
977
984
|
}
|
|
978
985
|
return {
|
|
979
986
|
ok: true,
|
|
@@ -1136,6 +1143,7 @@ async function corroborateNoChangeClaim(params) {
|
|
|
1136
1143
|
return {
|
|
1137
1144
|
ok: false,
|
|
1138
1145
|
code: "commit_missing",
|
|
1146
|
+
check: "no_change_corroboration",
|
|
1139
1147
|
message: "resolved_no_change cannot be corroborated: baseline_commit does not resolve to a real commit",
|
|
1140
1148
|
};
|
|
1141
1149
|
}
|
|
@@ -1144,6 +1152,7 @@ async function corroborateNoChangeClaim(params) {
|
|
|
1144
1152
|
return {
|
|
1145
1153
|
ok: false,
|
|
1146
1154
|
code: "commit_missing",
|
|
1155
|
+
check: "no_change_corroboration",
|
|
1147
1156
|
message: "resolved_no_change cannot be corroborated: git could not enumerate the changes since the workload baseline",
|
|
1148
1157
|
};
|
|
1149
1158
|
}
|
|
@@ -1154,6 +1163,7 @@ async function corroborateNoChangeClaim(params) {
|
|
|
1154
1163
|
return {
|
|
1155
1164
|
ok: false,
|
|
1156
1165
|
code: "changed_files_mismatch",
|
|
1166
|
+
check: "no_change_corroboration",
|
|
1157
1167
|
message: "resolved_no_change is contradicted by the tree — these files changed since the " +
|
|
1158
1168
|
`workload baseline: ${violating.join(", ")}` +
|
|
1159
1169
|
(outOfScope.length > 0
|
|
@@ -1359,6 +1369,7 @@ function requiredTestIssue(workItem, failures) {
|
|
|
1359
1369
|
: failures.some((failure) => failure.outcome === "output_overflow")
|
|
1360
1370
|
? "required_test_output_overflow"
|
|
1361
1371
|
: "required_test_failed",
|
|
1372
|
+
check: "test_evidence",
|
|
1362
1373
|
work_item_id: workItem.id,
|
|
1363
1374
|
result_path: workItem.result_path,
|
|
1364
1375
|
message: `mechanical required-test rerun failed: ${failures
|
|
@@ -1418,6 +1429,7 @@ async function corroborateHostResult(params) {
|
|
|
1418
1429
|
return {
|
|
1419
1430
|
ok: false,
|
|
1420
1431
|
code: "commit_missing",
|
|
1432
|
+
check: "commit_evidence",
|
|
1421
1433
|
message: "baseline_commit and commit_evidence.after must both resolve to real commits",
|
|
1422
1434
|
};
|
|
1423
1435
|
}
|
|
@@ -1426,6 +1438,7 @@ async function corroborateHostResult(params) {
|
|
|
1426
1438
|
return {
|
|
1427
1439
|
ok: false,
|
|
1428
1440
|
code: "baseline_not_ancestor",
|
|
1441
|
+
check: "commit_evidence",
|
|
1429
1442
|
message: "the trusted workload baseline is not an ancestor of the claimed landed commit",
|
|
1430
1443
|
};
|
|
1431
1444
|
}
|
|
@@ -1442,6 +1455,7 @@ async function corroborateHostResult(params) {
|
|
|
1442
1455
|
return {
|
|
1443
1456
|
ok: false,
|
|
1444
1457
|
code: "baseline_not_ancestor",
|
|
1458
|
+
check: "commit_evidence",
|
|
1445
1459
|
message: "the trusted workload baseline is not an ancestor of the claimed landed commit, " +
|
|
1446
1460
|
"and the baseline is NOT orphaned (a ref still contains it, or it is reachable " +
|
|
1447
1461
|
"from HEAD), so the stale-worker protection stands and recovery cannot waive it",
|
|
@@ -1453,6 +1467,7 @@ async function corroborateHostResult(params) {
|
|
|
1453
1467
|
return {
|
|
1454
1468
|
ok: false,
|
|
1455
1469
|
code: "commit_not_landed",
|
|
1470
|
+
check: "commit_evidence",
|
|
1456
1471
|
message: "commit_evidence.after is not reachable from the repository HEAD",
|
|
1457
1472
|
};
|
|
1458
1473
|
}
|
|
@@ -1461,6 +1476,7 @@ async function corroborateHostResult(params) {
|
|
|
1461
1476
|
return {
|
|
1462
1477
|
ok: false,
|
|
1463
1478
|
code: "changed_files_mismatch",
|
|
1479
|
+
check: "write_scope",
|
|
1464
1480
|
message: "the landed commit's mechanically derived changed files do not exactly match changed_files",
|
|
1465
1481
|
};
|
|
1466
1482
|
}
|
|
@@ -1468,6 +1484,7 @@ async function corroborateHostResult(params) {
|
|
|
1468
1484
|
return {
|
|
1469
1485
|
ok: false,
|
|
1470
1486
|
code: "changed_files_mismatch",
|
|
1487
|
+
check: "write_scope",
|
|
1471
1488
|
message: "the landed commit changed a file outside the prompt-bound allowed_files",
|
|
1472
1489
|
};
|
|
1473
1490
|
}
|
|
@@ -1477,13 +1494,14 @@ async function corroborateHostResult(params) {
|
|
|
1477
1494
|
return {
|
|
1478
1495
|
ok: false,
|
|
1479
1496
|
code: "run_start_dirty_overlap",
|
|
1497
|
+
check: "worktree_evidence",
|
|
1480
1498
|
message: `landed files overlap pre-existing run-start dirt: ${dirtyOverlap.join(", ")}`,
|
|
1481
1499
|
};
|
|
1482
1500
|
}
|
|
1483
1501
|
const failedTests = await rerunRequiredTests(root, workItem.required_tests, verdicts);
|
|
1484
1502
|
if (failedTests.length > 0) {
|
|
1485
1503
|
const issue = requiredTestIssue(workItem, failedTests);
|
|
1486
|
-
return { ok: false, code: issue.code, message: issue.message };
|
|
1504
|
+
return { ok: false, code: issue.code, check: "test_evidence", message: issue.message };
|
|
1487
1505
|
}
|
|
1488
1506
|
return { ok: true, changedFiles: actualFiles, usedRecovery };
|
|
1489
1507
|
}
|
|
@@ -1609,6 +1627,55 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1609
1627
|
return "unsupported_retired_state";
|
|
1610
1628
|
const paths = resolveBoundaryPaths(params);
|
|
1611
1629
|
const nextState = structuredClone(state);
|
|
1630
|
+
const validated = await validateHostResultBundle({
|
|
1631
|
+
state,
|
|
1632
|
+
nextState,
|
|
1633
|
+
paths,
|
|
1634
|
+
runId: params.runId,
|
|
1635
|
+
recovery: params.recovery,
|
|
1636
|
+
});
|
|
1637
|
+
if (validated.kind === "summary") {
|
|
1638
|
+
const issues = await recordAndEnrichHostIssues(params.artifactsDir, params.runId, validated.summary.issues, validated.summary.completed_work_item_ids);
|
|
1639
|
+
return { ...validated.summary, issues };
|
|
1640
|
+
}
|
|
1641
|
+
const acc = {
|
|
1642
|
+
issues: validated.issues,
|
|
1643
|
+
completed: [],
|
|
1644
|
+
resultIds: new Set(),
|
|
1645
|
+
landedFiles: new Set(nextState.applied_edit_surface ?? []),
|
|
1646
|
+
settledFindingIds: new Set(),
|
|
1647
|
+
recordedRecoveryMarks: null,
|
|
1648
|
+
};
|
|
1649
|
+
const verdicts = await executeHostVerificationReruns(validated.ctx, acc);
|
|
1650
|
+
const issues = await recordAndEnrichHostIssues(params.artifactsDir, params.runId, acc.issues, acc.completed);
|
|
1651
|
+
return commitRemediationStateUpdates(validated.ctx, acc, verdicts, issues);
|
|
1652
|
+
}
|
|
1653
|
+
/** Record raw observations first, then decorate only the returned diagnostics. */
|
|
1654
|
+
async function recordAndEnrichHostIssues(artifactsDir, runId, issues, acceptedIds) {
|
|
1655
|
+
const refusals = await readTrailingSubmissionRefusals(artifactsDir, issues
|
|
1656
|
+
.map((issue) => issue.work_item_id ?? issue.submission_id)
|
|
1657
|
+
.filter((id) => id !== undefined), { runId });
|
|
1658
|
+
await recordHostResultOutcomes(artifactsDir, runId, {
|
|
1659
|
+
// This refusal already reports that the ledger write failed. Retrying
|
|
1660
|
+
// that same item would replace its diagnostic with an ingest exception;
|
|
1661
|
+
// other items retain normal recording and error propagation.
|
|
1662
|
+
issues: issues.filter((issue) => issue.code !== "recovery_unrecorded"),
|
|
1663
|
+
acceptedIds,
|
|
1664
|
+
}, { scopeToRunId: runId });
|
|
1665
|
+
return enrichMissingSubmissionIssues(issues, refusals, "submission_rejected");
|
|
1666
|
+
}
|
|
1667
|
+
/**
|
|
1668
|
+
* Phase 1 — the whole-bundle gates, up to the schedulable frontier.
|
|
1669
|
+
*
|
|
1670
|
+
* Returns either a populated context or ONE OF THREE finished summaries. The
|
|
1671
|
+
* three do not agree on `pending_work_item_ids` — the read failure and the
|
|
1672
|
+
* canonical parse failure return the binding's own item ids, the trusted-binding
|
|
1673
|
+
* refusal returns the empty list — so folding any two together is a silent
|
|
1674
|
+
* behavior change. Each is pinned by a test that asserts the pending list, not
|
|
1675
|
+
* just the code.
|
|
1676
|
+
*/
|
|
1677
|
+
async function validateHostResultBundle(input) {
|
|
1678
|
+
const { state, nextState, paths } = input;
|
|
1612
1679
|
const issues = [];
|
|
1613
1680
|
const workloadRead = await readSubmissionDocument(paths.workloadPath);
|
|
1614
1681
|
if (workloadRead.kind !== "value") {
|
|
@@ -1617,18 +1684,22 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1617
1684
|
code: workloadRead.kind === "missing"
|
|
1618
1685
|
? "workload_missing"
|
|
1619
1686
|
: "workload_invalid",
|
|
1687
|
+
check: "workload_binding",
|
|
1620
1688
|
message: workloadRead.kind === "missing"
|
|
1621
1689
|
? "the persisted trusted handoff has no workload file"
|
|
1622
1690
|
: `the workload file is not valid JSON: ${workloadRead.detail}`,
|
|
1623
1691
|
});
|
|
1624
1692
|
}
|
|
1625
1693
|
return {
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1694
|
+
kind: "summary",
|
|
1695
|
+
summary: {
|
|
1696
|
+
accepted_count: 0,
|
|
1697
|
+
completed_work_item_ids: [],
|
|
1698
|
+
pending_work_item_ids: state.host_handoff?.work_item_ids ?? [],
|
|
1699
|
+
issues,
|
|
1700
|
+
state_changed: false,
|
|
1701
|
+
state: nextState,
|
|
1702
|
+
},
|
|
1632
1703
|
};
|
|
1633
1704
|
}
|
|
1634
1705
|
// Producer-side plan defects are reported BEFORE the workload is parsed: a
|
|
@@ -1648,62 +1719,85 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1648
1719
|
if ((await isGitRepo(paths.root)) && !state.host_handoff) {
|
|
1649
1720
|
issues.push({
|
|
1650
1721
|
code: "trusted_binding_missing",
|
|
1722
|
+
check: "workload_binding",
|
|
1651
1723
|
message: "a git-backed remediation workload requires the tool-owned host_handoff state binding",
|
|
1652
1724
|
});
|
|
1653
1725
|
return {
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1726
|
+
kind: "summary",
|
|
1727
|
+
summary: {
|
|
1728
|
+
accepted_count: 0,
|
|
1729
|
+
completed_work_item_ids: [],
|
|
1730
|
+
pending_work_item_ids: [],
|
|
1731
|
+
issues,
|
|
1732
|
+
state_changed: false,
|
|
1733
|
+
state: nextState,
|
|
1734
|
+
},
|
|
1660
1735
|
};
|
|
1661
1736
|
}
|
|
1662
|
-
const workload = parseWorkload(workloadRead.value, paths,
|
|
1737
|
+
const workload = parseWorkload(workloadRead.value, paths, input.runId, state);
|
|
1663
1738
|
if (!workload) {
|
|
1664
1739
|
// Accumulated, not replaced: when a block-contract defect is WHY the
|
|
1665
1740
|
// canonical re-derivation failed, the block-attributed issue is the only
|
|
1666
1741
|
// thing that names the cause.
|
|
1667
1742
|
issues.push({
|
|
1668
1743
|
code: "workload_invalid",
|
|
1744
|
+
check: "workload_binding",
|
|
1669
1745
|
message: "the workload does not match its canonical state shape and persisted digest binding",
|
|
1670
1746
|
});
|
|
1671
1747
|
return {
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1748
|
+
kind: "summary",
|
|
1749
|
+
summary: {
|
|
1750
|
+
accepted_count: 0,
|
|
1751
|
+
completed_work_item_ids: [],
|
|
1752
|
+
pending_work_item_ids: state.host_handoff?.work_item_ids ?? [],
|
|
1753
|
+
issues,
|
|
1754
|
+
state_changed: false,
|
|
1755
|
+
state: nextState,
|
|
1756
|
+
},
|
|
1678
1757
|
};
|
|
1679
1758
|
}
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1759
|
+
return {
|
|
1760
|
+
kind: "context",
|
|
1761
|
+
issues,
|
|
1762
|
+
ctx: {
|
|
1763
|
+
paths,
|
|
1764
|
+
runId: input.runId,
|
|
1765
|
+
recovery: input.recovery !== undefined,
|
|
1766
|
+
state,
|
|
1767
|
+
nextState,
|
|
1768
|
+
effectiveWorkload: effectiveBoundWorkload(state, workload),
|
|
1769
|
+
eligibleIds: new Set((hostDependencyLevels(state)[0] ?? []).map((block) => block.block_id)),
|
|
1770
|
+
// Can this ingest be corroborated against ground truth AT ALL? A git root
|
|
1771
|
+
// supplies the tree; a persisted `host_handoff` supplies the trusted
|
|
1772
|
+
// binding. With NEITHER there is nothing to check a host's claim against,
|
|
1773
|
+
// and the remaining evidence is the host's own attestation — which is
|
|
1774
|
+
// exactly the claim under test. That branch is REFUSED for both result
|
|
1775
|
+
// and decision documents rather than admitted on the attestation alone.
|
|
1776
|
+
canCorroborate: state.host_handoff !== undefined || (await isGitRepo(paths.root)),
|
|
1777
|
+
// Recovery-only answer table; the normal lane gets null and spawns
|
|
1778
|
+
// exactly as it always has. See RemediationRequiredTestVerdicts.
|
|
1779
|
+
requiredTestVerdicts: input.recovery?.requiredTestVerdicts ?? null,
|
|
1780
|
+
},
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
/**
|
|
1784
|
+
* Phase 2 — per-item verification. Writes NOTHING to `ctx.nextState`.
|
|
1785
|
+
*
|
|
1786
|
+
* Iterates the effective workload in order and emits one verdict per ACCEPTED
|
|
1787
|
+
* item; a refusal pushes its classified issue and continues. The ledger mark
|
|
1788
|
+
* for a recovery acceptance still goes down before that item's verdict is
|
|
1789
|
+
* emitted, so no acceptance can outrun its record.
|
|
1790
|
+
*/
|
|
1791
|
+
async function executeHostVerificationReruns(ctx, acc) {
|
|
1792
|
+
const { paths, nextState, state } = ctx;
|
|
1793
|
+
const verdicts = [];
|
|
1794
|
+
for (const workItem of ctx.effectiveWorkload.work_items) {
|
|
1795
|
+
const pendingItems = workItem.finding_ids.filter((findingId) => nextState.items[findingId]?.status === "pending" &&
|
|
1796
|
+
!acc.settledFindingIds.has(findingId));
|
|
1703
1797
|
if (pendingItems.length === 0)
|
|
1704
1798
|
continue;
|
|
1705
|
-
if (!eligibleIds.has(workItem.id)) {
|
|
1706
|
-
issues.push({
|
|
1799
|
+
if (!ctx.eligibleIds.has(workItem.id)) {
|
|
1800
|
+
acc.issues.push({
|
|
1707
1801
|
code: "submission_contract_invalid",
|
|
1708
1802
|
work_item_id: workItem.id,
|
|
1709
1803
|
result_path: workItem.result_path,
|
|
@@ -1717,29 +1811,30 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1717
1811
|
workItemId: workItem.id,
|
|
1718
1812
|
resultPath: workItem.result_path,
|
|
1719
1813
|
parse: (value) => {
|
|
1720
|
-
const result = parseResult(value,
|
|
1814
|
+
const result = parseResult(value, ctx.runId, workItem, paths.root);
|
|
1721
1815
|
return result.ok
|
|
1722
1816
|
? { ok: true, parsed: result }
|
|
1723
|
-
: { ok: false, detail: result.reason };
|
|
1817
|
+
: { ok: false, check: result.check, detail: result.reason };
|
|
1724
1818
|
},
|
|
1725
1819
|
resultId: (result) => result.result.result_id,
|
|
1726
|
-
seen: (resultId) => resultIds.has(resultId),
|
|
1820
|
+
seen: (resultId) => acc.resultIds.has(resultId),
|
|
1727
1821
|
messages: remediationScanMessages,
|
|
1728
1822
|
});
|
|
1729
1823
|
if (!scan.ok) {
|
|
1730
|
-
issues.push(scan.issue);
|
|
1824
|
+
acc.issues.push(scan.issue);
|
|
1731
1825
|
continue;
|
|
1732
1826
|
}
|
|
1733
1827
|
const parsed = scan.parsed;
|
|
1734
1828
|
const resultId = parsed.result.result_id;
|
|
1735
|
-
resultIds.add(resultId);
|
|
1829
|
+
acc.resultIds.add(resultId);
|
|
1736
1830
|
if (parsed.kind === "decision") {
|
|
1737
1831
|
const result = parsed.result;
|
|
1738
1832
|
const outcome = result.outcome;
|
|
1739
1833
|
if (outcome.status === "resolved_no_change") {
|
|
1740
|
-
if (!canCorroborate) {
|
|
1741
|
-
issues.push({
|
|
1834
|
+
if (!ctx.canCorroborate) {
|
|
1835
|
+
acc.issues.push({
|
|
1742
1836
|
code: "trusted_binding_missing",
|
|
1837
|
+
check: "no_change_corroboration",
|
|
1743
1838
|
work_item_id: workItem.id,
|
|
1744
1839
|
result_path: workItem.result_path,
|
|
1745
1840
|
message: "resolved_no_change needs a git root or a persisted host_handoff binding to corroborate the write scope against; attestation-only acceptance is refused",
|
|
@@ -1754,63 +1849,42 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1754
1849
|
// `applied_edit_surface` and grows as this same ingest accepts).
|
|
1755
1850
|
excusedPaths: new Set([
|
|
1756
1851
|
...(state.run_start_dirty ?? []).map(normalizeRepoPath),
|
|
1757
|
-
...[...landedFiles].map(normalizeRepoPath),
|
|
1852
|
+
...[...acc.landedFiles].map(normalizeRepoPath),
|
|
1758
1853
|
]),
|
|
1759
1854
|
});
|
|
1760
1855
|
if (!noChange.ok) {
|
|
1761
|
-
issues.push({
|
|
1856
|
+
acc.issues.push({
|
|
1762
1857
|
code: noChange.code,
|
|
1858
|
+
check: noChange.check,
|
|
1763
1859
|
work_item_id: workItem.id,
|
|
1764
1860
|
result_path: workItem.result_path,
|
|
1765
1861
|
message: noChange.message,
|
|
1766
1862
|
});
|
|
1767
1863
|
continue;
|
|
1768
1864
|
}
|
|
1769
|
-
const failedTests = await rerunRequiredTests(paths.root, workItem.required_tests, requiredTestVerdicts);
|
|
1865
|
+
const failedTests = await rerunRequiredTests(paths.root, workItem.required_tests, ctx.requiredTestVerdicts);
|
|
1770
1866
|
if (failedTests.length > 0) {
|
|
1771
|
-
issues.push(requiredTestIssue(workItem, failedTests));
|
|
1867
|
+
acc.issues.push(requiredTestIssue(workItem, failedTests));
|
|
1772
1868
|
continue;
|
|
1773
1869
|
}
|
|
1774
1870
|
}
|
|
1775
|
-
const
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
else if (outcome.status === "blocked") {
|
|
1786
|
-
item.status = "blocked";
|
|
1787
|
-
item.completed_at = now;
|
|
1788
|
-
item.failure_reason = outcome.failure_reason;
|
|
1789
|
-
}
|
|
1790
|
-
else {
|
|
1791
|
-
item.status = "needs_clarification";
|
|
1792
|
-
delete item.completed_at;
|
|
1793
|
-
item.failure_reason = outcome.question;
|
|
1794
|
-
const clarifications = nextState.clarifications ?? [];
|
|
1795
|
-
if (!clarifications.some((entry) => entry.finding_id === findingId)) {
|
|
1796
|
-
clarifications.push({
|
|
1797
|
-
finding_id: findingId,
|
|
1798
|
-
category: isClarificationCategory(outcome.category)
|
|
1799
|
-
? outcome.category
|
|
1800
|
-
: "scope_of_fix",
|
|
1801
|
-
description: outcome.question,
|
|
1802
|
-
});
|
|
1803
|
-
}
|
|
1804
|
-
nextState.clarifications = clarifications;
|
|
1805
|
-
}
|
|
1806
|
-
}
|
|
1807
|
-
completed.push(workItem.id);
|
|
1871
|
+
for (const findingId of pendingItems)
|
|
1872
|
+
acc.settledFindingIds.add(findingId);
|
|
1873
|
+
verdicts.push({
|
|
1874
|
+
kind: "decision",
|
|
1875
|
+
workItem,
|
|
1876
|
+
pendingItems,
|
|
1877
|
+
at: new Date().toISOString(),
|
|
1878
|
+
outcome,
|
|
1879
|
+
});
|
|
1880
|
+
acc.completed.push(workItem.id);
|
|
1808
1881
|
continue;
|
|
1809
1882
|
}
|
|
1810
1883
|
const result = parsed.result;
|
|
1811
|
-
if (!canCorroborate) {
|
|
1812
|
-
issues.push({
|
|
1884
|
+
if (!ctx.canCorroborate) {
|
|
1885
|
+
acc.issues.push({
|
|
1813
1886
|
code: "trusted_binding_missing",
|
|
1887
|
+
check: "workload_binding",
|
|
1814
1888
|
work_item_id: workItem.id,
|
|
1815
1889
|
result_path: workItem.result_path,
|
|
1816
1890
|
message: "a landed result needs a git root or a persisted host_handoff binding to corroborate the write scope against; attestation-only acceptance is refused",
|
|
@@ -1822,12 +1896,13 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1822
1896
|
state,
|
|
1823
1897
|
workItem,
|
|
1824
1898
|
result,
|
|
1825
|
-
verdicts: requiredTestVerdicts,
|
|
1826
|
-
recovery:
|
|
1899
|
+
verdicts: ctx.requiredTestVerdicts,
|
|
1900
|
+
recovery: ctx.recovery,
|
|
1827
1901
|
});
|
|
1828
1902
|
if (!corroborated.ok) {
|
|
1829
|
-
issues.push({
|
|
1903
|
+
acc.issues.push({
|
|
1830
1904
|
code: corroborated.code,
|
|
1905
|
+
check: corroborated.check,
|
|
1831
1906
|
work_item_id: workItem.id,
|
|
1832
1907
|
result_path: workItem.result_path,
|
|
1833
1908
|
message: corroborated.message,
|
|
@@ -1841,7 +1916,7 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1841
1916
|
// must never read as one that never drifted. The refusal is per item:
|
|
1842
1917
|
// an unwritable ledger is not a reason to discard the whole ingest.
|
|
1843
1918
|
try {
|
|
1844
|
-
recordedRecoveryMarks ??= (await readSubmissionLedger(paths.artifactsDir)).filter((event) => event.kind === "accepted_via_recovery");
|
|
1919
|
+
acc.recordedRecoveryMarks ??= (await readSubmissionLedger(paths.artifactsDir)).filter((event) => event.kind === "accepted_via_recovery");
|
|
1845
1920
|
// The mark's identity is (run, item, LANDED COMMIT), not just
|
|
1846
1921
|
// (run, item): an item re-opened and later re-accepted from a
|
|
1847
1922
|
// DIFFERENT landing is a different relaxed acceptance and earns its
|
|
@@ -1850,13 +1925,13 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1850
1925
|
// contract carries no commit field, and a 40-hex sha this writer
|
|
1851
1926
|
// itself emitted is an unambiguous token to match on.
|
|
1852
1927
|
const landedCommit = result.commit_evidence.after;
|
|
1853
|
-
const alreadyMarked = recordedRecoveryMarks.some((event) => event.run_id ===
|
|
1928
|
+
const alreadyMarked = acc.recordedRecoveryMarks.some((event) => event.run_id === ctx.runId &&
|
|
1854
1929
|
event.submission_id === workItem.id &&
|
|
1855
1930
|
(event.message ?? "").includes(landedCommit));
|
|
1856
1931
|
if (!alreadyMarked) {
|
|
1857
1932
|
const event = {
|
|
1858
1933
|
contract_version: SUBMISSION_LEDGER_EVENT_CONTRACT_VERSION,
|
|
1859
|
-
run_id:
|
|
1934
|
+
run_id: ctx.runId,
|
|
1860
1935
|
submission_id: workItem.id,
|
|
1861
1936
|
lane: workItem.id,
|
|
1862
1937
|
kind: "accepted_via_recovery",
|
|
@@ -1869,11 +1944,11 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1869
1944
|
recorded_at: new Date().toISOString(),
|
|
1870
1945
|
};
|
|
1871
1946
|
await appendSubmissionEvent(paths.artifactsDir, event);
|
|
1872
|
-
recordedRecoveryMarks.push(event);
|
|
1947
|
+
acc.recordedRecoveryMarks.push(event);
|
|
1873
1948
|
}
|
|
1874
1949
|
}
|
|
1875
1950
|
catch (error) {
|
|
1876
|
-
issues.push({
|
|
1951
|
+
acc.issues.push({
|
|
1877
1952
|
code: "recovery_unrecorded",
|
|
1878
1953
|
work_item_id: workItem.id,
|
|
1879
1954
|
result_path: workItem.result_path,
|
|
@@ -1883,35 +1958,91 @@ export async function ingestRemediationHostResults(params) {
|
|
|
1883
1958
|
continue;
|
|
1884
1959
|
}
|
|
1885
1960
|
}
|
|
1886
|
-
const
|
|
1887
|
-
|
|
1888
|
-
|
|
1961
|
+
for (const findingId of pendingItems)
|
|
1962
|
+
acc.settledFindingIds.add(findingId);
|
|
1963
|
+
verdicts.push({
|
|
1964
|
+
kind: "landed",
|
|
1965
|
+
workItem,
|
|
1966
|
+
pendingItems,
|
|
1967
|
+
at: new Date().toISOString(),
|
|
1968
|
+
});
|
|
1969
|
+
for (const changedFile of corroborated.changedFiles) {
|
|
1970
|
+
acc.landedFiles.add(changedFile);
|
|
1971
|
+
}
|
|
1972
|
+
acc.completed.push(workItem.id);
|
|
1973
|
+
}
|
|
1974
|
+
return verdicts;
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Phase 3 — apply the accepted verdicts to the clone and assemble the summary.
|
|
1978
|
+
*
|
|
1979
|
+
* Infallible given the verdicts: every refusal was already classified in
|
|
1980
|
+
* phase 2, so nothing here can reject. Verdicts apply in workload order, which
|
|
1981
|
+
* is the order they were emitted, so a finding two items share is written the
|
|
1982
|
+
* same way it was before the phases were separated.
|
|
1983
|
+
*/
|
|
1984
|
+
function commitRemediationStateUpdates(ctx, acc, verdicts, issues) {
|
|
1985
|
+
const { nextState } = ctx;
|
|
1986
|
+
for (const verdict of verdicts) {
|
|
1987
|
+
if (verdict.kind === "decision") {
|
|
1988
|
+
const outcome = verdict.outcome;
|
|
1989
|
+
for (const findingId of verdict.pendingItems) {
|
|
1990
|
+
const item = nextState.items[findingId];
|
|
1991
|
+
item.started_at ??= verdict.at;
|
|
1992
|
+
if (outcome.status === "resolved_no_change") {
|
|
1993
|
+
item.status = "resolved_no_change";
|
|
1994
|
+
item.completed_at = verdict.at;
|
|
1995
|
+
item.host_result_evidence = [...outcome.evidence];
|
|
1996
|
+
delete item.failure_reason;
|
|
1997
|
+
}
|
|
1998
|
+
else if (outcome.status === "blocked") {
|
|
1999
|
+
item.status = "blocked";
|
|
2000
|
+
item.completed_at = verdict.at;
|
|
2001
|
+
item.failure_reason = outcome.failure_reason;
|
|
2002
|
+
}
|
|
2003
|
+
else {
|
|
2004
|
+
item.status = "needs_clarification";
|
|
2005
|
+
delete item.completed_at;
|
|
2006
|
+
item.failure_reason = outcome.question;
|
|
2007
|
+
const clarifications = nextState.clarifications ?? [];
|
|
2008
|
+
if (!clarifications.some((entry) => entry.finding_id === findingId)) {
|
|
2009
|
+
clarifications.push({
|
|
2010
|
+
finding_id: findingId,
|
|
2011
|
+
category: isClarificationCategory(outcome.category)
|
|
2012
|
+
? outcome.category
|
|
2013
|
+
: "scope_of_fix",
|
|
2014
|
+
description: outcome.question,
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
nextState.clarifications = clarifications;
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
continue;
|
|
2021
|
+
}
|
|
2022
|
+
for (const findingId of verdict.pendingItems) {
|
|
1889
2023
|
const item = nextState.items[findingId];
|
|
1890
2024
|
item.status = "resolved";
|
|
1891
|
-
item.started_at ??=
|
|
1892
|
-
item.completed_at =
|
|
2025
|
+
item.started_at ??= verdict.at;
|
|
2026
|
+
item.completed_at = verdict.at;
|
|
1893
2027
|
delete item.failure_reason;
|
|
1894
2028
|
delete item.host_result_evidence;
|
|
1895
2029
|
}
|
|
1896
|
-
for (const changedFile of acceptedFiles)
|
|
1897
|
-
landedFiles.add(changedFile);
|
|
1898
|
-
completed.push(workItem.id);
|
|
1899
2030
|
}
|
|
1900
|
-
if (completed.length > 0) {
|
|
1901
|
-
nextState.applied_edit_surface = [...landedFiles].sort(compareCodeUnits);
|
|
2031
|
+
if (acc.completed.length > 0) {
|
|
2032
|
+
nextState.applied_edit_surface = [...acc.landedFiles].sort(compareCodeUnits);
|
|
1902
2033
|
}
|
|
1903
|
-
const pendingWorkItemIds = effectiveWorkload.work_items
|
|
2034
|
+
const pendingWorkItemIds = ctx.effectiveWorkload.work_items
|
|
1904
2035
|
.filter((workItem) => workItem.finding_ids.some((findingId) => nextState.items[findingId]?.status === "pending"))
|
|
1905
2036
|
.map((workItem) => workItem.id);
|
|
1906
|
-
let stateChanged = completed.length > 0;
|
|
2037
|
+
let stateChanged = acc.completed.length > 0;
|
|
1907
2038
|
if (nextState.host_handoff && pendingWorkItemIds.length === 0) {
|
|
1908
2039
|
migrateLegacyDirectoryScopesAfterFinalDrain(nextState);
|
|
1909
2040
|
delete nextState.host_handoff;
|
|
1910
2041
|
stateChanged = true;
|
|
1911
2042
|
}
|
|
1912
2043
|
return {
|
|
1913
|
-
accepted_count: completed.length,
|
|
1914
|
-
completed_work_item_ids: completed,
|
|
2044
|
+
accepted_count: acc.completed.length,
|
|
2045
|
+
completed_work_item_ids: acc.completed,
|
|
1915
2046
|
pending_work_item_ids: pendingWorkItemIds,
|
|
1916
2047
|
issues,
|
|
1917
2048
|
state_changed: stateChanged,
|