sdd-agent-platform 0.4.0 → 0.4.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 +18 -23
- package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js +31 -28
- package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js +3 -2
- package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.d.ts +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js +14 -5
- package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/contracts.d.ts +2 -0
- package/node_modules/@sdd-agent-platform/core/dist/contracts.js +2 -0
- package/node_modules/@sdd-agent-platform/core/dist/contracts.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js +3 -3
- package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js +155 -1
- package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.d.ts +23 -0
- package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js +54 -0
- package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/contracts.d.ts +11 -0
- package/node_modules/@sdd-agent-platform/core/dist/execution/agent-execution-records.js +15 -8
- package/node_modules/@sdd-agent-platform/core/dist/execution/agent-execution-records.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js +14 -6
- package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.d.ts +112 -0
- package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js +145 -0
- package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/instructions.js +36 -36
- package/node_modules/@sdd-agent-platform/core/dist/instructions.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.d.ts +2 -0
- package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js +37 -17
- package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.d.ts +16 -1
- package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js +174 -16
- package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js +2 -2
- package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.d.ts +10 -0
- package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js +31 -1
- package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.d.ts +2 -17
- package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.js +222 -10
- package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js +5 -5
- package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime-config.js +27 -12
- package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime-config.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime.d.ts +59 -1
- package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.d.ts +3 -1
- package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js +191 -0
- package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/router/routing.js +32 -6
- package/node_modules/@sdd-agent-platform/core/dist/router/routing.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/router/runtime-inspection.js +11 -4
- package/node_modules/@sdd-agent-platform/core/dist/router/runtime-inspection.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js +31 -3
- package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js +48 -15
- package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/run-state/events.js +2 -2
- package/node_modules/@sdd-agent-platform/core/dist/run-state/events.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.d.ts +3 -1
- package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js +15 -49
- package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/run-state/invocation-ledger.js +2 -2
- package/node_modules/@sdd-agent-platform/core/dist/run-state/invocation-ledger.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/run-state/model.d.ts +25 -1
- package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js +21 -14
- package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.d.ts +62 -0
- package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js +130 -0
- package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/run-state.d.ts +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/run-state.js +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/run-state.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.d.ts +10 -0
- package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js +44 -14
- package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/context.js +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/context.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.d.ts +4 -0
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js +189 -0
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js +12 -3
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.d.ts +20 -0
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js +101 -21
- package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/status/project-status.d.ts +62 -1
- package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js +192 -4
- package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.d.ts +195 -2
- package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js +499 -2
- package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js +23 -1
- package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.d.ts +19 -0
- package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js +114 -12
- package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js +21 -0
- package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js +16 -2
- package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js +34 -2
- package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js +15 -5
- package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/verification/review-gate.d.ts +22 -0
- package/node_modules/@sdd-agent-platform/core/dist/verification/review-gate.js +53 -0
- package/node_modules/@sdd-agent-platform/core/dist/verification/review-gate.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js +102 -9
- package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.d.ts +16 -1
- package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js +355 -69
- package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.d.ts +58 -0
- package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js +428 -0
- package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.d.ts +2 -0
- package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js +116 -18
- package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/verification.d.ts +2 -0
- package/node_modules/@sdd-agent-platform/core/dist/verification.js +2 -0
- package/node_modules/@sdd-agent-platform/core/dist/verification.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.d.ts +24 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js +182 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.d.ts +4 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js +130 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.d.ts +4 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js +146 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.d.ts +89 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.js +2 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js +16 -1
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.d.ts +8 -4
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.js +25 -11
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.d.ts +38 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js +122 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js.map +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.d.ts +27 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js +166 -37
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state.d.ts +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state.js +1 -0
- package/node_modules/@sdd-agent-platform/core/dist/workflow-state.js.map +1 -1
- package/node_modules/@sdd-agent-platform/core/package.json +1 -1
- package/node_modules/@sdd-agent-platform/core/src/ai-tools.ts +31 -28
- package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-result.test.ts +50 -4
- package/node_modules/@sdd-agent-platform/core/src/config/init-project.test.ts +13 -10
- package/node_modules/@sdd-agent-platform/core/src/config/init-project.ts +3 -2
- package/node_modules/@sdd-agent-platform/core/src/config/starter-documents.ts +15 -5
- package/node_modules/@sdd-agent-platform/core/src/contracts.ts +2 -0
- package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-evidence.ts +3 -3
- package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.test.ts +117 -5
- package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.ts +164 -1
- package/node_modules/@sdd-agent-platform/core/src/evidence/lookup.ts +80 -0
- package/node_modules/@sdd-agent-platform/core/src/evidence-runtime/contracts.ts +12 -0
- package/node_modules/@sdd-agent-platform/core/src/execution/agent-execution-records.ts +16 -11
- package/node_modules/@sdd-agent-platform/core/src/execution/background-executor.test.ts +7 -0
- package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.test.ts +5 -0
- package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.ts +14 -6
- package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.test.ts +102 -0
- package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.ts +271 -0
- package/node_modules/@sdd-agent-platform/core/src/execution/wave-executor.test.ts +4 -0
- package/node_modules/@sdd-agent-platform/core/src/governance/policy.test.ts +2 -0
- package/node_modules/@sdd-agent-platform/core/src/instructions.test.ts +11 -5
- package/node_modules/@sdd-agent-platform/core/src/instructions.ts +36 -36
- package/node_modules/@sdd-agent-platform/core/src/lifecycle/ship.ts +39 -17
- package/node_modules/@sdd-agent-platform/core/src/phase8-contracts.test.ts +3 -2
- package/node_modules/@sdd-agent-platform/core/src/phase8-risk-kernel.test.ts +5 -0
- package/node_modules/@sdd-agent-platform/core/src/planning/task-graph.test.ts +2 -0
- package/node_modules/@sdd-agent-platform/core/src/planning/wave-plan.test.ts +3 -0
- package/node_modules/@sdd-agent-platform/core/src/registries/agent-capability-catalog.ts +269 -17
- package/node_modules/@sdd-agent-platform/core/src/registries/agent-registry.ts +2 -2
- package/node_modules/@sdd-agent-platform/core/src/registries/agent-runtime-static.ts +41 -1
- package/node_modules/@sdd-agent-platform/core/src/registries/capability-sources.ts +238 -15
- package/node_modules/@sdd-agent-platform/core/src/registries/registries.test.ts +27 -2
- package/node_modules/@sdd-agent-platform/core/src/registries/workflow-gates.ts +5 -5
- package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime-config.ts +31 -12
- package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime.ts +66 -1
- package/node_modules/@sdd-agent-platform/core/src/router/route-projection.ts +211 -0
- package/node_modules/@sdd-agent-platform/core/src/router/route-sdd-task.test.ts +151 -3
- package/node_modules/@sdd-agent-platform/core/src/router/routing.ts +35 -6
- package/node_modules/@sdd-agent-platform/core/src/router/runtime-inspection.ts +11 -4
- package/node_modules/@sdd-agent-platform/core/src/router/runtime-validation.ts +32 -3
- package/node_modules/@sdd-agent-platform/core/src/run-state/artifacts.ts +48 -15
- package/node_modules/@sdd-agent-platform/core/src/run-state/events.ts +2 -2
- package/node_modules/@sdd-agent-platform/core/src/run-state/inspect-run.ts +17 -52
- package/node_modules/@sdd-agent-platform/core/src/run-state/invocation-ledger.ts +2 -2
- package/node_modules/@sdd-agent-platform/core/src/run-state/model.ts +28 -1
- package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.test.ts +3 -0
- package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.ts +22 -18
- package/node_modules/@sdd-agent-platform/core/src/run-state/task-evidence.ts +206 -0
- package/node_modules/@sdd-agent-platform/core/src/run-state.ts +1 -0
- package/node_modules/@sdd-agent-platform/core/src/runtime-paths.ts +54 -14
- package/node_modules/@sdd-agent-platform/core/src/sdd-docs/context.ts +1 -1
- package/node_modules/@sdd-agent-platform/core/src/sdd-docs/document-hashes.ts +207 -0
- package/node_modules/@sdd-agent-platform/core/src/sdd-docs/run-binding.ts +12 -3
- package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.test.ts +139 -0
- package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.ts +137 -24
- package/node_modules/@sdd-agent-platform/core/src/status/project-status.ts +268 -5
- package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.test.ts +368 -4
- package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.ts +697 -2
- package/node_modules/@sdd-agent-platform/core/src/sync-back/apply.ts +23 -1
- package/node_modules/@sdd-agent-platform/core/src/sync-back/inspect.ts +145 -12
- package/node_modules/@sdd-agent-platform/core/src/sync-back/sync-back.test.ts +132 -9
- package/node_modules/@sdd-agent-platform/core/src/test-support/fixtures.ts +21 -0
- package/node_modules/@sdd-agent-platform/core/src/test-support/run-state.ts +16 -2
- package/node_modules/@sdd-agent-platform/core/src/verification/goal-verify.test.ts +1 -1
- package/node_modules/@sdd-agent-platform/core/src/verification/goal-verify.ts +38 -5
- package/node_modules/@sdd-agent-platform/core/src/verification/rendering.ts +15 -5
- package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.test.ts +77 -0
- package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.ts +77 -0
- package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.test.ts +64 -4
- package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.ts +110 -12
- package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.test.ts +72 -25
- package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.ts +402 -77
- package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.test.ts +341 -0
- package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.ts +513 -0
- package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.test.ts +144 -5
- package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.ts +129 -18
- package/node_modules/@sdd-agent-platform/core/src/verification.ts +2 -0
- package/node_modules/@sdd-agent-platform/core/src/workflow-gate/evidence-packet.ts +196 -0
- package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.test.ts +171 -0
- package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.ts +143 -0
- package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.test.ts +137 -0
- package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.ts +155 -0
- package/node_modules/@sdd-agent-platform/core/src/workflow-gate/types.ts +114 -0
- package/node_modules/@sdd-agent-platform/core/src/workflow-state/affected-file-conflicts.ts +18 -1
- package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.test.ts +1 -1
- package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.ts +33 -11
- package/node_modules/@sdd-agent-platform/core/src/workflow-state/latest-eligible-run.ts +156 -0
- package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.test.ts +351 -2
- package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.ts +227 -39
- package/node_modules/@sdd-agent-platform/core/src/workflow-state.ts +1 -0
- package/package.json +1 -1
- package/packages/cli/dist/commands/status.js +2 -2
- package/packages/cli/dist/commands/status.js.map +1 -1
- package/packages/cli/dist/commands/sync-back.js +1 -1
- package/packages/cli/dist/commands/sync-back.js.map +1 -1
- package/packages/cli/dist/commands/tasks.js +4 -4
- package/packages/cli/dist/commands/tasks.js.map +1 -1
- package/packages/cli/dist/commands/test.js +94 -5
- package/packages/cli/dist/commands/test.js.map +1 -1
- package/packages/cli/dist/commands/verifies.js +5 -3
- package/packages/cli/dist/commands/verifies.js.map +1 -1
- package/packages/cli/dist/commands/verify.js +48 -7
- package/packages/cli/dist/commands/verify.js.map +1 -1
- package/packages/cli/dist/help.js +32 -18
- package/packages/cli/dist/help.js.map +1 -1
- package/packages/cli/dist/renderers/artifacts.js +1 -1
- package/packages/cli/dist/renderers/artifacts.js.map +1 -1
- package/packages/cli/dist/renderers/registry-runtime.js +7 -2
- package/packages/cli/dist/renderers/registry-runtime.js.map +1 -1
- package/packages/cli/dist/renderers/router.js +4 -2
- package/packages/cli/dist/renderers/router.js.map +1 -1
- package/packages/cli/dist/renderers/workflow.js +33 -12
- package/packages/cli/dist/renderers/workflow.js.map +1 -1
- package/packages/cli/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/cli/package.json +2 -2
- package/packages/core/dist/ai-tools.js +31 -28
- package/packages/core/dist/ai-tools.js.map +1 -1
- package/packages/core/dist/config/init-project.js +3 -2
- package/packages/core/dist/config/init-project.js.map +1 -1
- package/packages/core/dist/config/starter-documents.d.ts +1 -1
- package/packages/core/dist/config/starter-documents.js +14 -5
- package/packages/core/dist/config/starter-documents.js.map +1 -1
- package/packages/core/dist/contracts.d.ts +2 -0
- package/packages/core/dist/contracts.js +2 -0
- package/packages/core/dist/contracts.js.map +1 -1
- package/packages/core/dist/doctor/checks/run-evidence.js +3 -3
- package/packages/core/dist/doctor/checks/run-evidence.js.map +1 -1
- package/packages/core/dist/doctor/doctor.js +155 -1
- package/packages/core/dist/doctor/doctor.js.map +1 -1
- package/packages/core/dist/evidence/lookup.d.ts +23 -0
- package/packages/core/dist/evidence/lookup.js +54 -0
- package/packages/core/dist/evidence/lookup.js.map +1 -0
- package/packages/core/dist/evidence-runtime/contracts.d.ts +11 -0
- package/packages/core/dist/execution/agent-execution-records.js +15 -8
- package/packages/core/dist/execution/agent-execution-records.js.map +1 -1
- package/packages/core/dist/execution/resident-worker.js +14 -6
- package/packages/core/dist/execution/resident-worker.js.map +1 -1
- package/packages/core/dist/execution/stage-team-runtime.d.ts +112 -0
- package/packages/core/dist/execution/stage-team-runtime.js +145 -0
- package/packages/core/dist/execution/stage-team-runtime.js.map +1 -0
- package/packages/core/dist/instructions.js +36 -36
- package/packages/core/dist/instructions.js.map +1 -1
- package/packages/core/dist/lifecycle/ship.d.ts +2 -0
- package/packages/core/dist/lifecycle/ship.js +37 -17
- package/packages/core/dist/lifecycle/ship.js.map +1 -1
- package/packages/core/dist/registries/agent-capability-catalog.d.ts +16 -1
- package/packages/core/dist/registries/agent-capability-catalog.js +174 -16
- package/packages/core/dist/registries/agent-capability-catalog.js.map +1 -1
- package/packages/core/dist/registries/agent-registry.js +2 -2
- package/packages/core/dist/registries/agent-registry.js.map +1 -1
- package/packages/core/dist/registries/agent-runtime-static.d.ts +10 -0
- package/packages/core/dist/registries/agent-runtime-static.js +31 -1
- package/packages/core/dist/registries/agent-runtime-static.js.map +1 -1
- package/packages/core/dist/registries/capability-sources.d.ts +2 -17
- package/packages/core/dist/registries/capability-sources.js +222 -10
- package/packages/core/dist/registries/capability-sources.js.map +1 -1
- package/packages/core/dist/registries/workflow-gates.js +5 -5
- package/packages/core/dist/registries/workflow-gates.js.map +1 -1
- package/packages/core/dist/router/agent-runtime-config.js +27 -12
- package/packages/core/dist/router/agent-runtime-config.js.map +1 -1
- package/packages/core/dist/router/agent-runtime.d.ts +59 -1
- package/packages/core/dist/router/route-projection.d.ts +3 -1
- package/packages/core/dist/router/route-projection.js +191 -0
- package/packages/core/dist/router/route-projection.js.map +1 -1
- package/packages/core/dist/router/routing.js +32 -6
- package/packages/core/dist/router/routing.js.map +1 -1
- package/packages/core/dist/router/runtime-inspection.js +11 -4
- package/packages/core/dist/router/runtime-inspection.js.map +1 -1
- package/packages/core/dist/router/runtime-validation.js +31 -3
- package/packages/core/dist/router/runtime-validation.js.map +1 -1
- package/packages/core/dist/run-state/artifacts.js +48 -15
- package/packages/core/dist/run-state/artifacts.js.map +1 -1
- package/packages/core/dist/run-state/events.js +2 -2
- package/packages/core/dist/run-state/events.js.map +1 -1
- package/packages/core/dist/run-state/inspect-run.d.ts +3 -1
- package/packages/core/dist/run-state/inspect-run.js +15 -49
- package/packages/core/dist/run-state/inspect-run.js.map +1 -1
- package/packages/core/dist/run-state/invocation-ledger.js +2 -2
- package/packages/core/dist/run-state/invocation-ledger.js.map +1 -1
- package/packages/core/dist/run-state/model.d.ts +25 -1
- package/packages/core/dist/run-state/run-state.js +21 -14
- package/packages/core/dist/run-state/run-state.js.map +1 -1
- package/packages/core/dist/run-state/task-evidence.d.ts +62 -0
- package/packages/core/dist/run-state/task-evidence.js +130 -0
- package/packages/core/dist/run-state/task-evidence.js.map +1 -0
- package/packages/core/dist/run-state.d.ts +1 -0
- package/packages/core/dist/run-state.js +1 -0
- package/packages/core/dist/run-state.js.map +1 -1
- package/packages/core/dist/runtime-paths.d.ts +10 -0
- package/packages/core/dist/runtime-paths.js +44 -14
- package/packages/core/dist/runtime-paths.js.map +1 -1
- package/packages/core/dist/sdd-docs/context.js +1 -1
- package/packages/core/dist/sdd-docs/context.js.map +1 -1
- package/packages/core/dist/sdd-docs/document-hashes.d.ts +4 -0
- package/packages/core/dist/sdd-docs/document-hashes.js +189 -0
- package/packages/core/dist/sdd-docs/document-hashes.js.map +1 -0
- package/packages/core/dist/sdd-docs/run-binding.js +12 -3
- package/packages/core/dist/sdd-docs/run-binding.js.map +1 -1
- package/packages/core/dist/sdd-docs/task-parser.d.ts +20 -0
- package/packages/core/dist/sdd-docs/task-parser.js +101 -21
- package/packages/core/dist/sdd-docs/task-parser.js.map +1 -1
- package/packages/core/dist/status/project-status.d.ts +62 -1
- package/packages/core/dist/status/project-status.js +192 -4
- package/packages/core/dist/status/project-status.js.map +1 -1
- package/packages/core/dist/storage/runtime-store.d.ts +195 -2
- package/packages/core/dist/storage/runtime-store.js +499 -2
- package/packages/core/dist/storage/runtime-store.js.map +1 -1
- package/packages/core/dist/sync-back/apply.js +23 -1
- package/packages/core/dist/sync-back/apply.js.map +1 -1
- package/packages/core/dist/sync-back/inspect.d.ts +19 -0
- package/packages/core/dist/sync-back/inspect.js +114 -12
- package/packages/core/dist/sync-back/inspect.js.map +1 -1
- package/packages/core/dist/test-support/fixtures.js +21 -0
- package/packages/core/dist/test-support/fixtures.js.map +1 -1
- package/packages/core/dist/test-support/run-state.js +16 -2
- package/packages/core/dist/test-support/run-state.js.map +1 -1
- package/packages/core/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/core/dist/verification/goal-verify.js +34 -2
- package/packages/core/dist/verification/goal-verify.js.map +1 -1
- package/packages/core/dist/verification/rendering.js +15 -5
- package/packages/core/dist/verification/rendering.js.map +1 -1
- package/packages/core/dist/verification/review-gate.d.ts +22 -0
- package/packages/core/dist/verification/review-gate.js +53 -0
- package/packages/core/dist/verification/review-gate.js.map +1 -0
- package/packages/core/dist/verification/single-task-loop.js +102 -9
- package/packages/core/dist/verification/single-task-loop.js.map +1 -1
- package/packages/core/dist/verification/test-runtime.d.ts +16 -1
- package/packages/core/dist/verification/test-runtime.js +355 -69
- package/packages/core/dist/verification/test-runtime.js.map +1 -1
- package/packages/core/dist/verification/validation-wave.d.ts +58 -0
- package/packages/core/dist/verification/validation-wave.js +428 -0
- package/packages/core/dist/verification/validation-wave.js.map +1 -0
- package/packages/core/dist/verification/verify-contract.d.ts +2 -0
- package/packages/core/dist/verification/verify-contract.js +116 -18
- package/packages/core/dist/verification/verify-contract.js.map +1 -1
- package/packages/core/dist/verification.d.ts +2 -0
- package/packages/core/dist/verification.js +2 -0
- package/packages/core/dist/verification.js.map +1 -1
- package/packages/core/dist/workflow-gate/evidence-packet.d.ts +24 -0
- package/packages/core/dist/workflow-gate/evidence-packet.js +182 -0
- package/packages/core/dist/workflow-gate/evidence-packet.js.map +1 -0
- package/packages/core/dist/workflow-gate/hard-checks.d.ts +4 -0
- package/packages/core/dist/workflow-gate/hard-checks.js +130 -0
- package/packages/core/dist/workflow-gate/hard-checks.js.map +1 -0
- package/packages/core/dist/workflow-gate/policy.d.ts +4 -0
- package/packages/core/dist/workflow-gate/policy.js +146 -0
- package/packages/core/dist/workflow-gate/policy.js.map +1 -0
- package/packages/core/dist/workflow-gate/types.d.ts +89 -0
- package/packages/core/dist/workflow-gate/types.js +2 -0
- package/packages/core/dist/workflow-gate/types.js.map +1 -0
- package/packages/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
- package/packages/core/dist/workflow-state/affected-file-conflicts.js +16 -1
- package/packages/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
- package/packages/core/dist/workflow-state/dependencies.d.ts +8 -4
- package/packages/core/dist/workflow-state/dependencies.js +25 -11
- package/packages/core/dist/workflow-state/dependencies.js.map +1 -1
- package/packages/core/dist/workflow-state/latest-eligible-run.d.ts +38 -0
- package/packages/core/dist/workflow-state/latest-eligible-run.js +122 -0
- package/packages/core/dist/workflow-state/latest-eligible-run.js.map +1 -0
- package/packages/core/dist/workflow-state/resolve.d.ts +27 -0
- package/packages/core/dist/workflow-state/resolve.js +166 -37
- package/packages/core/dist/workflow-state/resolve.js.map +1 -1
- package/packages/core/dist/workflow-state.d.ts +1 -0
- package/packages/core/dist/workflow-state.js +1 -0
- package/packages/core/dist/workflow-state.js.map +1 -1
- package/packages/core/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
|
-
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
|
|
@@ -8,17 +8,17 @@ import { validTaskMarkdown, writeBranchDocs } from '../test-support/fixtures.js'
|
|
|
8
8
|
import { inspectVerifyContract, writeVerifyContract } from './verify-contract.js';
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
test('inspectVerifyContract
|
|
11
|
+
test('inspectVerifyContract blocks when verify document is missing', async () => {
|
|
12
12
|
const root = await mkdtemp(path.join(tmpdir(), 'sdd-verify-contract-missing-'));
|
|
13
13
|
try {
|
|
14
14
|
await writeBranchDocs(root, 'feature', validTaskMarkdown('T1', []));
|
|
15
15
|
|
|
16
16
|
const inspection = await inspectVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
17
17
|
|
|
18
|
-
assert.equal(inspection.status, '
|
|
18
|
+
assert.equal(inspection.status, 'BLOCKED');
|
|
19
19
|
assert.equal(inspection.exists, false);
|
|
20
20
|
assert.equal(inspection.taskCount, 1);
|
|
21
|
-
assert.equal(inspection.issues.some((issue) => issue.field === 'verify.md' && issue.level === '
|
|
21
|
+
assert.equal(inspection.issues.some((issue) => issue.field === 'verify.md' && issue.level === 'FAIL'), true);
|
|
22
22
|
} finally {
|
|
23
23
|
await rm(root, { recursive: true, force: true });
|
|
24
24
|
}
|
|
@@ -34,6 +34,9 @@ test('writeVerifyContract creates task-derived verify contract', async () => {
|
|
|
34
34
|
|
|
35
35
|
assert.equal(written.status, 'created');
|
|
36
36
|
assert.match(written.content, /contract: sdd-verify-doc-v1/);
|
|
37
|
+
assert.match(written.content, /verification_batches:/);
|
|
38
|
+
assert.match(written.content, /id: \"task-T1\"/);
|
|
39
|
+
assert.match(written.content, /failure_policy:\n repair_flow: deferred/);
|
|
37
40
|
assert.match(written.content, /\| T1 \|/);
|
|
38
41
|
assert.match(written.content, /author_role: verification-designer/);
|
|
39
42
|
assert.match(written.content, /independent_from_roles:\n - task-planner\n - implementer/);
|
|
@@ -47,6 +50,87 @@ test('writeVerifyContract creates task-derived verify contract', async () => {
|
|
|
47
50
|
}
|
|
48
51
|
});
|
|
49
52
|
|
|
53
|
+
test('writeVerifyContract groups tasks by validation_batch', async () => {
|
|
54
|
+
const root = await mkdtemp(path.join(tmpdir(), 'sdd-verify-contract-batch-'));
|
|
55
|
+
try {
|
|
56
|
+
await writeBranchDocs(root, 'feature', `# Tasks
|
|
57
|
+
|
|
58
|
+
### T1: UI copy
|
|
59
|
+
|
|
60
|
+
\`\`\`sdd-task
|
|
61
|
+
id: T1
|
|
62
|
+
status: pending
|
|
63
|
+
wave: 1
|
|
64
|
+
depends_on: []
|
|
65
|
+
acceptance_refs:
|
|
66
|
+
- AC-T1-copy
|
|
67
|
+
affected_files:
|
|
68
|
+
- app/src/main/webapp/index.jsp
|
|
69
|
+
change_surface: frontend_only
|
|
70
|
+
implementation_wave: ui-wave-1
|
|
71
|
+
validation_batch: ui-render-wave-1
|
|
72
|
+
validation_timing: batch_end
|
|
73
|
+
requires_verify_before_next: false
|
|
74
|
+
validation:
|
|
75
|
+
- browser/manual check copy => AC-T1-copy
|
|
76
|
+
required_artifacts:
|
|
77
|
+
- artifacts/ui-render-wave-1.md
|
|
78
|
+
risk: []
|
|
79
|
+
\`\`\`
|
|
80
|
+
|
|
81
|
+
#### Boundary
|
|
82
|
+
|
|
83
|
+
Only UI copy.
|
|
84
|
+
|
|
85
|
+
#### Acceptance
|
|
86
|
+
|
|
87
|
+
- Copy renders.
|
|
88
|
+
|
|
89
|
+
### T2: UI image
|
|
90
|
+
|
|
91
|
+
\`\`\`sdd-task
|
|
92
|
+
id: T2
|
|
93
|
+
status: pending
|
|
94
|
+
wave: 1
|
|
95
|
+
depends_on: []
|
|
96
|
+
acceptance_refs:
|
|
97
|
+
- AC-T2-image
|
|
98
|
+
affected_files:
|
|
99
|
+
- app/src/main/webapp/assets/banner.svg
|
|
100
|
+
change_surface: frontend_only
|
|
101
|
+
implementation_wave: ui-wave-1
|
|
102
|
+
validation_batch: ui-render-wave-1
|
|
103
|
+
validation_timing: batch_end
|
|
104
|
+
requires_verify_before_next: false
|
|
105
|
+
validation:
|
|
106
|
+
- browser/manual check image => AC-T2-image
|
|
107
|
+
required_artifacts:
|
|
108
|
+
- artifacts/ui-render-wave-1.md
|
|
109
|
+
risk: []
|
|
110
|
+
\`\`\`
|
|
111
|
+
|
|
112
|
+
#### Boundary
|
|
113
|
+
|
|
114
|
+
Only UI image.
|
|
115
|
+
|
|
116
|
+
#### Acceptance
|
|
117
|
+
|
|
118
|
+
- Image renders.
|
|
119
|
+
`);
|
|
120
|
+
|
|
121
|
+
const written = await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
122
|
+
|
|
123
|
+
assert.match(written.content, /id: \"ui-render-wave-1\"/);
|
|
124
|
+
assert.match(written.content, /timing: batch_end/);
|
|
125
|
+
assert.match(written.content, /change_surface: frontend_only/);
|
|
126
|
+
assert.match(written.content, /forbidden_validation:\n - \"maven_compile\"\n - \"gradle_build\"/);
|
|
127
|
+
assert.match(written.content, /T1:\n - \"AC-T1-copy\"/);
|
|
128
|
+
assert.match(written.content, /T2:\n - \"AC-T2-image\"/);
|
|
129
|
+
} finally {
|
|
130
|
+
await rm(root, { recursive: true, force: true });
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
50
134
|
test('inspectVerifyContract warns when verify document is stale', async () => {
|
|
51
135
|
const root = await mkdtemp(path.join(tmpdir(), 'sdd-verify-contract-stale-'));
|
|
52
136
|
try {
|
|
@@ -57,9 +141,64 @@ test('inspectVerifyContract warns when verify document is stale', async () => {
|
|
|
57
141
|
const inspection = await inspectVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
58
142
|
|
|
59
143
|
assert.equal(inspection.status, 'WARN');
|
|
60
|
-
assert.equal(inspection.issues.some((issue) => issue.field === '
|
|
144
|
+
assert.equal(inspection.issues.some((issue) => issue.field === 'based_on_tasks_contract_hash'), true);
|
|
61
145
|
assert.equal(inspection.issues.some((issue) => issue.field === 'tasks' && /T2/.test(issue.message)), true);
|
|
62
146
|
} finally {
|
|
63
147
|
await rm(root, { recursive: true, force: true });
|
|
64
148
|
}
|
|
65
149
|
});
|
|
150
|
+
|
|
151
|
+
test('inspectVerifyContract blocks legacy verify documents without tasks contract hash', async () => {
|
|
152
|
+
const root = await mkdtemp(path.join(tmpdir(), 'sdd-verify-contract-legacy-'));
|
|
153
|
+
try {
|
|
154
|
+
await writeBranchDocs(root, 'feature', validTaskMarkdown('T1', []));
|
|
155
|
+
const written = await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
156
|
+
await writeFile(path.join(root, 'specs', 'feature', 'verify.md'), written.content.replace(/^based_on_tasks_contract_hash: .+\n/m, ''), 'utf8');
|
|
157
|
+
|
|
158
|
+
const inspection = await inspectVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
159
|
+
|
|
160
|
+
assert.equal(inspection.status, 'BLOCKED');
|
|
161
|
+
assert.equal(inspection.issues.some((issue) => issue.field === 'based_on_tasks_contract_hash' && issue.level === 'FAIL'), true);
|
|
162
|
+
} finally {
|
|
163
|
+
await rm(root, { recursive: true, force: true });
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('writeVerifyContract upgrades legacy verify documents without force', async () => {
|
|
168
|
+
const root = await mkdtemp(path.join(tmpdir(), 'sdd-verify-contract-upgrade-'));
|
|
169
|
+
try {
|
|
170
|
+
await writeBranchDocs(root, 'feature', validTaskMarkdown('T1', []));
|
|
171
|
+
const written = await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
172
|
+
await writeFile(path.join(root, 'specs', 'feature', 'verify.md'), written.content.replace(/^based_on_tasks_contract_hash: .+\n/m, ''), 'utf8');
|
|
173
|
+
|
|
174
|
+
const upgraded = await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
175
|
+
const inspection = await inspectVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
176
|
+
|
|
177
|
+
assert.equal(upgraded.status, 'updated');
|
|
178
|
+
assert.match(upgraded.content, /based_on_tasks_contract_hash: /);
|
|
179
|
+
assert.equal(inspection.status, 'PASS');
|
|
180
|
+
} finally {
|
|
181
|
+
await rm(root, { recursive: true, force: true });
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('writeVerifyContract preserves stale bound verify documents without force', async () => {
|
|
186
|
+
const root = await mkdtemp(path.join(tmpdir(), 'sdd-verify-contract-preserve-stale-'));
|
|
187
|
+
try {
|
|
188
|
+
await writeBranchDocs(root, 'feature', validTaskMarkdown('T1', []));
|
|
189
|
+
const written = await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
190
|
+
const verifyPath = path.join(root, 'specs', 'feature', 'verify.md');
|
|
191
|
+
const initial = await readFile(verifyPath, 'utf8');
|
|
192
|
+
await writeFile(path.join(root, 'specs', 'feature', 'tasks.md'), validTaskMarkdown('T2', []), 'utf8');
|
|
193
|
+
|
|
194
|
+
const preserved = await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
195
|
+
const inspection = await inspectVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
196
|
+
|
|
197
|
+
assert.equal(written.status, 'created');
|
|
198
|
+
assert.equal(preserved.status, 'unchanged');
|
|
199
|
+
assert.equal(preserved.content, initial);
|
|
200
|
+
assert.equal(inspection.status, 'WARN');
|
|
201
|
+
} finally {
|
|
202
|
+
await rm(root, { recursive: true, force: true });
|
|
203
|
+
}
|
|
204
|
+
});
|
|
@@ -27,6 +27,8 @@ export interface VerifyContractInspection {
|
|
|
27
27
|
status: VerifyContractStatus;
|
|
28
28
|
basedOnTasksHash: string | null;
|
|
29
29
|
currentTasksHash: string | null;
|
|
30
|
+
basedOnTasksContractHash: string | null;
|
|
31
|
+
currentTasksContractHash: string | null;
|
|
30
32
|
issues: VerifyContractIssue[];
|
|
31
33
|
taskCount: number;
|
|
32
34
|
authorRole: VerifyContractAuthorRole | null;
|
|
@@ -58,10 +60,10 @@ export async function inspectVerifyContract(projectRoot: string, options: { bran
|
|
|
58
60
|
|
|
59
61
|
if (!model.documents.verifyExists || raw === null) {
|
|
60
62
|
issues.push({
|
|
61
|
-
level: '
|
|
63
|
+
level: 'FAIL',
|
|
62
64
|
field: 'verify.md',
|
|
63
65
|
message: 'Verification contract document is missing.',
|
|
64
|
-
action: `Run sdd verifies write --branch ${context.partition} to create specs/${context.partition}/verify.md.`
|
|
66
|
+
action: `Run /sdd:tasks or sdd verifies write --branch ${context.partition} to create specs/${context.partition}/verify.md before /sdd:test.`
|
|
65
67
|
});
|
|
66
68
|
} else {
|
|
67
69
|
if (!raw.includes(`contract: ${VERIFY_DOCUMENT_CONTRACT_VERSION}`)) {
|
|
@@ -72,12 +74,23 @@ export async function inspectVerifyContract(projectRoot: string, options: { bran
|
|
|
72
74
|
action: 'Regenerate verify.md with sdd verifies write or update the frontmatter contract.'
|
|
73
75
|
});
|
|
74
76
|
}
|
|
77
|
+
if (!model.documents.verifyBasedOnTasksContractHash) {
|
|
78
|
+
issues.push({
|
|
79
|
+
level: 'FAIL',
|
|
80
|
+
field: 'based_on_tasks_contract_hash',
|
|
81
|
+
message: 'verify.md does not bind to the frozen tasks contract hash.',
|
|
82
|
+
action: `Run /sdd:tasks or sdd verifies write --branch ${context.partition} --force to regenerate verify.md from the current tasks contract.`
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
75
86
|
if (model.documents.verifyStale) {
|
|
76
87
|
issues.push({
|
|
77
|
-
level: 'WARN',
|
|
78
|
-
field: '
|
|
79
|
-
message:
|
|
80
|
-
|
|
88
|
+
level: model.documents.verifyBasedOnTasksContractHash ? 'WARN' : 'FAIL',
|
|
89
|
+
field: 'based_on_tasks_contract_hash',
|
|
90
|
+
message: model.documents.verifyBasedOnTasksContractHash
|
|
91
|
+
? `verify.md is stale for current tasks contract hash ${model.documents.tasksContractHash}.`
|
|
92
|
+
: 'verify.md cannot be proven current because based_on_tasks_contract_hash is missing.',
|
|
93
|
+
action: `Run /sdd:tasks or sdd verifies write --branch ${context.partition} --force after reviewing task contract changes.`
|
|
81
94
|
});
|
|
82
95
|
}
|
|
83
96
|
const authorRole = readDocumentScalar(raw, 'author_role');
|
|
@@ -86,7 +99,7 @@ export async function inspectVerifyContract(projectRoot: string, options: { bran
|
|
|
86
99
|
level: 'WARN',
|
|
87
100
|
field: 'author_role',
|
|
88
101
|
message: `verify.md must be owned by ${VERIFY_CONTRACT_AUTHOR_ROLE}, not ${authorRole ?? 'missing'}.`,
|
|
89
|
-
action: 'Regenerate verify.md with a verification-designer role before running
|
|
102
|
+
action: 'Regenerate verify.md with a verification-designer role before running sdd test task.'
|
|
90
103
|
});
|
|
91
104
|
}
|
|
92
105
|
const independentFromRoles = readDocumentList(raw, 'independent_from_roles');
|
|
@@ -100,6 +113,14 @@ export async function inspectVerifyContract(projectRoot: string, options: { bran
|
|
|
100
113
|
});
|
|
101
114
|
}
|
|
102
115
|
}
|
|
116
|
+
if (!/^verification_batches:\s*$/m.test(raw)) {
|
|
117
|
+
issues.push({
|
|
118
|
+
level: 'FAIL',
|
|
119
|
+
field: 'verification_batches',
|
|
120
|
+
message: 'verify.md does not declare verification_batches from the frozen tasks contract.',
|
|
121
|
+
action: `Run /sdd:tasks or sdd verifies write --branch ${context.partition} --force to regenerate verify.md as a batch/wave validation plan.`
|
|
122
|
+
});
|
|
123
|
+
}
|
|
103
124
|
for (const task of model.tasks) {
|
|
104
125
|
if (!new RegExp(`\\b${escapeRegex(task.id)}\\b`).test(raw)) {
|
|
105
126
|
issues.push({
|
|
@@ -120,6 +141,8 @@ export async function inspectVerifyContract(projectRoot: string, options: { bran
|
|
|
120
141
|
status: issues.some((issue) => issue.level === 'FAIL') ? 'BLOCKED' : issues.length > 0 ? 'WARN' : 'PASS',
|
|
121
142
|
basedOnTasksHash: model.documents.verifyBasedOnTasksHash ?? null,
|
|
122
143
|
currentTasksHash: model.documents.tasksHash ?? null,
|
|
144
|
+
basedOnTasksContractHash: model.documents.verifyBasedOnTasksContractHash ?? null,
|
|
145
|
+
currentTasksContractHash: model.documents.tasksContractHash ?? null,
|
|
123
146
|
issues,
|
|
124
147
|
taskCount: model.tasks.length,
|
|
125
148
|
authorRole: raw ? readDocumentScalar(raw, 'author_role') as VerifyContractAuthorRole | null : null,
|
|
@@ -134,13 +157,18 @@ export async function writeVerifyContract(projectRoot: string, options: { branch
|
|
|
134
157
|
const existed = await exists(model.verifyPath);
|
|
135
158
|
if (existed && !options.force) {
|
|
136
159
|
const current = await readFile(model.verifyPath, 'utf8');
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
160
|
+
const currentTasksContractHash = readDocumentScalar(current, 'based_on_tasks_contract_hash');
|
|
161
|
+
const hasCurrentBatchPlan = /^verification_batches:\s*$/m.test(current);
|
|
162
|
+
const hasContractBinding = Boolean(currentTasksContractHash && currentTasksContractHash !== 'missing');
|
|
163
|
+
if (current === content || (hasContractBinding && hasCurrentBatchPlan)) {
|
|
164
|
+
return {
|
|
165
|
+
branch: context.partition,
|
|
166
|
+
verifyPath: model.verifyPath,
|
|
167
|
+
relativePath: `specs/${context.partition}/verify.md`,
|
|
168
|
+
status: 'unchanged',
|
|
169
|
+
content: current
|
|
170
|
+
};
|
|
171
|
+
}
|
|
144
172
|
}
|
|
145
173
|
await mkdir(path.dirname(model.verifyPath), { recursive: true });
|
|
146
174
|
await writeFile(model.verifyPath, content, 'utf8');
|
|
@@ -158,6 +186,7 @@ export function renderVerifyContractDocument(model: SddTaskModel, timestamp: str
|
|
|
158
186
|
contract: ${VERIFY_DOCUMENT_CONTRACT_VERSION}
|
|
159
187
|
version: 1.0.0
|
|
160
188
|
branch: ${model.branch}
|
|
189
|
+
based_on_tasks_contract_hash: ${model.documents.tasksContractHash ?? 'missing'}
|
|
161
190
|
based_on_tasks_hash: ${model.documents.tasksHash ?? 'missing'}
|
|
162
191
|
author_role: ${VERIFY_CONTRACT_AUTHOR_ROLE}
|
|
163
192
|
independent_from_roles:
|
|
@@ -172,13 +201,18 @@ updated_at: ${timestamp}
|
|
|
172
201
|
|
|
173
202
|
This document maps executable SDD tasks to verification expectations. It is derived from specs/${model.branch}/tasks.md and is not runtime evidence. It is owned by the verification-designer role and must remain independent from task planning and implementation authority.
|
|
174
203
|
|
|
175
|
-
## 2.
|
|
204
|
+
## 2. Verification Batches
|
|
205
|
+
|
|
206
|
+
verification_batches:
|
|
207
|
+
${model.tasks.length > 0 ? renderVerificationBatches(model.tasks) : ' []'}
|
|
208
|
+
|
|
209
|
+
## 3. Task Verification Matrix
|
|
176
210
|
|
|
177
211
|
| Task | Acceptance refs | Validation commands | Required artifacts | Verification availability |
|
|
178
212
|
|---|---|---|---|---|
|
|
179
213
|
${model.tasks.length > 0 ? model.tasks.map(renderTaskMatrixRow).join('\n') : '| none | none | none | none | none |'}
|
|
180
214
|
|
|
181
|
-
##
|
|
215
|
+
## 4. Verification Rules
|
|
182
216
|
|
|
183
217
|
- The agent that creates tasks.md must not be the same authority that owns verify.md.
|
|
184
218
|
- The implementer must not own verify.md or perform authoritative goal verification.
|
|
@@ -186,15 +220,92 @@ ${model.tasks.length > 0 ? model.tasks.map(renderTaskMatrixRow).join('\n') : '|
|
|
|
186
220
|
- Physical evidence files live under branch evidence .sdd/runs/<branchSlug>/evidence/artifacts/.
|
|
187
221
|
- Goal-level verify must resolve the latest eligible run by branch and task unless --run is explicitly supplied for replay.
|
|
188
222
|
- PASS requires policy-backed acceptance evidence, not mention-only acceptance text.
|
|
189
|
-
-
|
|
223
|
+
- \`/sdd:test\` consumes this contract and must not create or refresh it.
|
|
224
|
+
- Low-level sync-back may inspect or replay the generated proposal for diagnostic/recovery use, but normal workflow completion proceeds through test judgment and ship readiness.
|
|
190
225
|
|
|
191
|
-
##
|
|
226
|
+
## 5. Out of Scope
|
|
192
227
|
|
|
193
228
|
- This document does not replace runtime.sqlite, branch evidence artifacts, validator reports, or sync-back proposals.
|
|
194
229
|
- This document does not authorize publish, push, tag, release, or source changes outside the selected task boundary.
|
|
195
230
|
`;
|
|
196
231
|
}
|
|
197
232
|
|
|
233
|
+
interface VerificationBatch {
|
|
234
|
+
id: string;
|
|
235
|
+
tasks: SddTask[];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function renderVerificationBatches(tasks: SddTask[]): string {
|
|
239
|
+
const batches = new Map<string, VerificationBatch>();
|
|
240
|
+
for (const task of tasks) {
|
|
241
|
+
const id = task.validationBatch ?? `task-${task.id}`;
|
|
242
|
+
const existing = batches.get(id);
|
|
243
|
+
if (existing) {
|
|
244
|
+
existing.tasks.push(task);
|
|
245
|
+
} else {
|
|
246
|
+
batches.set(id, { id, tasks: [task] });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return Array.from(batches.values()).map(renderVerificationBatch).join('\n');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function renderVerificationBatch(batch: VerificationBatch): string {
|
|
253
|
+
const timing = batch.tasks.some((task) => task.validationTiming === 'wave_end') ? 'wave_end' : batch.tasks.some((task) => task.validationTiming === 'batch_end') ? 'batch_end' : 'task_end';
|
|
254
|
+
const changeSurface = unique(batch.tasks.map((task) => task.changeSurface)).length === 1 ? batch.tasks[0].changeSurface : 'mixed';
|
|
255
|
+
const requiredArtifacts = unique(batch.tasks.flatMap((task) => task.requiredArtifacts));
|
|
256
|
+
const forbiddenValidation = changeSurface === 'frontend_only' ? ['maven_compile', 'gradle_build'] : [];
|
|
257
|
+
return [
|
|
258
|
+
` - id: ${quoteYaml(batch.id)}`,
|
|
259
|
+
` timing: ${timing}`,
|
|
260
|
+
` tasks:`,
|
|
261
|
+
...batch.tasks.map((task) => ` - ${quoteYaml(task.id)}`),
|
|
262
|
+
` change_surface: ${changeSurface}`,
|
|
263
|
+
` checks:`,
|
|
264
|
+
...renderBatchChecks(batch.tasks),
|
|
265
|
+
` forbidden_validation:${renderInlineOrNestedList(forbiddenValidation, 6)}`,
|
|
266
|
+
` required_artifacts:${renderInlineOrNestedList(requiredArtifacts, 6)}`,
|
|
267
|
+
` acceptance_mapping:`,
|
|
268
|
+
...renderAcceptanceMapping(batch.tasks),
|
|
269
|
+
` failure_policy:`,
|
|
270
|
+
` repair_flow: deferred`,
|
|
271
|
+
` rerun_scope: pending_design`
|
|
272
|
+
].join('\n');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function renderBatchChecks(tasks: SddTask[]): string[] {
|
|
276
|
+
const checks = unique(tasks.flatMap((task) => task.validation));
|
|
277
|
+
return checks.length > 0 ? checks.map((check) => ` - ${quoteYaml(check)}`) : [' []'];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function renderAcceptanceMapping(tasks: SddTask[]): string[] {
|
|
281
|
+
const lines: string[] = [];
|
|
282
|
+
for (const task of tasks) {
|
|
283
|
+
lines.push(` ${task.id}:`);
|
|
284
|
+
if (task.acceptanceRefs.length > 0) {
|
|
285
|
+
lines.push(...task.acceptanceRefs.map((ref) => ` - ${quoteYaml(ref)}`));
|
|
286
|
+
} else {
|
|
287
|
+
lines.push(' []');
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return lines;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function renderInlineOrNestedList(values: string[], indent: number): string {
|
|
294
|
+
if (values.length === 0) {
|
|
295
|
+
return ' []';
|
|
296
|
+
}
|
|
297
|
+
const spaces = ' '.repeat(indent);
|
|
298
|
+
return `\n${values.map((value) => `${spaces}- ${quoteYaml(value)}`).join('\n')}`;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function unique(values: string[]): string[] {
|
|
302
|
+
return Array.from(new Set(values.filter(Boolean)));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function quoteYaml(value: string): string {
|
|
306
|
+
return JSON.stringify(value);
|
|
307
|
+
}
|
|
308
|
+
|
|
198
309
|
function renderTaskMatrixRow(task: SddTask): string {
|
|
199
310
|
return `| ${task.id} | ${cell(task.acceptanceRefs)} | ${cell(task.validation)} | ${cell(task.requiredArtifacts)} | ${cell(task.verificationAvailability)} |`;
|
|
200
311
|
}
|
|
@@ -4,3 +4,5 @@ export type { GoalVerifyResultLike, SingleTaskLoopResultLike } from './verificat
|
|
|
4
4
|
export * from './verification/single-task-loop.js';
|
|
5
5
|
export * from './verification/verify-contract.js';
|
|
6
6
|
export * from './verification/test-runtime.js';
|
|
7
|
+
export * from './verification/validation-wave.js';
|
|
8
|
+
export * from './verification/review-gate.js';
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { WORKFLOW_GATE_RUNTIME_CONTRACT_VERSION } from '../contracts.js';
|
|
4
|
+
import { listRuntimeArtifactPayloads, listRuntimeDurableGaps, listRuntimeFanInEvidenceSets, listRuntimeLlmAdvisorAssessments, listRuntimeSyncBackDecisions, recordRuntimeWorkflowGateDecision, runtimeScopedId, type RuntimeArtifactPayloadRecord } from '../storage/runtime-store.js';
|
|
5
|
+
import { getEvidenceAttachmentPath } from '../runtime-paths.js';
|
|
6
|
+
import { readAllRunStates } from '../run-state/run-state.js';
|
|
7
|
+
import { affectedFileConflictsForSelectedRuns } from '../workflow-state/affected-file-conflicts.js';
|
|
8
|
+
import { resolveWorkflowState } from '../workflow-state/resolve.js';
|
|
9
|
+
import { evaluateWorkflowGateHardChecks } from './hard-checks.js';
|
|
10
|
+
import { synthesizeWorkflowGateDecision } from './policy.js';
|
|
11
|
+
import type { WorkflowGateDecision, WorkflowGateDecisionKind, WorkflowGateEvidencePacket } from './types.js';
|
|
12
|
+
|
|
13
|
+
export async function buildWorkflowGateEvidencePacket(projectRoot: string, input: { branch?: string | null; taskId?: string | null; runId?: string | null; decisionKind: WorkflowGateDecisionKind; waveRunId?: string | null; taskIds?: string[]; runIds?: string[]; evidenceRefs?: string[] }): Promise<WorkflowGateEvidencePacket> {
|
|
14
|
+
const workflow = await resolveWorkflowState(projectRoot, { branch: input.branch, branchSource: input.branch ? 'cli_option' : undefined, taskId: input.taskId ?? null });
|
|
15
|
+
const taskId = input.taskId ?? workflow.latestRun?.taskId ?? workflow.model.tasks[0]?.id ?? null;
|
|
16
|
+
const selection = taskId ? workflow.latestEligibleRunsByTask.find((candidate) => candidate.taskId === taskId) ?? null : null;
|
|
17
|
+
const runId = input.runId ?? selection?.selected?.runId ?? workflow.latestRun?.runId ?? null;
|
|
18
|
+
const scopedTaskIds = sortedUnique(input.taskIds ?? (taskId ? [taskId] : []));
|
|
19
|
+
const scopedLatestEligibleSelections = scopedTaskIds.length > 0
|
|
20
|
+
? scopedTaskIds.map((scopedTaskId) => workflow.latestEligibleRunsByTask.find((candidate) => candidate.taskId === scopedTaskId) ?? emptyLatestEligibleSelection(workflow.branch, scopedTaskId))
|
|
21
|
+
: (selection ? [selection] : []);
|
|
22
|
+
const scopedRunIds = sortedUnique(input.runIds ?? scopedLatestEligibleSelections.flatMap((candidate) => candidate.selected ? [candidate.selected.runId] : []));
|
|
23
|
+
const workflowScope = {
|
|
24
|
+
waveRunId: input.waveRunId ?? null,
|
|
25
|
+
taskIds: scopedTaskIds,
|
|
26
|
+
runIds: scopedRunIds.length > 0 ? scopedRunIds : sortedUnique(runId ? [runId] : []),
|
|
27
|
+
evidenceRefs: sortedUnique(input.evidenceRefs ?? [])
|
|
28
|
+
};
|
|
29
|
+
const scopedTasks = workflowScope.taskIds.length > 0
|
|
30
|
+
? workflow.model.tasks.filter((candidate) => workflowScope.taskIds.includes(candidate.id))
|
|
31
|
+
: workflow.model.tasks.filter((candidate) => candidate.id === taskId);
|
|
32
|
+
const runtimeInputs = await loadRuntimeGateInputs(projectRoot, workflow.branch, workflowScope.taskIds, workflowScope.runIds);
|
|
33
|
+
const scopedAffectedFileConflicts = await loadScopedAffectedFileConflicts(projectRoot, workflow.affectedFileConflicts, workflowScope.runIds);
|
|
34
|
+
const packetBase = {
|
|
35
|
+
packetId: runtimeScopedId(WORKFLOW_GATE_RUNTIME_CONTRACT_VERSION, workflow.branch, taskId ?? 'none', runId ?? 'none', input.decisionKind),
|
|
36
|
+
generatedAt: new Date().toISOString(),
|
|
37
|
+
decisionKind: input.decisionKind,
|
|
38
|
+
partition: workflow.branch,
|
|
39
|
+
taskId,
|
|
40
|
+
runId,
|
|
41
|
+
documents: workflow.documents,
|
|
42
|
+
latestEligibleSelection: selection,
|
|
43
|
+
latestEligibleSelections: scopedLatestEligibleSelections,
|
|
44
|
+
workflowScope,
|
|
45
|
+
runtimeHealth: runtimeInputs.runtimeHealth,
|
|
46
|
+
durableGaps: runtimeInputs.durableGaps,
|
|
47
|
+
dependencyBlockers: workflow.dependencyBlockers,
|
|
48
|
+
affectedFileConflicts: scopedAffectedFileConflicts,
|
|
49
|
+
syncBackDecision: runtimeInputs.syncBackDecisions[0] ?? null,
|
|
50
|
+
syncBackDecisions: runtimeInputs.syncBackDecisions,
|
|
51
|
+
fanInEvidenceSets: runtimeInputs.fanInEvidenceSets,
|
|
52
|
+
advisorAssessments: runtimeInputs.advisorAssessments,
|
|
53
|
+
canonicalEvidenceRefs: sortedUnique([...workflowScope.evidenceRefs, ...runtimeInputs.payloads.filter((payload) => payload.status === 'active').map((payload) => payload.logicalRef)]),
|
|
54
|
+
requiredArtifactRefs: sortedUnique(scopedTasks.flatMap((task) => task.requiredArtifacts)),
|
|
55
|
+
artifactPayloadHealth: await inspectArtifactPayloadHealth(projectRoot, runtimeInputs.payloads.filter((payload) => payload.status === 'active'))
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
...packetBase,
|
|
59
|
+
hardChecks: evaluateWorkflowGateHardChecks(packetBase)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function emptyLatestEligibleSelection(partition: string, taskId: string): WorkflowGateEvidencePacket['latestEligibleSelections'][number] {
|
|
64
|
+
return {
|
|
65
|
+
partition,
|
|
66
|
+
taskId,
|
|
67
|
+
selected: null,
|
|
68
|
+
candidates: [],
|
|
69
|
+
rejected: []
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function loadScopedAffectedFileConflicts(projectRoot: string, fallback: WorkflowGateEvidencePacket['affectedFileConflicts'], runIds: string[]): Promise<WorkflowGateEvidencePacket['affectedFileConflicts']> {
|
|
74
|
+
if (runIds.length === 0) {
|
|
75
|
+
return fallback;
|
|
76
|
+
}
|
|
77
|
+
const states = await readAllRunStates(projectRoot);
|
|
78
|
+
const selectedRuns = states.filter((state) => runIds.includes(state.runId));
|
|
79
|
+
return affectedFileConflictsForSelectedRuns(states, selectedRuns);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function loadRuntimeGateInputs(projectRoot: string, partition: string, taskIds: string[], runIds: string[]): Promise<{
|
|
83
|
+
runtimeHealth: WorkflowGateEvidencePacket['runtimeHealth'];
|
|
84
|
+
durableGaps: WorkflowGateEvidencePacket['durableGaps'];
|
|
85
|
+
syncBackDecisions: NonNullable<WorkflowGateEvidencePacket['syncBackDecision']>[];
|
|
86
|
+
fanInEvidenceSets: WorkflowGateEvidencePacket['fanInEvidenceSets'];
|
|
87
|
+
advisorAssessments: WorkflowGateEvidencePacket['advisorAssessments'];
|
|
88
|
+
payloads: RuntimeArtifactPayloadRecord[];
|
|
89
|
+
}> {
|
|
90
|
+
try {
|
|
91
|
+
const runtimeScopes = scopedRuntimeQueries(taskIds, runIds);
|
|
92
|
+
const [durableGapResults, syncBackDecisionResults, fanInEvidenceSetResults, advisorAssessmentResults, payloadResults] = await Promise.all([
|
|
93
|
+
Promise.all(runtimeScopes.map((scope) => listRuntimeDurableGaps(projectRoot, { partition, taskId: scope.taskId, runId: scope.runId, status: 'open_terminal' }))),
|
|
94
|
+
Promise.all(runIds.map((scopedRunId) => listRuntimeSyncBackDecisions(projectRoot, scopedRunId))),
|
|
95
|
+
Promise.all(runtimeScopes.map((scope) => listRuntimeFanInEvidenceSets(projectRoot, { partition, taskId: scope.taskId, runId: scope.runId }))),
|
|
96
|
+
Promise.all(runtimeScopes.map((scope) => listRuntimeLlmAdvisorAssessments(projectRoot, { partition, taskId: scope.taskId, runId: scope.runId }))),
|
|
97
|
+
Promise.all(runIds.map((scopedRunId) => listRuntimeArtifactPayloads(projectRoot, { runId: scopedRunId })))
|
|
98
|
+
]);
|
|
99
|
+
return {
|
|
100
|
+
runtimeHealth: { status: 'ok', issues: [] },
|
|
101
|
+
durableGaps: uniqueBy(durableGapResults.flat(), (gap) => gap.gapId),
|
|
102
|
+
syncBackDecisions: uniqueBy(syncBackDecisionResults.flat(), (decision) => decision.decisionId),
|
|
103
|
+
fanInEvidenceSets: uniqueBy(fanInEvidenceSetResults.flat(), (evidenceSet) => evidenceSet.fanInId),
|
|
104
|
+
advisorAssessments: uniqueBy(advisorAssessmentResults.flat(), (assessment) => assessment.assessmentId),
|
|
105
|
+
payloads: uniqueBy(payloadResults.flat(), (payload) => payload.payloadId)
|
|
106
|
+
};
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return {
|
|
109
|
+
runtimeHealth: { status: 'unavailable', issues: [messageFromError(error)] },
|
|
110
|
+
durableGaps: [],
|
|
111
|
+
syncBackDecisions: [],
|
|
112
|
+
fanInEvidenceSets: [],
|
|
113
|
+
advisorAssessments: [],
|
|
114
|
+
payloads: []
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function scopedRuntimeQueries(taskIds: string[], runIds: string[]): Array<{ taskId: string | null; runId: string | null }> {
|
|
120
|
+
if (taskIds.length === 0 && runIds.length === 0) {
|
|
121
|
+
return [{ taskId: null, runId: null }];
|
|
122
|
+
}
|
|
123
|
+
if (taskIds.length === 0) {
|
|
124
|
+
return runIds.map((scopedRunId) => ({ taskId: null, runId: scopedRunId }));
|
|
125
|
+
}
|
|
126
|
+
if (runIds.length === 0) {
|
|
127
|
+
return taskIds.map((scopedTaskId) => ({ taskId: scopedTaskId, runId: null }));
|
|
128
|
+
}
|
|
129
|
+
return uniqueBy([
|
|
130
|
+
...taskIds.flatMap((scopedTaskId) => runIds.map((scopedRunId) => ({ taskId: scopedTaskId, runId: scopedRunId }))),
|
|
131
|
+
...taskIds.map((scopedTaskId) => ({ taskId: scopedTaskId, runId: null })),
|
|
132
|
+
...runIds.map((scopedRunId) => ({ taskId: null, runId: scopedRunId }))
|
|
133
|
+
], (scope) => `${scope.taskId ?? 'none'}:${scope.runId ?? 'none'}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function uniqueBy<T>(items: T[], keyOf: (item: T) => string): T[] {
|
|
137
|
+
const seen = new Set<string>();
|
|
138
|
+
return items.filter((item) => {
|
|
139
|
+
const key = keyOf(item);
|
|
140
|
+
if (seen.has(key)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
seen.add(key);
|
|
144
|
+
return true;
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function inspectArtifactPayloadHealth(projectRoot: string, payloads: RuntimeArtifactPayloadRecord[]): Promise<WorkflowGateEvidencePacket['artifactPayloadHealth']> {
|
|
149
|
+
return Promise.all(payloads.map(async (payload) => {
|
|
150
|
+
try {
|
|
151
|
+
const raw = await readFile(getEvidenceAttachmentPath(projectRoot, payload.branchSlug, payload.physicalPayloadPath), 'utf8');
|
|
152
|
+
const actualDigest = hashDocumentContent(raw);
|
|
153
|
+
return {
|
|
154
|
+
payloadId: payload.payloadId,
|
|
155
|
+
logicalRef: payload.logicalRef,
|
|
156
|
+
physicalPayloadPath: payload.physicalPayloadPath,
|
|
157
|
+
expectedDigest: payload.digest,
|
|
158
|
+
actualDigest,
|
|
159
|
+
status: actualDigest === payload.digest ? 'ok' as const : 'digest_drift' as const
|
|
160
|
+
};
|
|
161
|
+
} catch {
|
|
162
|
+
return {
|
|
163
|
+
payloadId: payload.payloadId,
|
|
164
|
+
logicalRef: payload.logicalRef,
|
|
165
|
+
physicalPayloadPath: payload.physicalPayloadPath,
|
|
166
|
+
expectedDigest: payload.digest,
|
|
167
|
+
actualDigest: null,
|
|
168
|
+
status: 'missing' as const
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function hashDocumentContent(raw: string): string {
|
|
175
|
+
return createHash('sha256').update(raw.replace(/\r\n/g, '\n'), 'utf8').digest('hex');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export async function evaluateAndRecordWorkflowGateDecision(projectRoot: string, input: { branch?: string | null; taskId?: string | null; runId?: string | null; decisionKind: WorkflowGateDecisionKind; waveRunId?: string | null; taskIds?: string[]; runIds?: string[]; evidenceRefs?: string[] }): Promise<{ packet: WorkflowGateEvidencePacket; decision: WorkflowGateDecision }> {
|
|
179
|
+
const packet = await buildWorkflowGateEvidencePacket(projectRoot, input);
|
|
180
|
+
const decision = synthesizeWorkflowGateDecision(packet);
|
|
181
|
+
try {
|
|
182
|
+
await recordRuntimeWorkflowGateDecision(projectRoot, decision);
|
|
183
|
+
} catch (error) {
|
|
184
|
+
if (packet.runtimeHealth.status === 'ok') {
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return { packet, decision };
|
|
189
|
+
}
|
|
190
|
+
function sortedUnique(values: string[]): string[] {
|
|
191
|
+
return [...new Set(values.filter(Boolean))].sort();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function messageFromError(error: unknown): string {
|
|
195
|
+
return error instanceof Error ? error.message : String(error);
|
|
196
|
+
}
|