audit-tools 0.52.5 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit/cli/auditStep.d.ts +1 -1
- package/dist/audit/cli/conceptualDispatch.d.ts +2 -2
- package/dist/audit/cli/conceptualDispatch.d.ts.map +1 -1
- package/dist/audit/cli/conceptualDispatch.js +6 -5
- package/dist/audit/cli/conceptualDispatch.js.map +1 -1
- package/dist/audit/cli/confirmIntentStep.d.ts.map +1 -1
- package/dist/audit/cli/confirmIntentStep.js +3 -16
- package/dist/audit/cli/confirmIntentStep.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 +22 -1
- package/dist/audit/cli/dispatch/hostHandoff.js.map +1 -1
- package/dist/audit/cli/dispatch/packetFilter.d.ts +1 -1
- package/dist/audit/cli/dispatch/packetFilter.d.ts.map +1 -1
- package/dist/audit/cli/dispatch/packetFilter.js +1 -1
- package/dist/audit/cli/dispatch/packetFilter.js.map +1 -1
- package/dist/audit/cli/functionalPreflight.d.ts.map +1 -1
- package/dist/audit/cli/functionalPreflight.js +6 -3
- package/dist/audit/cli/functionalPreflight.js.map +1 -1
- package/dist/audit/cli/nextStepCommand.d.ts.map +1 -1
- package/dist/audit/cli/nextStepCommand.js +57 -34
- package/dist/audit/cli/nextStepCommand.js.map +1 -1
- package/dist/audit/cli/nextStepHelpers.d.ts +3 -3
- package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
- package/dist/audit/cli/nextStepHelpers.js +52 -77
- package/dist/audit/cli/nextStepHelpers.js.map +1 -1
- package/dist/audit/cli/prompts.d.ts +1 -2
- package/dist/audit/cli/prompts.d.ts.map +1 -1
- package/dist/audit/cli/prompts.js +2 -12
- package/dist/audit/cli/prompts.js.map +1 -1
- package/dist/audit/cli/sampleRunCommand.d.ts +2 -2
- package/dist/audit/cli/semanticReviewStep.d.ts +11 -2
- package/dist/audit/cli/semanticReviewStep.d.ts.map +1 -1
- package/dist/audit/cli/semanticReviewStep.js +14 -10
- package/dist/audit/cli/semanticReviewStep.js.map +1 -1
- package/dist/audit/contracts/workerSchemas.d.ts +14 -14
- package/dist/audit/contracts/wrapperResponse.d.ts +6 -6
- package/dist/audit/extractors/graphRoutes.d.ts.map +1 -1
- package/dist/audit/extractors/graphRoutes.js +1 -3
- package/dist/audit/extractors/graphRoutes.js.map +1 -1
- package/dist/audit/io/artifacts.d.ts.map +1 -1
- package/dist/audit/io/artifacts.js +2 -3
- package/dist/audit/io/artifacts.js.map +1 -1
- package/dist/audit/orchestrator/advance.d.ts.map +1 -1
- package/dist/audit/orchestrator/advance.js +21 -1
- package/dist/audit/orchestrator/advance.js.map +1 -1
- package/dist/audit/orchestrator/architectureDiscovery.d.ts +25 -0
- package/dist/audit/orchestrator/architectureDiscovery.d.ts.map +1 -0
- package/dist/audit/orchestrator/architectureDiscovery.js +193 -0
- package/dist/audit/orchestrator/architectureDiscovery.js.map +1 -0
- package/dist/audit/orchestrator/dependencyMap.d.ts +20 -0
- package/dist/audit/orchestrator/dependencyMap.d.ts.map +1 -1
- package/dist/audit/orchestrator/dependencyMap.js +47 -0
- package/dist/audit/orchestrator/dependencyMap.js.map +1 -1
- package/dist/audit/orchestrator/dependencySlices.d.ts.map +1 -1
- package/dist/audit/orchestrator/dependencySlices.js +37 -3
- package/dist/audit/orchestrator/dependencySlices.js.map +1 -1
- package/dist/audit/orchestrator/designReviewProjection.d.ts +2 -6
- package/dist/audit/orchestrator/designReviewProjection.d.ts.map +1 -1
- package/dist/audit/orchestrator/designReviewProjection.js +2 -6
- package/dist/audit/orchestrator/designReviewProjection.js.map +1 -1
- package/dist/audit/orchestrator/designReviewPrompt.d.ts +2 -2
- package/dist/audit/orchestrator/designReviewPrompt.js +2 -2
- package/dist/audit/orchestrator/designReviewSnapshot.d.ts +2 -3
- package/dist/audit/orchestrator/designReviewSnapshot.d.ts.map +1 -1
- package/dist/audit/orchestrator/designReviewSnapshot.js +2 -3
- package/dist/audit/orchestrator/designReviewSnapshot.js.map +1 -1
- package/dist/audit/orchestrator/executorRunners.d.ts.map +1 -1
- package/dist/audit/orchestrator/executorRunners.js +1 -22
- package/dist/audit/orchestrator/executorRunners.js.map +1 -1
- package/dist/audit/orchestrator/executors.d.ts.map +1 -1
- package/dist/audit/orchestrator/executors.js +0 -12
- package/dist/audit/orchestrator/executors.js.map +1 -1
- package/dist/audit/orchestrator/ingestionExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/ingestionExecutors.js +38 -37
- package/dist/audit/orchestrator/ingestionExecutors.js.map +1 -1
- package/dist/audit/orchestrator/nextStep.d.ts +2 -28
- package/dist/audit/orchestrator/nextStep.d.ts.map +1 -1
- package/dist/audit/orchestrator/nextStep.js +4 -37
- package/dist/audit/orchestrator/nextStep.js.map +1 -1
- package/dist/audit/orchestrator/obligationDerive.d.ts +2 -3
- package/dist/audit/orchestrator/obligationDerive.d.ts.map +1 -1
- package/dist/audit/orchestrator/obligationDerive.js +2 -3
- package/dist/audit/orchestrator/obligationDerive.js.map +1 -1
- package/dist/audit/orchestrator/pendingTasks.d.ts +2 -0
- package/dist/audit/orchestrator/pendingTasks.d.ts.map +1 -1
- package/dist/audit/orchestrator/pendingTasks.js +5 -1
- package/dist/audit/orchestrator/pendingTasks.js.map +1 -1
- package/dist/audit/orchestrator/planningExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/planningExecutors.js +9 -0
- package/dist/audit/orchestrator/planningExecutors.js.map +1 -1
- package/dist/audit/orchestrator/requeueCommand.d.ts +1 -1
- package/dist/audit/orchestrator/resultBaseline.d.ts +5 -5
- package/dist/audit/orchestrator/resultBaseline.d.ts.map +1 -1
- package/dist/audit/orchestrator/resultBaseline.js +24 -47
- package/dist/audit/orchestrator/resultBaseline.js.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.d.ts.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.js +2 -0
- package/dist/audit/orchestrator/selectiveDeepening/findingFollowup.js.map +1 -1
- package/dist/audit/orchestrator/staleness.d.ts.map +1 -1
- package/dist/audit/orchestrator/staleness.js +14 -10
- package/dist/audit/orchestrator/staleness.js.map +1 -1
- package/dist/audit/orchestrator/state.js +1 -1
- package/dist/audit/orchestrator/state.js.map +1 -1
- package/dist/audit/orchestrator/synthesisExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/synthesisExecutors.js +3 -0
- package/dist/audit/orchestrator/synthesisExecutors.js.map +1 -1
- package/dist/audit/types/auditState.d.ts +6 -6
- package/dist/audit/types/flowCoverage.d.ts +6 -6
- package/dist/audit/types.d.ts +24 -13
- package/dist/audit/types.d.ts.map +1 -1
- package/dist/audit/types.js +92 -11
- package/dist/audit/types.js.map +1 -1
- package/dist/remediate/contractPipeline/executionPlan.d.ts +1908 -0
- package/dist/remediate/contractPipeline/executionPlan.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/executionPlan.js +467 -0
- package/dist/remediate/contractPipeline/executionPlan.js.map +1 -0
- package/dist/remediate/contractPipeline/runtimePlanAuthority.d.ts +12 -0
- package/dist/remediate/contractPipeline/runtimePlanAuthority.d.ts.map +1 -0
- package/dist/remediate/contractPipeline/runtimePlanAuthority.js +41 -0
- package/dist/remediate/contractPipeline/runtimePlanAuthority.js.map +1 -0
- package/dist/remediate/dedup/crossLensDedup.d.ts +3 -16
- package/dist/remediate/dedup/crossLensDedup.d.ts.map +1 -1
- package/dist/remediate/dedup/crossLensDedup.js +2 -32
- package/dist/remediate/dedup/crossLensDedup.js.map +1 -1
- package/dist/remediate/index.d.ts +2 -19
- package/dist/remediate/index.d.ts.map +1 -1
- package/dist/remediate/index.js +22 -138
- package/dist/remediate/index.js.map +1 -1
- package/dist/remediate/intake.d.ts +10 -10
- package/dist/remediate/intent/intentOrdering.d.ts +6 -8
- package/dist/remediate/intent/intentOrdering.d.ts.map +1 -1
- package/dist/remediate/intent/intentOrdering.js +24 -47
- package/dist/remediate/intent/intentOrdering.js.map +1 -1
- package/dist/remediate/phases/close.d.ts +25 -17
- package/dist/remediate/phases/close.d.ts.map +1 -1
- package/dist/remediate/phases/close.js +278 -218
- package/dist/remediate/phases/close.js.map +1 -1
- package/dist/remediate/phases/closeAcceptance.d.ts +42 -0
- package/dist/remediate/phases/closeAcceptance.d.ts.map +1 -0
- package/dist/remediate/phases/closeAcceptance.js +66 -0
- package/dist/remediate/phases/closeAcceptance.js.map +1 -0
- package/dist/remediate/phases/closeReviewProvenance.d.ts +1 -1
- package/dist/remediate/phases/closeReviewProvenance.d.ts.map +1 -1
- package/dist/remediate/phases/closeReviewProvenance.js +9 -8
- package/dist/remediate/phases/closeReviewProvenance.js.map +1 -1
- package/dist/remediate/phases/closeVerifyAnalyzerLeads.d.ts.map +1 -1
- package/dist/remediate/phases/closeVerifyAnalyzerLeads.js +11 -9
- package/dist/remediate/phases/closeVerifyAnalyzerLeads.js.map +1 -1
- package/dist/remediate/phases/closeVerifyHeadEvidence.d.ts +21 -86
- package/dist/remediate/phases/closeVerifyHeadEvidence.d.ts.map +1 -1
- package/dist/remediate/phases/closeVerifyHeadEvidence.js +30 -19
- package/dist/remediate/phases/closeVerifyHeadEvidence.js.map +1 -1
- package/dist/remediate/phases/plan.d.ts +3 -60
- package/dist/remediate/phases/plan.d.ts.map +1 -1
- package/dist/remediate/phases/plan.js +3 -227
- package/dist/remediate/phases/plan.js.map +1 -1
- package/dist/remediate/phases/triage.d.ts.map +1 -1
- package/dist/remediate/phases/triage.js +19 -30
- package/dist/remediate/phases/triage.js.map +1 -1
- package/dist/remediate/riskSignal.d.ts +9 -43
- package/dist/remediate/riskSignal.d.ts.map +1 -1
- package/dist/remediate/riskSignal.js +7 -28
- package/dist/remediate/riskSignal.js.map +1 -1
- package/dist/remediate/state/disposition.d.ts +2 -1
- package/dist/remediate/state/disposition.d.ts.map +1 -1
- package/dist/remediate/state/disposition.js +37 -1
- package/dist/remediate/state/disposition.js.map +1 -1
- package/dist/remediate/state/runIdentity.d.ts +2 -13
- package/dist/remediate/state/runIdentity.d.ts.map +1 -1
- package/dist/remediate/state/runIdentity.js +3 -13
- package/dist/remediate/state/runIdentity.js.map +1 -1
- package/dist/remediate/state/store.d.ts +12 -36
- package/dist/remediate/state/store.d.ts.map +1 -1
- package/dist/remediate/state/store.js +58 -150
- package/dist/remediate/state/store.js.map +1 -1
- package/dist/remediate/state/types.d.ts +406 -504
- package/dist/remediate/state/types.d.ts.map +1 -1
- package/dist/remediate/state/types.js +24 -104
- package/dist/remediate/state/types.js.map +1 -1
- package/dist/remediate/steps/contractPipeline.d.ts +7 -661
- package/dist/remediate/steps/contractPipeline.d.ts.map +1 -1
- package/dist/remediate/steps/contractPipeline.js +264 -3851
- package/dist/remediate/steps/contractPipeline.js.map +1 -1
- package/dist/remediate/steps/contractPipelinePrompts.d.ts +20 -142
- package/dist/remediate/steps/contractPipelinePrompts.d.ts.map +1 -1
- package/dist/remediate/steps/contractPipelinePrompts.js +48 -581
- package/dist/remediate/steps/contractPipelinePrompts.js.map +1 -1
- package/dist/remediate/steps/dispatch/contractConformanceReview.d.ts +4 -1
- package/dist/remediate/steps/dispatch/contractConformanceReview.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch/contractConformanceReview.js +6 -3
- package/dist/remediate/steps/dispatch/contractConformanceReview.js.map +1 -1
- package/dist/remediate/steps/dispatch/hostContracts.d.ts +1 -1
- package/dist/remediate/steps/dispatch/hostContracts.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch/hostHandoff.d.ts +4 -21
- package/dist/remediate/steps/dispatch/hostHandoff.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch/hostHandoff.js +161 -383
- package/dist/remediate/steps/dispatch/hostHandoff.js.map +1 -1
- package/dist/remediate/steps/finalGate.d.ts +34 -0
- package/dist/remediate/steps/finalGate.d.ts.map +1 -1
- package/dist/remediate/steps/finalGate.js +44 -4
- package/dist/remediate/steps/finalGate.js.map +1 -1
- package/dist/remediate/steps/frictionCloseout.d.ts +1 -30
- package/dist/remediate/steps/frictionCloseout.d.ts.map +1 -1
- package/dist/remediate/steps/frictionCloseout.js +6 -99
- package/dist/remediate/steps/frictionCloseout.js.map +1 -1
- package/dist/remediate/steps/nextStep.d.ts +2 -15
- package/dist/remediate/steps/nextStep.d.ts.map +1 -1
- package/dist/remediate/steps/nextStep.js +254 -1042
- package/dist/remediate/steps/nextStep.js.map +1 -1
- package/dist/remediate/steps/prompts.js +16 -16
- package/dist/remediate/steps/prompts.js.map +1 -1
- package/dist/remediate/steps/stepUtils.d.ts +1 -1
- package/dist/remediate/steps/stepUtils.d.ts.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 +1 -1
- package/dist/remediate/steps/types.js.map +1 -1
- package/dist/remediate/types/options.d.ts +9 -0
- package/dist/remediate/types/options.d.ts.map +1 -1
- package/dist/remediate/validation/artifacts.d.ts.map +1 -1
- package/dist/remediate/validation/artifacts.js +10 -56
- package/dist/remediate/validation/artifacts.js.map +1 -1
- package/dist/remediate/validation/remediationState.d.ts +2 -2
- package/dist/remediate/validation/remediationState.d.ts.map +1 -1
- package/dist/remediate/validation/remediationState.js +17 -77
- package/dist/remediate/validation/remediationState.js.map +1 -1
- package/dist/remediate/validation/verificationReport.d.ts +3 -0
- package/dist/remediate/validation/verificationReport.d.ts.map +1 -0
- package/dist/remediate/validation/verificationReport.js +28 -0
- package/dist/remediate/validation/verificationReport.js.map +1 -0
- package/dist/shared/analyzers/types.d.ts +10 -10
- package/dist/shared/engine/obligationEngine.d.ts +2 -2
- package/dist/shared/friction/triage.d.ts +7 -28
- package/dist/shared/friction/triage.d.ts.map +1 -1
- package/dist/shared/friction/triage.js +7 -28
- package/dist/shared/friction/triage.js.map +1 -1
- package/dist/shared/graph/orderedReachability.js +1 -1
- package/dist/shared/graph/orderedReachability.js.map +1 -1
- package/dist/shared/index.d.ts +5 -6
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +3 -4
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/loopCorePaths.d.ts.map +1 -1
- package/dist/shared/loopCorePaths.js +37 -5
- package/dist/shared/loopCorePaths.js.map +1 -1
- package/dist/shared/prompts.d.ts +24 -10
- package/dist/shared/prompts.d.ts.map +1 -1
- package/dist/shared/prompts.js +27 -13
- package/dist/shared/prompts.js.map +1 -1
- package/dist/shared/reReview/projectionDiff.d.ts.map +1 -1
- package/dist/shared/reReview/projectionDiff.js +6 -14
- package/dist/shared/reReview/projectionDiff.js.map +1 -1
- package/dist/shared/types/executionPlan.d.ts +416 -0
- package/dist/shared/types/executionPlan.d.ts.map +1 -0
- package/dist/shared/types/executionPlan.js +132 -0
- package/dist/shared/types/executionPlan.js.map +1 -0
- package/dist/shared/types/remediationOutcome.d.ts +1378 -12
- package/dist/shared/types/remediationOutcome.d.ts.map +1 -1
- package/dist/shared/types/remediationOutcome.js +29 -1
- package/dist/shared/types/remediationOutcome.js.map +1 -1
- package/dist/shared/types/{contractPipeline/verification.d.ts → verificationReport.d.ts} +9 -37
- package/dist/shared/types/verificationReport.d.ts.map +1 -0
- package/dist/shared/types/verificationReport.js +4 -0
- package/dist/shared/types/verificationReport.js.map +1 -0
- package/dist/shared/validation/findingGrounding.d.ts +3 -5
- package/dist/shared/validation/findingGrounding.d.ts.map +1 -1
- package/dist/shared/validation/findingGrounding.js +4 -7
- package/dist/shared/validation/findingGrounding.js.map +1 -1
- package/package.json +2 -1
- package/scripts/shared/primitives.mjs +20 -0
- package/skills/audit-code/SKILL.md +5 -12
- package/skills/audit-code/audit-code.prompt.md +5 -8
- package/skills/audit-code/opencode-command-template.txt +2 -2
- package/skills/remediate-code/SKILL.md +5 -7
- package/skills/remediate-code/remediate-code.prompt.md +5 -5
- package/dispatch/lens-definitions.json +0 -46
- package/dist/remediate/contractPipeline/artifactNames.d.ts +0 -8
- package/dist/remediate/contractPipeline/artifactNames.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/artifactNames.js +0 -28
- package/dist/remediate/contractPipeline/artifactNames.js.map +0 -1
- package/dist/remediate/contractPipeline/artifactStore.d.ts +0 -219
- package/dist/remediate/contractPipeline/artifactStore.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/artifactStore.js +0 -436
- package/dist/remediate/contractPipeline/artifactStore.js.map +0 -1
- package/dist/remediate/contractPipeline/changeClassification.d.ts +0 -130
- package/dist/remediate/contractPipeline/changeClassification.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/changeClassification.js +0 -446
- package/dist/remediate/contractPipeline/changeClassification.js.map +0 -1
- package/dist/remediate/contractPipeline/contractReviewBinding.d.ts +0 -28
- package/dist/remediate/contractPipeline/contractReviewBinding.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/contractReviewBinding.js +0 -75
- package/dist/remediate/contractPipeline/contractReviewBinding.js.map +0 -1
- package/dist/remediate/contractPipeline/counterexampleFingerprint.d.ts +0 -27
- package/dist/remediate/contractPipeline/counterexampleFingerprint.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/counterexampleFingerprint.js +0 -37
- package/dist/remediate/contractPipeline/counterexampleFingerprint.js.map +0 -1
- package/dist/remediate/contractPipeline/cyclicSeamResolution.d.ts +0 -131
- package/dist/remediate/contractPipeline/cyclicSeamResolution.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/cyclicSeamResolution.js +0 -257
- package/dist/remediate/contractPipeline/cyclicSeamResolution.js.map +0 -1
- package/dist/remediate/contractPipeline/derive.d.ts +0 -173
- package/dist/remediate/contractPipeline/derive.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/derive.js +0 -477
- package/dist/remediate/contractPipeline/derive.js.map +0 -1
- package/dist/remediate/contractPipeline/finalizedContractFields.d.ts +0 -50
- package/dist/remediate/contractPipeline/finalizedContractFields.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/finalizedContractFields.js +0 -77
- package/dist/remediate/contractPipeline/finalizedContractFields.js.map +0 -1
- package/dist/remediate/contractPipeline/idRegistry.d.ts +0 -144
- package/dist/remediate/contractPipeline/idRegistry.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/idRegistry.js +0 -214
- package/dist/remediate/contractPipeline/idRegistry.js.map +0 -1
- package/dist/remediate/contractPipeline/obligationKinds.d.ts +0 -27
- package/dist/remediate/contractPipeline/obligationKinds.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/obligationKinds.js +0 -18
- package/dist/remediate/contractPipeline/obligationKinds.js.map +0 -1
- package/dist/remediate/contractPipeline/phaseCut.d.ts +0 -125
- package/dist/remediate/contractPipeline/phaseCut.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/phaseCut.js +0 -339
- package/dist/remediate/contractPipeline/phaseCut.js.map +0 -1
- package/dist/remediate/contractPipeline/phaseCutArtifact.d.ts +0 -31
- package/dist/remediate/contractPipeline/phaseCutArtifact.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/phaseCutArtifact.js +0 -48
- package/dist/remediate/contractPipeline/phaseCutArtifact.js.map +0 -1
- package/dist/remediate/contractPipeline/repairState.d.ts +0 -110
- package/dist/remediate/contractPipeline/repairState.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/repairState.js +0 -185
- package/dist/remediate/contractPipeline/repairState.js.map +0 -1
- package/dist/remediate/contractPipeline/reviewSnapshot.d.ts +0 -79
- package/dist/remediate/contractPipeline/reviewSnapshot.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/reviewSnapshot.js +0 -140
- package/dist/remediate/contractPipeline/reviewSnapshot.js.map +0 -1
- package/dist/remediate/contractPipeline/semanticProjection.d.ts +0 -64
- package/dist/remediate/contractPipeline/semanticProjection.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/semanticProjection.js +0 -136
- package/dist/remediate/contractPipeline/semanticProjection.js.map +0 -1
- package/dist/remediate/contractPipeline/sketchSource.d.ts +0 -194
- package/dist/remediate/contractPipeline/sketchSource.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/sketchSource.js +0 -262
- package/dist/remediate/contractPipeline/sketchSource.js.map +0 -1
- package/dist/remediate/contractPipeline/testPlanCarry.d.ts +0 -17
- package/dist/remediate/contractPipeline/testPlanCarry.d.ts.map +0 -1
- package/dist/remediate/contractPipeline/testPlanCarry.js +0 -72
- package/dist/remediate/contractPipeline/testPlanCarry.js.map +0 -1
- package/dist/remediate/steps/dispatch/marshal.d.ts +0 -7
- package/dist/remediate/steps/dispatch/marshal.d.ts.map +0 -1
- package/dist/remediate/steps/dispatch/marshal.js +0 -11
- package/dist/remediate/steps/dispatch/marshal.js.map +0 -1
- package/dist/remediate/validation/contractPipeline.d.ts +0 -35
- package/dist/remediate/validation/contractPipeline.d.ts.map +0 -1
- package/dist/remediate/validation/contractPipeline.js +0 -613
- package/dist/remediate/validation/contractPipeline.js.map +0 -1
- package/dist/remediate/validation/contractPipelineGates.d.ts +0 -272
- package/dist/remediate/validation/contractPipelineGates.d.ts.map +0 -1
- package/dist/remediate/validation/contractPipelineGates.js +0 -1397
- package/dist/remediate/validation/contractPipelineGates.js.map +0 -1
- package/dist/shared/types/contractPipeline/design.d.ts +0 -79
- package/dist/shared/types/contractPipeline/design.d.ts.map +0 -1
- package/dist/shared/types/contractPipeline/design.js +0 -16
- package/dist/shared/types/contractPipeline/design.js.map +0 -1
- package/dist/shared/types/contractPipeline/goal.d.ts +0 -41
- package/dist/shared/types/contractPipeline/goal.d.ts.map +0 -1
- package/dist/shared/types/contractPipeline/goal.js +0 -10
- package/dist/shared/types/contractPipeline/goal.js.map +0 -1
- package/dist/shared/types/contractPipeline/implementation.d.ts +0 -118
- package/dist/shared/types/contractPipeline/implementation.d.ts.map +0 -1
- package/dist/shared/types/contractPipeline/implementation.js +0 -13
- package/dist/shared/types/contractPipeline/implementation.js.map +0 -1
- package/dist/shared/types/contractPipeline/obligations.d.ts +0 -283
- package/dist/shared/types/contractPipeline/obligations.d.ts.map +0 -1
- package/dist/shared/types/contractPipeline/obligations.js +0 -84
- package/dist/shared/types/contractPipeline/obligations.js.map +0 -1
- package/dist/shared/types/contractPipeline/verification.d.ts.map +0 -1
- package/dist/shared/types/contractPipeline/verification.js +0 -10
- package/dist/shared/types/contractPipeline/verification.js.map +0 -1
- package/dist/shared/types/contractPipeline.d.ts +0 -48
- package/dist/shared/types/contractPipeline.d.ts.map +0 -1
- package/dist/shared/types/contractPipeline.js +0 -32
- package/dist/shared/types/contractPipeline.js.map +0 -1
- package/dist/shared/types/obligationLedger.d.ts +0 -39
- package/dist/shared/types/obligationLedger.d.ts.map +0 -1
- package/dist/shared/types/obligationLedger.js +0 -49
- package/dist/shared/types/obligationLedger.js.map +0 -1
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { type ContractReviewProvenance, type ContractReviewDeclaration } from "../../shared/types/reviewIndependence.js";
|
|
2
|
-
import { CP_ARTIFACT_NAMES } from "./artifactNames.js";
|
|
3
|
-
import type { ContractPipelineArtifactName } from "./artifactNames.js";
|
|
4
|
-
export { CP_ARTIFACT_NAMES };
|
|
5
|
-
export type { ContractPipelineArtifactName };
|
|
6
|
-
export declare const DEPENDENCY_MAP: Record<ContractPipelineArtifactName, ContractPipelineArtifactName[]>;
|
|
7
|
-
export interface ContractPipelineArtifactEnvelope {
|
|
8
|
-
artifact_name: ContractPipelineArtifactName;
|
|
9
|
-
review_provenance?: ContractReviewProvenance;
|
|
10
|
-
/**
|
|
11
|
-
* Identity of this exact emission: `hashContent(stableStringify(payload))`.
|
|
12
|
-
* KEY-ORDER INDEPENDENT — the same payload assembled in a different field
|
|
13
|
-
* order hashes identically (see `computeHash`).
|
|
14
|
-
*
|
|
15
|
-
* A stored header that disagrees with the payload it sits beside is CORRECTED
|
|
16
|
-
* IN MEMORY on read and NOT persisted: `readContractArtifact` recomputes,
|
|
17
|
-
* returns the recomputed value, and emits a
|
|
18
|
-
* `contract_artifact_content_hash_mismatch` warning naming both hashes. The
|
|
19
|
-
* file on disk keeps whatever it was written with, so this field is the
|
|
20
|
-
* identity of the payload AS READ, never a claim about the stored bytes.
|
|
21
|
-
*/
|
|
22
|
-
content_hash: string;
|
|
23
|
-
/** Semantic-projection hashes of upstream dependency artifacts at write time. */
|
|
24
|
-
dependency_hashes: Partial<Record<ContractPipelineArtifactName, string>>;
|
|
25
|
-
payload: unknown;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Canonical predicate for a stored content-hash envelope. Single-sourced here so
|
|
29
|
-
* any consumer (the contract-pipeline ingest path, the `validate-artifact` CLI)
|
|
30
|
-
* unwraps with identical structural rules and cannot drift. A plain payload that
|
|
31
|
-
* happens to carry an `artifact_name` but no `content_hash` is NOT an envelope.
|
|
32
|
-
*
|
|
33
|
-
* The THREE-KEY test this used to be (`artifact_name` string, `content_hash`
|
|
34
|
-
* string, `"payload" in value`) was a cast wearing a predicate's name: it admits
|
|
35
|
-
* a bare payload that carries `await`-shaped fields, and — more to the point —
|
|
36
|
-
* it does not check that `artifact_name` is one of the fifteen names the
|
|
37
|
-
* dependency DAG and the semantic projection are keyed by. An envelope whose
|
|
38
|
-
* `artifact_name` was misspelled passes `isEnvelope`, then reads a projection
|
|
39
|
-
* table with an absent key. See {@link readContractArtifact}, which is where
|
|
40
|
-
* that binding is now enforced.
|
|
41
|
-
*/
|
|
42
|
-
export declare function isEnvelope(value: unknown): value is ContractPipelineArtifactEnvelope;
|
|
43
|
-
/**
|
|
44
|
-
* Stamp a tool-owned `created_at` onto a raw artifact payload when the host did
|
|
45
|
-
* not provide one. The host has no clock — `created_at` is tool bookkeeping, not
|
|
46
|
-
* a judgment field — so the tool stamps it at the point the payload enters the
|
|
47
|
-
* tool (ingest + the `validate-artifact` self-check), and the host-facing
|
|
48
|
-
* schemas no longer ask for it. A payload that already carries a string
|
|
49
|
-
* `created_at` (e.g. a tool-derived artifact) is returned untouched. The stamp
|
|
50
|
-
* is a universal non-semantic field (`semanticProjection` strips it), so adding
|
|
51
|
-
* it never affects staleness. Non-object payloads pass through unchanged — their
|
|
52
|
-
* own validator reports the shape error.
|
|
53
|
-
*/
|
|
54
|
-
export declare function stampToolCreatedAt(payload: unknown, now: string): unknown;
|
|
55
|
-
export declare function contractPipelineDir(artifactsDir: string): string;
|
|
56
|
-
/**
|
|
57
|
-
* Path to the optional Path-A seed file. Present only when the intake source
|
|
58
|
-
* is a structured audit-findings report; absent for document/conversation runs.
|
|
59
|
-
*/
|
|
60
|
-
export declare function pathASeedFilePath(artifactsDir: string): string;
|
|
61
|
-
/**
|
|
62
|
-
* Where a review artifact's diff-based re-review snapshot lives.
|
|
63
|
-
*
|
|
64
|
-
* Single-sourced here, beside the artifact path helpers, because the ARCHIVE
|
|
65
|
-
* boundary has to reach it from a module that must not import the snapshot
|
|
66
|
-
* module's own read/write surface. Kept as a filename rather than a computed
|
|
67
|
-
* `join` in each caller so the two can never disagree about the directory.
|
|
68
|
-
*/
|
|
69
|
-
export declare const REVIEW_SNAPSHOT_DIRNAME = "review-snapshots";
|
|
70
|
-
export declare function reviewSnapshotDirPath(artifactsDir: string): string;
|
|
71
|
-
export declare function reviewSnapshotFilePath(artifactsDir: string, name: ContractPipelineArtifactName): string;
|
|
72
|
-
/**
|
|
73
|
-
* Drop a review artifact's diff-based re-review snapshot.
|
|
74
|
-
*
|
|
75
|
-
* Called when the artifact's INPUT is destroyed — the ordinary re-emit after an
|
|
76
|
-
* archive, and the promotion rejection that rolls a promoted plan back. The
|
|
77
|
-
* snapshot holds the verdict a re-review would re-affirm, and its whole value
|
|
78
|
-
* depends on being the LAST verdict for THAT input. Left in place across a
|
|
79
|
-
* rewrite it becomes worse than absent: `captureReviewSnapshot` runs at INGEST,
|
|
80
|
-
* which happens AFTER ingest's own staleness pass, so the archive pass inside
|
|
81
|
-
* THIS invocation has already gone by — a snapshot surviving the intervening
|
|
82
|
-
* call would be diffed against the NEW payload while claiming to be the prior
|
|
83
|
-
* verdict, and the worker would be told to re-affirm a verdict about content it
|
|
84
|
-
* never saw. With none present, `buildReReviewSection` renders no section and
|
|
85
|
-
* the phase runs as an ordinary full review, which is correct.
|
|
86
|
-
*
|
|
87
|
-
* Deliberately NOT called for the `stale` archive: that path re-opens a
|
|
88
|
-
* DOWNSTREAM artifact, which by construction has no snapshot of its own (its
|
|
89
|
-
* producer never ran), so there is nothing there to drop and the call would be
|
|
90
|
-
* noise in a hot loop.
|
|
91
|
-
*/
|
|
92
|
-
export declare function dropReviewSnapshot(artifactsDir: string, name: ContractPipelineArtifactName): Promise<void>;
|
|
93
|
-
/**
|
|
94
|
-
* Canonical envelope path `<name>.json` — the TOOL-owned content-hash envelope.
|
|
95
|
-
* Host code never reads or writes this; every tool-side consumer reaches it
|
|
96
|
-
* through `readContractArtifact`.
|
|
97
|
-
*/
|
|
98
|
-
export declare function contractArtifactFilePath(artifactsDir: string, name: ContractPipelineArtifactName): string;
|
|
99
|
-
/**
|
|
100
|
-
* Host input path `<name>.input.json` — the plain payload the host writes (and
|
|
101
|
-
* reads for upstreams). The host never sees the tool's canonical envelope; the
|
|
102
|
-
* tool reads this at ingest, validates, and derives the canonical `<name>.json`
|
|
103
|
-
* envelope from it (D3). Keeping the two paths disjoint means the on-disk file
|
|
104
|
-
* the host wrote is never mutated into an envelope in place.
|
|
105
|
-
*/
|
|
106
|
-
export declare function contractInputFilePath(artifactsDir: string, name: ContractPipelineArtifactName): string;
|
|
107
|
-
/**
|
|
108
|
-
* Hash an artifact's semantic projection (order-independent, stamp-stripped).
|
|
109
|
-
* Exported so the ingest idempotency guard can compare a freshly-read host input
|
|
110
|
-
* against the canonical envelope without re-deriving a new (stamp-bearing)
|
|
111
|
-
* content hash on every next-step.
|
|
112
|
-
*/
|
|
113
|
-
export declare function payloadSemanticHash(name: ContractPipelineArtifactName, payload: unknown): string;
|
|
114
|
-
/**
|
|
115
|
-
* The semantic hash to compare a dependency against. ALWAYS recomputed from the
|
|
116
|
-
* envelope's current `payload` — never read from a stored header field — so an
|
|
117
|
-
* in-place edit to a payload (header untouched) reconverges staleness on the next
|
|
118
|
-
* read. Cosmetic edits project to the same hash (see `semanticProjection`) and so
|
|
119
|
-
* still do not re-stale downstreams (B3).
|
|
120
|
-
*/
|
|
121
|
-
export declare function envelopeSemanticHash(envelope: ContractPipelineArtifactEnvelope): string;
|
|
122
|
-
/** Write an artifact envelope. Creates parent directories as needed. */
|
|
123
|
-
export declare function writeContractArtifact(artifactsDir: string, name: ContractPipelineArtifactName, payload: unknown, review?: ContractReviewDeclaration): Promise<ContractPipelineArtifactEnvelope>;
|
|
124
|
-
/**
|
|
125
|
-
* Write a TOOL-DERIVED artifact to BOTH path roles: the plain payload at the
|
|
126
|
-
* host-input path `<name>.input.json` and the canonical envelope at
|
|
127
|
-
* `<name>.json`.
|
|
128
|
-
*
|
|
129
|
-
* Why the input path too. Every host-facing artifact path the pipeline renders —
|
|
130
|
-
* both where a role WRITES its output and where it READS its upstreams — is
|
|
131
|
-
* `<name>.input.json` (D3: the host's world is entirely plain input files). An
|
|
132
|
-
* artifact the TOOL derives (the obligation ledger, the finalized contracts, a
|
|
133
|
-
* degenerate seam report, a no-cycles seam resolution, a merged shard aggregate)
|
|
134
|
-
* used to land only in the canonical envelope, so any downstream prompt naming
|
|
135
|
-
* it pointed a worker at a file that never existed. Materializing it here makes
|
|
136
|
-
* that ENOENT class unrepresentable: the write map and the prompts' input map
|
|
137
|
-
* are the same map.
|
|
138
|
-
*
|
|
139
|
-
* Deliberately NOT folded into `writeContractArtifact`: that one is also how
|
|
140
|
-
* INGEST wraps a host-authored payload, and writing back there would mutate the
|
|
141
|
-
* host's own input file in place — the exact separation D3 exists to keep. The
|
|
142
|
-
* derived input file is idempotent for ingest: its semantic projection matches
|
|
143
|
-
* the canonical envelope's, so the ingest idempotency guard skips it on every
|
|
144
|
-
* later pass rather than re-deriving.
|
|
145
|
-
*/
|
|
146
|
-
export declare function writeDerivedContractArtifact(artifactsDir: string, name: ContractPipelineArtifactName, payload: unknown): Promise<ContractPipelineArtifactEnvelope>;
|
|
147
|
-
/**
|
|
148
|
-
* Payload of a stored artifact whether or not it has been enveloped yet. A null
|
|
149
|
-
* envelope (absent on disk) yields undefined; a bare payload that was written
|
|
150
|
-
* without the envelope wrapper is returned as-is. Single-sourced here so every
|
|
151
|
-
* consumer unwraps identically (cannot drift from `isEnvelope`).
|
|
152
|
-
*/
|
|
153
|
-
export declare function envelopePayload(envelope: ContractPipelineArtifactEnvelope | null): unknown;
|
|
154
|
-
/**
|
|
155
|
-
* Read a stored artifact envelope, or null if absent.
|
|
156
|
-
*
|
|
157
|
-
* Three checks, all of them about IDENTITY — the file at `<name>.json` must BE
|
|
158
|
-
* the artifact `<name>`, not merely a JSON document that was found there:
|
|
159
|
-
*
|
|
160
|
-
* 1. **Shape.** Parsed against {@link isEnvelope}, never cast. The previous
|
|
161
|
-
* body was `readOptionalJsonFile<ContractPipelineArtifactEnvelope>` — a
|
|
162
|
-
* generic TYPE PARAMETER, which is an assertion the compiler erases. A file
|
|
163
|
-
* containing `{"hello":1}` came back typed as an envelope, and every
|
|
164
|
-
* downstream `.artifact_name` / `.payload` read was an unchecked property
|
|
165
|
-
* access on `unknown`-shaped data.
|
|
166
|
-
* 2. **Binding.** `artifact_name` must equal the name that was REQUESTED. The
|
|
167
|
-
* two are the same value by construction on the write path
|
|
168
|
-
* ({@link writeContractArtifact} passes one name to both), so a disagreement
|
|
169
|
-
* means the file was written by something else — a hand edit, a copy, a
|
|
170
|
-
* rename that missed the header. This is not cosmetic: `artifact_name` is
|
|
171
|
-
* the key into `DEPENDENCY_MAP` and `semanticProjection`, and a mismatched
|
|
172
|
-
* name silently reads another artifact's projection table. A mismatched
|
|
173
|
-
* envelope reads as ABSENT, so the caller's staleness DAG re-opens the
|
|
174
|
-
* producing phase rather than consuming bytes that cannot be trusted.
|
|
175
|
-
* 3. **Content hash.** Recomputed from the payload and, when it disagrees with
|
|
176
|
-
* the recorded one, the envelope is returned with
|
|
177
|
-
* {@link ContractPipelineArtifactEnvelope.content_hash} rewritten to the
|
|
178
|
-
* RECOMPUTED value. The payload is authoritative — it is what every
|
|
179
|
-
* consumer reads and what `envelopeSemanticHash` projects — so a header
|
|
180
|
-
* that no longer describes its payload must not be allowed to keep
|
|
181
|
-
* speaking. Reading the payload but reporting the stale header's hash is
|
|
182
|
-
* exactly the failure `detectStaleArtifacts`'s recompute-on-read exists to
|
|
183
|
-
* prevent (see its note on in-place edits), and the hash is the identity
|
|
184
|
-
* the judge/critique repair ledger keys on (`judge_hash` /
|
|
185
|
-
* `critique_hash` in repairState.ts), so a drifted value would make
|
|
186
|
-
* "already repaired for this report" answer about the wrong report.
|
|
187
|
-
*
|
|
188
|
-
* Deliberately NOT a null: treating a payload edit as an absent artifact
|
|
189
|
-
* would erase the distinction the caller needs (absent ⇒ re-emit the
|
|
190
|
-
* producer; edited ⇒ re-stale the downstreams), and it is a real thing
|
|
191
|
-
* hosts and tests do.
|
|
192
|
-
*
|
|
193
|
-
* A shape or binding refusal is silent-by-return (null), not a throw: every
|
|
194
|
-
* caller already handles absent (that IS the fresh-run case), and throwing here
|
|
195
|
-
* would turn one damaged file into a failed `next-step` rather than a re-emitted
|
|
196
|
-
* phase.
|
|
197
|
-
*/
|
|
198
|
-
export declare function readContractArtifact(artifactsDir: string, name: ContractPipelineArtifactName): Promise<ContractPipelineArtifactEnvelope | null>;
|
|
199
|
-
export interface StalenessResult {
|
|
200
|
-
/** Names of artifacts that are stale (upstream changed) or missing (never written). */
|
|
201
|
-
stale: ContractPipelineArtifactName[];
|
|
202
|
-
/** Names of artifacts that are absent (file does not exist). */
|
|
203
|
-
absent: ContractPipelineArtifactName[];
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Detect stale artifacts by walking the dependency DAG transitively.
|
|
207
|
-
* An artifact is stale when:
|
|
208
|
-
* - A dependency artifact is absent/missing.
|
|
209
|
-
* - A dependency artifact's current SEMANTIC-projection hash differs from what
|
|
210
|
-
* was recorded at write time in this artifact's envelope. Cosmetic upstream
|
|
211
|
-
* edits (reworded prose, regenerated timestamps, reordered keys) project to
|
|
212
|
-
* the same hash and do NOT mark downstreams stale (B3).
|
|
213
|
-
*
|
|
214
|
-
* Absent artifacts (never written) are reported under `absent`, not `stale`.
|
|
215
|
-
*/
|
|
216
|
-
export declare function detectStaleArtifacts(artifactsDir: string): Promise<StalenessResult>;
|
|
217
|
-
/** Returns true when the artifact file is present on disk. */
|
|
218
|
-
export declare function contractArtifactExists(artifactsDir: string, name: ContractPipelineArtifactName): boolean;
|
|
219
|
-
//# sourceMappingURL=artifactStore.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"artifactStore.d.ts","sourceRoot":"","sources":["../../../src/remediate/contractPipeline/artifactStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,wBAAwB,EAAE,KAAK,yBAAyB,EAA2B,MAAM,0CAA0C,CAAC;AAyClL,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAC7B,YAAY,EAAE,4BAA4B,EAAE,CAAC;AAM7C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,4BAA4B,EAAE,4BAA4B,EAAE,CAiC/F,CAAC;AAIF,MAAM,WAAW,gCAAgC;IAC/C,aAAa,EAAE,4BAA4B,CAAC;IAC5C,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;IAC7C;;;;;;;;;;;OAWG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,4BAA4B,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,OAAO,EAAE,OAAO,CAAC;CAClB;AA+CD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,gCAAgC,CAU3C;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAMzE;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAE1D,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,GACjC,MAAM,CAER;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,GACjC,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,GACjC,MAAM,CAER;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,GACjC,MAAM,CAER;AAqBD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,4BAA4B,EAClC,OAAO,EAAE,OAAO,GACf,MAAM,CAKR;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gCAAgC,GACzC,MAAM,CAER;AAID,wEAAwE;AACxE,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,EAClC,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,yBAAyB,GACjC,OAAO,CAAC,gCAAgC,CAAC,CAwB3C;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,4BAA4B,CAChD,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,EAClC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,gCAAgC,CAAC,CAI3C;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,gCAAgC,GAAG,IAAI,GAChD,OAAO,CAGT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,GACjC,OAAO,CAAC,gCAAgC,GAAG,IAAI,CAAC,CAqBlD;AAED,MAAM,WAAW,eAAe;IAC9B,uFAAuF;IACvF,KAAK,EAAE,4BAA4B,EAAE,CAAC;IACtC,gEAAgE;IAChE,MAAM,EAAE,4BAA4B,EAAE,CAAC;CACxC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,eAAe,CAAC,CA6C1B;AAED,8DAA8D;AAC9D,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,GACjC,OAAO,CAET"}
|
|
@@ -1,436 +0,0 @@
|
|
|
1
|
-
// sites-pinned: tests/remediate/contract-pipeline-artifact-store.test.ts, tests/remediate/contract-review-independence.test.ts, tests/remediate/contract-pipeline.test.ts, tests/remediate/contract-pipeline-adversarial.test.ts
|
|
2
|
-
import { propagateReachability } from "../../shared/graph/orderedReachability.js";
|
|
3
|
-
import { ContractReviewProvenanceSchema, reviewIndependenceIssue } from "../../shared/types/reviewIndependence.js";
|
|
4
|
-
/**
|
|
5
|
-
* Typed read/write helpers for the contract-pipeline artifacts.
|
|
6
|
-
*
|
|
7
|
-
* Two distinct, non-overlapping path roles live under
|
|
8
|
-
* `<artifactsDir>/intake/contract/` (D3):
|
|
9
|
-
*
|
|
10
|
-
* - **Host input** `<name>.input.json` — the authored submission. Ordinary roles
|
|
11
|
-
* write a raw payload; review roles write the bound review-submission envelope.
|
|
12
|
-
* - **Canonical envelope** `<name>.json` — tool-owned validated domain payload,
|
|
13
|
-
* dependency hashes and accepted review provenance. Downstream roles read its
|
|
14
|
-
* `payload` field and never write this file.
|
|
15
|
-
*
|
|
16
|
-
* No host input is rewritten in place. Collapsed ordinary authoring sections
|
|
17
|
-
* may read earlier raw inputs in the same round trip before ingestion; this
|
|
18
|
-
* exception never admits an unvalidated review envelope as canonical data.
|
|
19
|
-
*
|
|
20
|
-
* Independence from StateStore is intentional: these helpers operate on the
|
|
21
|
-
* contract-pipeline subdirectory only and do not touch the remediation
|
|
22
|
-
* state machine.
|
|
23
|
-
*/
|
|
24
|
-
import { existsSync } from "node:fs";
|
|
25
|
-
import { mkdir, rm } from "node:fs/promises";
|
|
26
|
-
import { join } from "node:path";
|
|
27
|
-
import { hashContent, isRecord, readOptionalJsonFile, stableStringify, writeJsonFile, } from "audit-tools/shared";
|
|
28
|
-
import { semanticProjection, stableStringifyProjection, } from "./semanticProjection.js";
|
|
29
|
-
// ── Artifact names ────────────────────────────────────────────────────────────
|
|
30
|
-
// Defined in ./artifactNames.js (below both this module and semanticProjection,
|
|
31
|
-
// which needs the name type — declaring it here closed a type-only cycle).
|
|
32
|
-
// Re-exported so existing importers are unchanged.
|
|
33
|
-
import { CP_ARTIFACT_NAMES } from "./artifactNames.js";
|
|
34
|
-
export { CP_ARTIFACT_NAMES };
|
|
35
|
-
// ── Dependency DAG ────────────────────────────────────────────────────────────
|
|
36
|
-
// An artifact is stale when any dependency it lists is missing or has a
|
|
37
|
-
// different content hash than recorded at write time.
|
|
38
|
-
export const DEPENDENCY_MAP = {
|
|
39
|
-
goal_spec: [],
|
|
40
|
-
context_bundle: ["goal_spec"],
|
|
41
|
-
module_decomposition: ["goal_spec", "context_bundle"],
|
|
42
|
-
module_contracts: ["goal_spec", "context_bundle", "module_decomposition"],
|
|
43
|
-
seam_reconciliation_report: ["module_decomposition", "module_contracts"],
|
|
44
|
-
finalized_module_contracts: ["module_contracts", "seam_reconciliation_report"],
|
|
45
|
-
conceptual_design_critique: ["goal_spec", "module_decomposition", "finalized_module_contracts"],
|
|
46
|
-
obligation_ledger: ["goal_spec", "finalized_module_contracts"],
|
|
47
|
-
cyclic_seam_resolution: ["obligation_ledger"],
|
|
48
|
-
test_validator_plan: ["goal_spec", "obligation_ledger"],
|
|
49
|
-
contract_assessment_report: ["goal_spec", "finalized_module_contracts", "obligation_ledger", "cyclic_seam_resolution", "test_validator_plan"],
|
|
50
|
-
counterexample: ["goal_spec", "finalized_module_contracts", "obligation_ledger", "cyclic_seam_resolution", "test_validator_plan", "contract_assessment_report"],
|
|
51
|
-
judge_report: ["goal_spec", "module_decomposition", "finalized_module_contracts", "obligation_ledger", "cyclic_seam_resolution", "test_validator_plan", "contract_assessment_report", "counterexample"],
|
|
52
|
-
implementation_dag: [
|
|
53
|
-
"goal_spec",
|
|
54
|
-
"context_bundle",
|
|
55
|
-
"finalized_module_contracts",
|
|
56
|
-
"obligation_ledger",
|
|
57
|
-
"cyclic_seam_resolution",
|
|
58
|
-
"test_validator_plan",
|
|
59
|
-
"contract_assessment_report",
|
|
60
|
-
"counterexample",
|
|
61
|
-
"judge_report",
|
|
62
|
-
],
|
|
63
|
-
verification_report: [
|
|
64
|
-
"goal_spec",
|
|
65
|
-
"context_bundle",
|
|
66
|
-
"finalized_module_contracts",
|
|
67
|
-
"obligation_ledger",
|
|
68
|
-
"contract_assessment_report",
|
|
69
|
-
"implementation_dag",
|
|
70
|
-
],
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Surface a `content_hash` header that no longer describes its payload.
|
|
74
|
-
*
|
|
75
|
-
* The correction itself is silent-by-design (the payload is authoritative and
|
|
76
|
-
* the read still returns), but a disagreement between a stored header and the
|
|
77
|
-
* bytes beside it is a FACT someone needs: it means the envelope was edited in
|
|
78
|
-
* place, copied, or written by an older hash definition, and the recorded value
|
|
79
|
-
* is the identity the judge/critique repair ledger keys on. A silent in-memory
|
|
80
|
-
* rewrite turns that into a run that behaves correctly and explains nothing.
|
|
81
|
-
*
|
|
82
|
-
* Same shape as the repository's other structured warnings
|
|
83
|
-
* (`file_integrity_io_error` in `utils/fileIntegrity.ts`,
|
|
84
|
-
* `truncated_verification_file_list` in the audit side): one `level: "warn"`
|
|
85
|
-
* JSON object per line on stderr, so a log reader that already parses these
|
|
86
|
-
* needs no new case.
|
|
87
|
-
*/
|
|
88
|
-
function reportContentHashMismatch(name, stored, recomputed) {
|
|
89
|
-
process.stderr.write(JSON.stringify({
|
|
90
|
-
level: "warn",
|
|
91
|
-
event: "contract_artifact_content_hash_mismatch",
|
|
92
|
-
artifact_name: name,
|
|
93
|
-
stored_content_hash: stored,
|
|
94
|
-
recomputed_content_hash: recomputed,
|
|
95
|
-
ts: new Date().toISOString(),
|
|
96
|
-
}) + "\n");
|
|
97
|
-
}
|
|
98
|
-
/** One dependency hash entry: a contract-pipeline artifact name → sha. */
|
|
99
|
-
function isDependencyHashes(value) {
|
|
100
|
-
return (isRecord(value) &&
|
|
101
|
-
Object.entries(value).every(([key, hash]) => CP_ARTIFACT_NAMES.includes(key) &&
|
|
102
|
-
typeof hash === "string"));
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Canonical predicate for a stored content-hash envelope. Single-sourced here so
|
|
106
|
-
* any consumer (the contract-pipeline ingest path, the `validate-artifact` CLI)
|
|
107
|
-
* unwraps with identical structural rules and cannot drift. A plain payload that
|
|
108
|
-
* happens to carry an `artifact_name` but no `content_hash` is NOT an envelope.
|
|
109
|
-
*
|
|
110
|
-
* The THREE-KEY test this used to be (`artifact_name` string, `content_hash`
|
|
111
|
-
* string, `"payload" in value`) was a cast wearing a predicate's name: it admits
|
|
112
|
-
* a bare payload that carries `await`-shaped fields, and — more to the point —
|
|
113
|
-
* it does not check that `artifact_name` is one of the fifteen names the
|
|
114
|
-
* dependency DAG and the semantic projection are keyed by. An envelope whose
|
|
115
|
-
* `artifact_name` was misspelled passes `isEnvelope`, then reads a projection
|
|
116
|
-
* table with an absent key. See {@link readContractArtifact}, which is where
|
|
117
|
-
* that binding is now enforced.
|
|
118
|
-
*/
|
|
119
|
-
export function isEnvelope(value) {
|
|
120
|
-
return (isRecord(value) &&
|
|
121
|
-
CP_ARTIFACT_NAMES.includes(value.artifact_name) &&
|
|
122
|
-
typeof value.content_hash === "string" &&
|
|
123
|
-
value.content_hash.length > 0 &&
|
|
124
|
-
"payload" in value &&
|
|
125
|
-
isDependencyHashes(value.dependency_hashes) &&
|
|
126
|
-
(value.review_provenance === undefined || ContractReviewProvenanceSchema.safeParse(value.review_provenance).success));
|
|
127
|
-
}
|
|
128
|
-
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
129
|
-
/**
|
|
130
|
-
* Stamp a tool-owned `created_at` onto a raw artifact payload when the host did
|
|
131
|
-
* not provide one. The host has no clock — `created_at` is tool bookkeeping, not
|
|
132
|
-
* a judgment field — so the tool stamps it at the point the payload enters the
|
|
133
|
-
* tool (ingest + the `validate-artifact` self-check), and the host-facing
|
|
134
|
-
* schemas no longer ask for it. A payload that already carries a string
|
|
135
|
-
* `created_at` (e.g. a tool-derived artifact) is returned untouched. The stamp
|
|
136
|
-
* is a universal non-semantic field (`semanticProjection` strips it), so adding
|
|
137
|
-
* it never affects staleness. Non-object payloads pass through unchanged — their
|
|
138
|
-
* own validator reports the shape error.
|
|
139
|
-
*/
|
|
140
|
-
export function stampToolCreatedAt(payload, now) {
|
|
141
|
-
if (!isRecord(payload))
|
|
142
|
-
return payload;
|
|
143
|
-
if (typeof payload.created_at === "string" && payload.created_at.length > 0) {
|
|
144
|
-
return payload;
|
|
145
|
-
}
|
|
146
|
-
return { ...payload, created_at: now };
|
|
147
|
-
}
|
|
148
|
-
export function contractPipelineDir(artifactsDir) {
|
|
149
|
-
return join(artifactsDir, "intake", "contract");
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Path to the optional Path-A seed file. Present only when the intake source
|
|
153
|
-
* is a structured audit-findings report; absent for document/conversation runs.
|
|
154
|
-
*/
|
|
155
|
-
export function pathASeedFilePath(artifactsDir) {
|
|
156
|
-
return join(contractPipelineDir(artifactsDir), "path_a_seed.json");
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Where a review artifact's diff-based re-review snapshot lives.
|
|
160
|
-
*
|
|
161
|
-
* Single-sourced here, beside the artifact path helpers, because the ARCHIVE
|
|
162
|
-
* boundary has to reach it from a module that must not import the snapshot
|
|
163
|
-
* module's own read/write surface. Kept as a filename rather than a computed
|
|
164
|
-
* `join` in each caller so the two can never disagree about the directory.
|
|
165
|
-
*/
|
|
166
|
-
export const REVIEW_SNAPSHOT_DIRNAME = "review-snapshots";
|
|
167
|
-
export function reviewSnapshotDirPath(artifactsDir) {
|
|
168
|
-
return join(contractPipelineDir(artifactsDir), REVIEW_SNAPSHOT_DIRNAME);
|
|
169
|
-
}
|
|
170
|
-
export function reviewSnapshotFilePath(artifactsDir, name) {
|
|
171
|
-
return join(reviewSnapshotDirPath(artifactsDir), `${name}.json`);
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Drop a review artifact's diff-based re-review snapshot.
|
|
175
|
-
*
|
|
176
|
-
* Called when the artifact's INPUT is destroyed — the ordinary re-emit after an
|
|
177
|
-
* archive, and the promotion rejection that rolls a promoted plan back. The
|
|
178
|
-
* snapshot holds the verdict a re-review would re-affirm, and its whole value
|
|
179
|
-
* depends on being the LAST verdict for THAT input. Left in place across a
|
|
180
|
-
* rewrite it becomes worse than absent: `captureReviewSnapshot` runs at INGEST,
|
|
181
|
-
* which happens AFTER ingest's own staleness pass, so the archive pass inside
|
|
182
|
-
* THIS invocation has already gone by — a snapshot surviving the intervening
|
|
183
|
-
* call would be diffed against the NEW payload while claiming to be the prior
|
|
184
|
-
* verdict, and the worker would be told to re-affirm a verdict about content it
|
|
185
|
-
* never saw. With none present, `buildReReviewSection` renders no section and
|
|
186
|
-
* the phase runs as an ordinary full review, which is correct.
|
|
187
|
-
*
|
|
188
|
-
* Deliberately NOT called for the `stale` archive: that path re-opens a
|
|
189
|
-
* DOWNSTREAM artifact, which by construction has no snapshot of its own (its
|
|
190
|
-
* producer never ran), so there is nothing there to drop and the call would be
|
|
191
|
-
* noise in a hot loop.
|
|
192
|
-
*/
|
|
193
|
-
export async function dropReviewSnapshot(artifactsDir, name) {
|
|
194
|
-
await rm(reviewSnapshotFilePath(artifactsDir, name), { force: true });
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Canonical envelope path `<name>.json` — the TOOL-owned content-hash envelope.
|
|
198
|
-
* Host code never reads or writes this; every tool-side consumer reaches it
|
|
199
|
-
* through `readContractArtifact`.
|
|
200
|
-
*/
|
|
201
|
-
export function contractArtifactFilePath(artifactsDir, name) {
|
|
202
|
-
return join(contractPipelineDir(artifactsDir), `${name}.json`);
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Host input path `<name>.input.json` — the plain payload the host writes (and
|
|
206
|
-
* reads for upstreams). The host never sees the tool's canonical envelope; the
|
|
207
|
-
* tool reads this at ingest, validates, and derives the canonical `<name>.json`
|
|
208
|
-
* envelope from it (D3). Keeping the two paths disjoint means the on-disk file
|
|
209
|
-
* the host wrote is never mutated into an envelope in place.
|
|
210
|
-
*/
|
|
211
|
-
export function contractInputFilePath(artifactsDir, name) {
|
|
212
|
-
return join(contractPipelineDir(artifactsDir), `${name}.input.json`);
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* The content hash of a payload — the artifact's IDENTITY, and the value the
|
|
216
|
-
* judge/critique repair ledger keys on.
|
|
217
|
-
*
|
|
218
|
-
* `stableStringify`, not `JSON.stringify`. The hash must depend on the payload's
|
|
219
|
-
* CONTENT and on nothing else, and raw `JSON.stringify` makes it depend on KEY
|
|
220
|
-
* INSERTION ORDER as well: the same contract assembled in a different field
|
|
221
|
-
* order hashes differently. That was latent while the only reader of the header
|
|
222
|
-
* was the writer's own round trip, but the moment a read RECOMPUTES and compares
|
|
223
|
-
* (see {@link readContractArtifact}) it becomes a false tamper report on a file
|
|
224
|
-
* nobody touched. The single deterministic serializer is the shared one
|
|
225
|
-
* (INV-CK-2: "there must be exactly ONE such serializer — never write a second"),
|
|
226
|
-
* so write and read agree by construction rather than by both happening to call
|
|
227
|
-
* the same expression.
|
|
228
|
-
*/
|
|
229
|
-
function computeHash(value) {
|
|
230
|
-
return hashContent(stableStringify(value), { length: 32 });
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Hash an artifact's semantic projection (order-independent, stamp-stripped).
|
|
234
|
-
* Exported so the ingest idempotency guard can compare a freshly-read host input
|
|
235
|
-
* against the canonical envelope without re-deriving a new (stamp-bearing)
|
|
236
|
-
* content hash on every next-step.
|
|
237
|
-
*/
|
|
238
|
-
export function payloadSemanticHash(name, payload) {
|
|
239
|
-
return hashContent(stableStringifyProjection(semanticProjection(name, payload)), { length: 32 });
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* The semantic hash to compare a dependency against. ALWAYS recomputed from the
|
|
243
|
-
* envelope's current `payload` — never read from a stored header field — so an
|
|
244
|
-
* in-place edit to a payload (header untouched) reconverges staleness on the next
|
|
245
|
-
* read. Cosmetic edits project to the same hash (see `semanticProjection`) and so
|
|
246
|
-
* still do not re-stale downstreams (B3).
|
|
247
|
-
*/
|
|
248
|
-
export function envelopeSemanticHash(envelope) {
|
|
249
|
-
return payloadSemanticHash(envelope.artifact_name, envelope.payload);
|
|
250
|
-
}
|
|
251
|
-
// ── Public API ────────────────────────────────────────────────────────────────
|
|
252
|
-
/** Write an artifact envelope. Creates parent directories as needed. */
|
|
253
|
-
export async function writeContractArtifact(artifactsDir, name, payload, review) {
|
|
254
|
-
await mkdir(contractPipelineDir(artifactsDir), { recursive: true });
|
|
255
|
-
const content_hash = computeHash(payload);
|
|
256
|
-
// Capture each dependency's SEMANTIC-projection hash at write time, so a later
|
|
257
|
-
// cosmetic edit to that dependency (same projection) does not re-stale this
|
|
258
|
-
// artifact — only a load-bearing change does (B3).
|
|
259
|
-
const dependency_hashes = {};
|
|
260
|
-
for (const dep of DEPENDENCY_MAP[name]) {
|
|
261
|
-
const depEnvelope = await readContractArtifact(artifactsDir, dep);
|
|
262
|
-
if (depEnvelope) {
|
|
263
|
-
dependency_hashes[dep] = envelopeSemanticHash(depEnvelope);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
const envelope = {
|
|
267
|
-
artifact_name: name,
|
|
268
|
-
content_hash,
|
|
269
|
-
dependency_hashes,
|
|
270
|
-
payload,
|
|
271
|
-
...(review ? { review_provenance: { ...review, reviewed_content_hash: content_hash } } : {}),
|
|
272
|
-
};
|
|
273
|
-
await writeJsonFile(contractArtifactFilePath(artifactsDir, name), envelope);
|
|
274
|
-
return envelope;
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Write a TOOL-DERIVED artifact to BOTH path roles: the plain payload at the
|
|
278
|
-
* host-input path `<name>.input.json` and the canonical envelope at
|
|
279
|
-
* `<name>.json`.
|
|
280
|
-
*
|
|
281
|
-
* Why the input path too. Every host-facing artifact path the pipeline renders —
|
|
282
|
-
* both where a role WRITES its output and where it READS its upstreams — is
|
|
283
|
-
* `<name>.input.json` (D3: the host's world is entirely plain input files). An
|
|
284
|
-
* artifact the TOOL derives (the obligation ledger, the finalized contracts, a
|
|
285
|
-
* degenerate seam report, a no-cycles seam resolution, a merged shard aggregate)
|
|
286
|
-
* used to land only in the canonical envelope, so any downstream prompt naming
|
|
287
|
-
* it pointed a worker at a file that never existed. Materializing it here makes
|
|
288
|
-
* that ENOENT class unrepresentable: the write map and the prompts' input map
|
|
289
|
-
* are the same map.
|
|
290
|
-
*
|
|
291
|
-
* Deliberately NOT folded into `writeContractArtifact`: that one is also how
|
|
292
|
-
* INGEST wraps a host-authored payload, and writing back there would mutate the
|
|
293
|
-
* host's own input file in place — the exact separation D3 exists to keep. The
|
|
294
|
-
* derived input file is idempotent for ingest: its semantic projection matches
|
|
295
|
-
* the canonical envelope's, so the ingest idempotency guard skips it on every
|
|
296
|
-
* later pass rather than re-deriving.
|
|
297
|
-
*/
|
|
298
|
-
export async function writeDerivedContractArtifact(artifactsDir, name, payload) {
|
|
299
|
-
await mkdir(contractPipelineDir(artifactsDir), { recursive: true });
|
|
300
|
-
await writeJsonFile(contractInputFilePath(artifactsDir, name), payload);
|
|
301
|
-
return writeContractArtifact(artifactsDir, name, payload);
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* Payload of a stored artifact whether or not it has been enveloped yet. A null
|
|
305
|
-
* envelope (absent on disk) yields undefined; a bare payload that was written
|
|
306
|
-
* without the envelope wrapper is returned as-is. Single-sourced here so every
|
|
307
|
-
* consumer unwraps identically (cannot drift from `isEnvelope`).
|
|
308
|
-
*/
|
|
309
|
-
export function envelopePayload(envelope) {
|
|
310
|
-
if (!envelope)
|
|
311
|
-
return undefined;
|
|
312
|
-
return isEnvelope(envelope) ? envelope.payload : envelope;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Read a stored artifact envelope, or null if absent.
|
|
316
|
-
*
|
|
317
|
-
* Three checks, all of them about IDENTITY — the file at `<name>.json` must BE
|
|
318
|
-
* the artifact `<name>`, not merely a JSON document that was found there:
|
|
319
|
-
*
|
|
320
|
-
* 1. **Shape.** Parsed against {@link isEnvelope}, never cast. The previous
|
|
321
|
-
* body was `readOptionalJsonFile<ContractPipelineArtifactEnvelope>` — a
|
|
322
|
-
* generic TYPE PARAMETER, which is an assertion the compiler erases. A file
|
|
323
|
-
* containing `{"hello":1}` came back typed as an envelope, and every
|
|
324
|
-
* downstream `.artifact_name` / `.payload` read was an unchecked property
|
|
325
|
-
* access on `unknown`-shaped data.
|
|
326
|
-
* 2. **Binding.** `artifact_name` must equal the name that was REQUESTED. The
|
|
327
|
-
* two are the same value by construction on the write path
|
|
328
|
-
* ({@link writeContractArtifact} passes one name to both), so a disagreement
|
|
329
|
-
* means the file was written by something else — a hand edit, a copy, a
|
|
330
|
-
* rename that missed the header. This is not cosmetic: `artifact_name` is
|
|
331
|
-
* the key into `DEPENDENCY_MAP` and `semanticProjection`, and a mismatched
|
|
332
|
-
* name silently reads another artifact's projection table. A mismatched
|
|
333
|
-
* envelope reads as ABSENT, so the caller's staleness DAG re-opens the
|
|
334
|
-
* producing phase rather than consuming bytes that cannot be trusted.
|
|
335
|
-
* 3. **Content hash.** Recomputed from the payload and, when it disagrees with
|
|
336
|
-
* the recorded one, the envelope is returned with
|
|
337
|
-
* {@link ContractPipelineArtifactEnvelope.content_hash} rewritten to the
|
|
338
|
-
* RECOMPUTED value. The payload is authoritative — it is what every
|
|
339
|
-
* consumer reads and what `envelopeSemanticHash` projects — so a header
|
|
340
|
-
* that no longer describes its payload must not be allowed to keep
|
|
341
|
-
* speaking. Reading the payload but reporting the stale header's hash is
|
|
342
|
-
* exactly the failure `detectStaleArtifacts`'s recompute-on-read exists to
|
|
343
|
-
* prevent (see its note on in-place edits), and the hash is the identity
|
|
344
|
-
* the judge/critique repair ledger keys on (`judge_hash` /
|
|
345
|
-
* `critique_hash` in repairState.ts), so a drifted value would make
|
|
346
|
-
* "already repaired for this report" answer about the wrong report.
|
|
347
|
-
*
|
|
348
|
-
* Deliberately NOT a null: treating a payload edit as an absent artifact
|
|
349
|
-
* would erase the distinction the caller needs (absent ⇒ re-emit the
|
|
350
|
-
* producer; edited ⇒ re-stale the downstreams), and it is a real thing
|
|
351
|
-
* hosts and tests do.
|
|
352
|
-
*
|
|
353
|
-
* A shape or binding refusal is silent-by-return (null), not a throw: every
|
|
354
|
-
* caller already handles absent (that IS the fresh-run case), and throwing here
|
|
355
|
-
* would turn one damaged file into a failed `next-step` rather than a re-emitted
|
|
356
|
-
* phase.
|
|
357
|
-
*/
|
|
358
|
-
export async function readContractArtifact(artifactsDir, name) {
|
|
359
|
-
const raw = await readOptionalJsonFile(contractArtifactFilePath(artifactsDir, name));
|
|
360
|
-
if (raw === undefined || raw === null)
|
|
361
|
-
return null;
|
|
362
|
-
if (!isEnvelope(raw))
|
|
363
|
-
return null;
|
|
364
|
-
if (raw.artifact_name !== name)
|
|
365
|
-
return null;
|
|
366
|
-
// Recompute through the SAME `computeHash` the writer used — one serializer
|
|
367
|
-
// for both directions (`stableStringify`, key-order independent), so a
|
|
368
|
-
// round-trip through disk always agrees and only a real payload edit fails.
|
|
369
|
-
// Re-deriving the expression here instead of calling the writer's would be a
|
|
370
|
-
// second copy of the hash definition, which is how a write and a read come to
|
|
371
|
-
// disagree about what "the same payload" means.
|
|
372
|
-
const actualHash = computeHash(raw.payload);
|
|
373
|
-
if (raw.review_provenance && (raw.review_provenance.reviewed_content_hash !== actualHash ||
|
|
374
|
-
reviewIndependenceIssue(raw.review_provenance.requirement, raw.review_provenance.review) !== null))
|
|
375
|
-
return null;
|
|
376
|
-
if (actualHash !== raw.content_hash) {
|
|
377
|
-
reportContentHashMismatch(name, raw.content_hash, actualHash);
|
|
378
|
-
return { ...raw, content_hash: actualHash };
|
|
379
|
-
}
|
|
380
|
-
return raw;
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Detect stale artifacts by walking the dependency DAG transitively.
|
|
384
|
-
* An artifact is stale when:
|
|
385
|
-
* - A dependency artifact is absent/missing.
|
|
386
|
-
* - A dependency artifact's current SEMANTIC-projection hash differs from what
|
|
387
|
-
* was recorded at write time in this artifact's envelope. Cosmetic upstream
|
|
388
|
-
* edits (reworded prose, regenerated timestamps, reordered keys) project to
|
|
389
|
-
* the same hash and do NOT mark downstreams stale (B3).
|
|
390
|
-
*
|
|
391
|
-
* Absent artifacts (never written) are reported under `absent`, not `stale`.
|
|
392
|
-
*/
|
|
393
|
-
export async function detectStaleArtifacts(artifactsDir) {
|
|
394
|
-
const stale = new Set();
|
|
395
|
-
const absent = new Set();
|
|
396
|
-
// Read all present envelopes up front to avoid repeated disk reads.
|
|
397
|
-
const envelopes = new Map();
|
|
398
|
-
for (const name of CP_ARTIFACT_NAMES) {
|
|
399
|
-
envelopes.set(name, await readContractArtifact(artifactsDir, name));
|
|
400
|
-
}
|
|
401
|
-
for (const name of CP_ARTIFACT_NAMES) {
|
|
402
|
-
const envelope = envelopes.get(name);
|
|
403
|
-
if (!envelope) {
|
|
404
|
-
absent.add(name);
|
|
405
|
-
continue;
|
|
406
|
-
}
|
|
407
|
-
// Check each immediate dependency.
|
|
408
|
-
for (const dep of DEPENDENCY_MAP[name]) {
|
|
409
|
-
const depEnvelope = envelopes.get(dep);
|
|
410
|
-
if (!depEnvelope) {
|
|
411
|
-
// Dependency is absent — downstream is stale.
|
|
412
|
-
stale.add(name);
|
|
413
|
-
break;
|
|
414
|
-
}
|
|
415
|
-
const recordedHash = (envelope.dependency_hashes ?? {})[dep];
|
|
416
|
-
if (recordedHash !== envelopeSemanticHash(depEnvelope)) {
|
|
417
|
-
stale.add(name);
|
|
418
|
-
break;
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
// Absence participates in reachability, but remains separate in the result.
|
|
423
|
-
// Preserve the old name-outer/dependency-inner edge order and Set insertion order.
|
|
424
|
-
const reached = new Set([...stale, ...absent]);
|
|
425
|
-
const edges = CP_ARTIFACT_NAMES.flatMap((name) => DEPENDENCY_MAP[name].map((dep) => [dep, name]));
|
|
426
|
-
propagateReachability(reached, edges, () => true);
|
|
427
|
-
return {
|
|
428
|
-
stale: [...reached].filter((name) => !absent.has(name)),
|
|
429
|
-
absent: [...absent],
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
/** Returns true when the artifact file is present on disk. */
|
|
433
|
-
export function contractArtifactExists(artifactsDir, name) {
|
|
434
|
-
return existsSync(contractArtifactFilePath(artifactsDir, name));
|
|
435
|
-
}
|
|
436
|
-
//# sourceMappingURL=artifactStore.js.map
|