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
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { artifactKind, readArtifact, writeArtifact } from '../run-state/artifacts.js';
|
|
10
10
|
import { appendEvent } from '../run-state/events.js';
|
|
11
11
|
import { appendArtifactHashLedgerEntry, appendDeclaredCommandLedgerEntries, appendInvocationLedgerEntry, listInvocationLedgerEntries } from '../run-state/invocation-ledger.js';
|
|
12
|
-
import type { InvocationLedgerEntry, InvocationLedgerKind, RunState } from '../run-state/model.js';
|
|
12
|
+
import type { InvocationLedgerEntry, InvocationLedgerKind, RunState, RunStateTaskRuntime } from '../run-state/model.js';
|
|
13
13
|
import { readRunState, writeRunState } from '../run-state/run-state.js';
|
|
14
14
|
import { toArtifactRootRelativePath } from '../runtime-paths.js';
|
|
15
15
|
import { hasRuntimeEvidenceScopeViolation, readRuntimeEvidenceClaims } from '../context/evidence-summary.js';
|
|
@@ -20,6 +20,7 @@ import { taskGap } from '../sdd-docs/task-inspection.js';
|
|
|
20
20
|
import { inspectSddTask } from '../sdd-docs/task-inspection.js';
|
|
21
21
|
import type { SddTask, SddTaskGap } from '../sdd-docs/task-parser.js';
|
|
22
22
|
import { resolveTaskRun } from '../sync-back/inspect.js';
|
|
23
|
+
import { recordRuntimeSyncBackDecision, runtimeScopedId } from '../storage/runtime-store.js';
|
|
23
24
|
|
|
24
25
|
export type GoalVerifyStatus = 'PASS' | 'PASS_WITH_GAPS' | 'FAIL' | 'BLOCKED';
|
|
25
26
|
export type HarnessVerifyStatus = 'PASS' | 'GAPS' | 'BLOCKED' | 'HUMAN_NEEDED';
|
|
@@ -204,13 +205,28 @@ export async function runGoalVerify(projectRoot: string, options: GoalVerifyOpti
|
|
|
204
205
|
await persistVerifyState(projectRoot, runId, {
|
|
205
206
|
status,
|
|
206
207
|
taskId: options.taskId,
|
|
207
|
-
taskState:
|
|
208
|
+
taskState: buildGoalVerifyTaskState(inspected.task, status, gaps, allArtifacts, acceptanceCoverage),
|
|
208
209
|
commands: plannedCommands,
|
|
209
210
|
evidence: allArtifacts,
|
|
210
211
|
syncBackProposalPath: proposal.runRelativePath,
|
|
211
212
|
syncBackProposalDigest: proposal.digest,
|
|
212
213
|
artifacts: allArtifacts.map((artifactPath) => ({ path: artifactPath, kind: artifactKind(artifactPath), task: options.taskId, agent: agentFromArtifactPath(artifactPath) }))
|
|
213
214
|
});
|
|
215
|
+
const decisionTime = new Date().toISOString();
|
|
216
|
+
await recordRuntimeSyncBackDecision(projectRoot, {
|
|
217
|
+
decisionId: runtimeScopedId(runId, options.taskId, 'sync-back'),
|
|
218
|
+
runId,
|
|
219
|
+
branch,
|
|
220
|
+
taskId: options.taskId,
|
|
221
|
+
status: 'proposed',
|
|
222
|
+
proposalPath: proposal.runRelativePath,
|
|
223
|
+
proposalDigest: proposal.digest,
|
|
224
|
+
proposalPayloadId: proposal.payloadId,
|
|
225
|
+
reasons: gaps.map((gap) => `${gap.severity} ${gap.type} ${gap.field}: ${gap.message}`),
|
|
226
|
+
createdAt: decisionTime,
|
|
227
|
+
updatedAt: decisionTime,
|
|
228
|
+
payload: { sourceVerifyStatus: status, standardStatus, artifacts: allArtifacts }
|
|
229
|
+
});
|
|
214
230
|
await appendEvent(projectRoot, runId, {
|
|
215
231
|
event: status === 'PASS' ? 'validation_passed' : 'validation_failed',
|
|
216
232
|
runId,
|
|
@@ -243,10 +259,26 @@ export async function runGoalVerify(projectRoot: string, options: GoalVerifyOpti
|
|
|
243
259
|
};
|
|
244
260
|
}
|
|
245
261
|
|
|
262
|
+
function buildGoalVerifyTaskState(task: SddTask | null, status: GoalVerifyStatus, gaps: SddTaskGap[], artifacts: string[], acceptanceCoverage: unknown[]): RunStateTaskRuntime {
|
|
263
|
+
const verificationStatus = status === 'PASS' ? 'pass' : status === 'PASS_WITH_GAPS' ? 'pass_with_gaps' : status === 'FAIL' ? 'failed' : 'blocked';
|
|
264
|
+
return {
|
|
265
|
+
status: status === 'PASS' ? 'implemented_verified' : verificationStatus === 'pass_with_gaps' ? 'validation_blocked' : verificationStatus === 'failed' ? 'validation_failed' : 'validation_blocked',
|
|
266
|
+
implementationStatus: 'implemented',
|
|
267
|
+
verificationStatus,
|
|
268
|
+
validationBatch: task?.validationBatch ?? null,
|
|
269
|
+
validationTiming: task?.validationTiming ?? 'task_end',
|
|
270
|
+
requiresVerifyBeforeNext: task?.requiresVerifyBeforeNext ?? true,
|
|
271
|
+
verifyStatus: status,
|
|
272
|
+
gaps,
|
|
273
|
+
artifacts,
|
|
274
|
+
acceptanceCoverage
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
246
278
|
async function persistVerifyState(projectRoot: string, runId: string, input: {
|
|
247
279
|
status: GoalVerifyStatus;
|
|
248
280
|
taskId: string;
|
|
249
|
-
taskState:
|
|
281
|
+
taskState: RunStateTaskRuntime;
|
|
250
282
|
commands: string[];
|
|
251
283
|
evidence: string[];
|
|
252
284
|
syncBackProposalPath: string;
|
|
@@ -284,10 +316,11 @@ async function persistVerifyState(projectRoot: string, runId: string, input: {
|
|
|
284
316
|
});
|
|
285
317
|
}
|
|
286
318
|
|
|
287
|
-
async function writeSyncBackProposal(projectRoot: string, runId: string, taskId: string, status: string, artifacts: string[], gaps: SddTaskGap[], summary: string): Promise<{ absolutePath: string; runRelativePath: string; digest: string }> {
|
|
319
|
+
async function writeSyncBackProposal(projectRoot: string, runId: string, taskId: string, status: string, artifacts: string[], gaps: SddTaskGap[], summary: string): Promise<{ absolutePath: string; runRelativePath: string; digest: string; payloadId: string }> {
|
|
288
320
|
const content = `# Sync-back Proposal\n\n## ${taskId}\n\n- status: ${status}\n- summary: ${summary}\n- artifacts:\n${artifacts.length > 0 ? artifacts.map((artifact) => ` - ${artifact}`).join('\n') : ' - none'}\n- gaps:\n${gaps.length > 0 ? gaps.map((gap) => ` - [${gap.severity}] ${gap.type} ${gap.field}: ${gap.message}`).join('\n') : ' - none'}\n\n## Boundaries\n\n- Proposal only; tasks.md/spec.md/plan.md were not modified by runtime.\n- Runtime modeled agent/verify steps through supplied artifacts and contract validation; no external agent API was invoked.\n`;
|
|
321
|
+
const digest = hashDocumentContent(content);
|
|
289
322
|
const written = await writeArtifact(projectRoot, runId, 'sync-back-proposal.md', content);
|
|
290
|
-
return { ...written, digest:
|
|
323
|
+
return { ...written, digest, payloadId: runtimeScopedId(runId, written.runRelativePath, digest) };
|
|
291
324
|
}
|
|
292
325
|
|
|
293
326
|
function renderAcceptanceCoverageArtifact(taskId: string, status: GoalVerifyStatus, task: SddTask | null, reviewArtifact: string | null, validationArtifact: string | null, coverage: AcceptanceCoverageItem[], gaps: SddTaskGap[], executedCommands: string[]): string {
|
|
@@ -57,7 +57,7 @@ export interface SingleTaskLoopResultLike {
|
|
|
57
57
|
export function renderGoalVerifyResult(result: GoalVerifyResultLike): string {
|
|
58
58
|
const lines = ['SDD verify task result', 'changed'];
|
|
59
59
|
lines.push(`- acceptance coverage written to ${result.coverageArtifactPath}`);
|
|
60
|
-
lines.push(`-
|
|
60
|
+
lines.push(`- compatibility diagnostic proposal=${result.syncBackProposalPath || 'none'}`);
|
|
61
61
|
lines.push('decision');
|
|
62
62
|
lines.push(`- status=${result.status}`);
|
|
63
63
|
lines.push(`- standard_status=${result.standardStatus}`);
|
|
@@ -85,7 +85,8 @@ export function renderGoalVerifyResult(result: GoalVerifyResultLike): string {
|
|
|
85
85
|
}
|
|
86
86
|
lines.push('next');
|
|
87
87
|
if (result.status === 'PASS') {
|
|
88
|
-
lines.push(`- sdd
|
|
88
|
+
lines.push(`- sdd test task ${result.taskId} --run ${result.runId}`);
|
|
89
|
+
lines.push('- then follow the test gate result toward ship readiness; use sync-back only for explicit diagnostic/recovery/replay.');
|
|
89
90
|
} else {
|
|
90
91
|
lines.push(`- update review/validator artifacts and rerun sdd test task ${result.taskId} --run ${result.runId}`);
|
|
91
92
|
}
|
|
@@ -108,8 +109,8 @@ export function renderSingleTaskLoopResult(result: SingleTaskLoopResultLike): st
|
|
|
108
109
|
lines.push(`- required_artifacts=${result.requiredArtifacts.join(',') || 'none'}`);
|
|
109
110
|
lines.push(`- accepted_artifacts=${result.acceptedArtifacts.join(',') || 'none'}`);
|
|
110
111
|
lines.push(`- sync_back_proposal=${result.syncBackProposalPath || 'none'}`);
|
|
111
|
-
lines.push(
|
|
112
|
-
lines.push(
|
|
112
|
+
lines.push('- agent_execution_records=runtime.sqlite:agent_executions');
|
|
113
|
+
lines.push('- team_session_records=runtime.sqlite:team_sessions');
|
|
113
114
|
lines.push('gaps');
|
|
114
115
|
if (result.gaps.length === 0) {
|
|
115
116
|
lines.push('- none');
|
|
@@ -118,7 +119,12 @@ export function renderSingleTaskLoopResult(result: SingleTaskLoopResultLike): st
|
|
|
118
119
|
}
|
|
119
120
|
lines.push('next');
|
|
120
121
|
if (result.status === 'completed') {
|
|
121
|
-
|
|
122
|
+
if (result.task && !requiresImmediateValidation(result.task) && result.task.validationBatch) {
|
|
123
|
+
lines.push(`- sdd status --branch <branch> to select the next safe do task or validation boundary`);
|
|
124
|
+
lines.push(`- after all tasks in validation_batch ${result.task.validationBatch} are implemented, run sdd test batch ${result.task.validationBatch}`);
|
|
125
|
+
} else {
|
|
126
|
+
lines.push(`- sdd test task ${result.taskId} --run ${result.runId}`);
|
|
127
|
+
}
|
|
122
128
|
} else {
|
|
123
129
|
const missingArtifacts = result.requiredArtifacts.filter((artifact) => !result.acceptedArtifacts.includes(artifact));
|
|
124
130
|
if (missingArtifacts.length > 0) {
|
|
@@ -137,6 +143,10 @@ export function renderSingleTaskLoopResult(result: SingleTaskLoopResultLike): st
|
|
|
137
143
|
return lines.join('\n');
|
|
138
144
|
}
|
|
139
145
|
|
|
146
|
+
function requiresImmediateValidation(task: SddTask): boolean {
|
|
147
|
+
return task.requiresVerifyBeforeNext || task.validationTiming === 'task_end';
|
|
148
|
+
}
|
|
149
|
+
|
|
140
150
|
function agentForLoopArtifact(artifactPath: string): LoopAgent | null {
|
|
141
151
|
const filename = artifactPath.replace(/\\/g, '/').split('/').pop() ?? '';
|
|
142
152
|
if (filename.startsWith('implement-')) {
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
|
|
7
|
+
import { initProject } from '../config/init-project.js';
|
|
8
|
+
import { listRuntimeWorkflowGateDecisions } from '../storage/runtime-store.js';
|
|
9
|
+
import { writeBranchDocs } from '../test-support/fixtures.js';
|
|
10
|
+
import { writeVerifyContract } from './verify-contract.js';
|
|
11
|
+
import { runValidationWave } from './validation-wave.js';
|
|
12
|
+
import { renderReviewGateResult, runReviewGate } from './review-gate.js';
|
|
13
|
+
|
|
14
|
+
function taskMarkdown(taskId: string, command: string, wave: number): string {
|
|
15
|
+
return `### ${taskId}: Review gate task
|
|
16
|
+
|
|
17
|
+
\`\`\`sdd-task
|
|
18
|
+
id: ${taskId}
|
|
19
|
+
status: pending
|
|
20
|
+
wave: ${wave}
|
|
21
|
+
depends_on: []
|
|
22
|
+
acceptance_refs:
|
|
23
|
+
- AC-${taskId}
|
|
24
|
+
plan_refs:
|
|
25
|
+
- "§4 Target Design Overview"
|
|
26
|
+
affected_files:
|
|
27
|
+
- docs/${taskId.toLowerCase()}.md
|
|
28
|
+
validation:
|
|
29
|
+
- ${command} => AC-${taskId}
|
|
30
|
+
risk: []
|
|
31
|
+
\`\`\`
|
|
32
|
+
|
|
33
|
+
#### Boundary
|
|
34
|
+
|
|
35
|
+
Stay in review gate fixtures.
|
|
36
|
+
|
|
37
|
+
#### Acceptance
|
|
38
|
+
|
|
39
|
+
- AC-${taskId}: Review gate evidence is mapped.
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
test('review gate records a workflow gate decision with whole-wave scope', async () => {
|
|
44
|
+
const root = await mkdtemp(path.join(tmpdir(), 'sdd-review-gate-'));
|
|
45
|
+
try {
|
|
46
|
+
await initProject(root);
|
|
47
|
+
await writeBranchDocs(root, 'feature', `# Tasks
|
|
48
|
+
|
|
49
|
+
${taskMarkdown('T1', 'node -e "process.stdout.write(\'one\')"', 1)}
|
|
50
|
+
${taskMarkdown('T2', 'node -e "process.stdout.write(\'two\')"', 1)}`);
|
|
51
|
+
await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
52
|
+
|
|
53
|
+
const wave = await runValidationWave(root, { branch: 'feature', wave: 1, approved: true });
|
|
54
|
+
const expectedEvidenceRefs = wave.taskResults.flatMap((taskResult) => [taskResult.validationArtifact, taskResult.indexArtifact].filter((ref): ref is string => Boolean(ref))).sort();
|
|
55
|
+
const result = await runReviewGate(root, {
|
|
56
|
+
branch: 'feature',
|
|
57
|
+
taskId: 'T1',
|
|
58
|
+
runId: wave.taskResults[0].runId,
|
|
59
|
+
waveRunId: wave.waveRunId,
|
|
60
|
+
taskIds: wave.plan.taskIds,
|
|
61
|
+
runIds: wave.taskResults.map((taskResult) => taskResult.runId),
|
|
62
|
+
evidenceRefs: expectedEvidenceRefs
|
|
63
|
+
});
|
|
64
|
+
const decisions = await listRuntimeWorkflowGateDecisions(root, { partition: 'feature', decisionKind: 'review_gate' });
|
|
65
|
+
const workflowGateScope = (result.workflowGateDecision.payload as { workflowScope?: { waveRunId: string | null; taskIds: string[]; runIds: string[]; evidenceRefs: string[] } }).workflowScope;
|
|
66
|
+
|
|
67
|
+
assert.equal(result.status, 'PASS');
|
|
68
|
+
assert.equal(decisions.some((decision) => decision.decisionId === result.workflowGateDecision.decisionId), true);
|
|
69
|
+
assert.equal(workflowGateScope?.waveRunId, wave.waveRunId);
|
|
70
|
+
assert.deepEqual(workflowGateScope?.taskIds, ['T1', 'T2']);
|
|
71
|
+
assert.deepEqual(workflowGateScope?.runIds, wave.taskResults.map((taskResult) => taskResult.runId).sort());
|
|
72
|
+
assert.deepEqual(workflowGateScope?.evidenceRefs, expectedEvidenceRefs);
|
|
73
|
+
assert.match(renderReviewGateResult(result), /workflow_gate=PASS:/);
|
|
74
|
+
} finally {
|
|
75
|
+
await rm(root, { recursive: true, force: true });
|
|
76
|
+
}
|
|
77
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { evaluateAndRecordWorkflowGateDecision } from '../workflow-gate/evidence-packet.js';
|
|
2
|
+
import type { WorkflowGateDecision, WorkflowGateStatus } from '../workflow-gate/types.js';
|
|
3
|
+
|
|
4
|
+
export const REVIEW_GATE_RUNTIME_CONTRACT_VERSION = 'phase-8.17-review-gate-runtime-v1';
|
|
5
|
+
|
|
6
|
+
export interface RunReviewGateOptions {
|
|
7
|
+
branch?: string | null;
|
|
8
|
+
taskId?: string | null;
|
|
9
|
+
runId?: string | null;
|
|
10
|
+
waveRunId?: string | null;
|
|
11
|
+
taskIds?: string[];
|
|
12
|
+
runIds?: string[];
|
|
13
|
+
evidenceRefs?: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ReviewGateRunResult {
|
|
17
|
+
contract: typeof REVIEW_GATE_RUNTIME_CONTRACT_VERSION;
|
|
18
|
+
branch: string;
|
|
19
|
+
taskId: string | null;
|
|
20
|
+
runId: string | null;
|
|
21
|
+
status: WorkflowGateStatus;
|
|
22
|
+
workflowGateDecision: WorkflowGateDecision;
|
|
23
|
+
next: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function runReviewGate(projectRoot: string, options: RunReviewGateOptions = {}): Promise<ReviewGateRunResult> {
|
|
27
|
+
const { decision } = await evaluateAndRecordWorkflowGateDecision(projectRoot, {
|
|
28
|
+
branch: options.branch,
|
|
29
|
+
taskId: options.taskId,
|
|
30
|
+
runId: options.runId,
|
|
31
|
+
decisionKind: 'review_gate',
|
|
32
|
+
waveRunId: options.waveRunId,
|
|
33
|
+
taskIds: options.taskIds,
|
|
34
|
+
runIds: options.runIds,
|
|
35
|
+
evidenceRefs: options.evidenceRefs
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
contract: REVIEW_GATE_RUNTIME_CONTRACT_VERSION,
|
|
39
|
+
branch: decision.partition,
|
|
40
|
+
taskId: decision.taskId,
|
|
41
|
+
runId: decision.runId,
|
|
42
|
+
status: decision.status,
|
|
43
|
+
workflowGateDecision: decision,
|
|
44
|
+
next: nextForReviewGate(decision)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function renderReviewGateResult(result: ReviewGateRunResult): string {
|
|
49
|
+
return [
|
|
50
|
+
'SDD review gate',
|
|
51
|
+
'',
|
|
52
|
+
`status=${result.status}`,
|
|
53
|
+
`branch=${result.branch}`,
|
|
54
|
+
`task=${result.taskId ?? 'none'}`,
|
|
55
|
+
`run=${result.runId ?? 'none'}`,
|
|
56
|
+
`workflow_gate=${result.workflowGateDecision.status}:${result.workflowGateDecision.decisionId}`,
|
|
57
|
+
'',
|
|
58
|
+
'Next:',
|
|
59
|
+
`- ${result.next}`
|
|
60
|
+
].join('\n');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function nextForReviewGate(decision: WorkflowGateDecision): string {
|
|
64
|
+
if (decision.status === 'PASS') {
|
|
65
|
+
return `Continue workflow after review gate ${decision.decisionId}.`;
|
|
66
|
+
}
|
|
67
|
+
if (decision.status === 'WARN') {
|
|
68
|
+
return `Inspect review gate ${decision.decisionId} warnings before continuing.`;
|
|
69
|
+
}
|
|
70
|
+
if (decision.status === 'HUMAN_REQUIRED') {
|
|
71
|
+
return `Create a decision card for review gate ${decision.decisionId}.`;
|
|
72
|
+
}
|
|
73
|
+
if (decision.status === 'ADVISORY_ONLY') {
|
|
74
|
+
return `Inspect advisor assessments for review gate ${decision.decisionId}; do not treat advisory output as pass.`;
|
|
75
|
+
}
|
|
76
|
+
return `Resolve review gate ${decision.decisionId} blockers before continuing.`;
|
|
77
|
+
}
|
|
@@ -12,10 +12,13 @@ import { getProjectStatus } from '../status/project-status.js';
|
|
|
12
12
|
import { doctor } from '../doctor/doctor.js';
|
|
13
13
|
import { readArtifact, writeArtifact } from '../run-state/artifacts.js';
|
|
14
14
|
import { inspectRun } from '../run-state/inspect-run.js';
|
|
15
|
+
import { readTaskEvidenceView } from '../run-state/task-evidence.js';
|
|
15
16
|
import { rebuildLocalRunIndex } from '../run-state/run-index.js';
|
|
16
17
|
import { readRunEvents } from '../run-state/events.js';
|
|
17
18
|
import { createRun, readRunState } from '../run-state/run-state.js';
|
|
19
|
+
import { recordRuntimeArtifactPayload, runtimeScopedId } from '../storage/runtime-store.js';
|
|
18
20
|
import { validResultArtifact, validTaskMarkdown, validTrustEvidence, writeBranchDocs } from '../test-support/fixtures.js';
|
|
21
|
+
import { writeVerifyContract } from './verify-contract.js';
|
|
19
22
|
import { bindTestRunState } from '../test-support/run-state.js';
|
|
20
23
|
import { renderSingleTaskLoopResult } from './rendering.js';
|
|
21
24
|
import { runSingleTaskLoop } from './single-task-loop.js';
|
|
@@ -32,6 +35,7 @@ test('runSingleTaskLoop completes from supplied review and validation artifacts
|
|
|
32
35
|
await initProject(root);
|
|
33
36
|
await execFileAsync('git', ['init'], { cwd: root });
|
|
34
37
|
await writeBranchDocs(root, 'feature', validTaskMarkdown('T1', []));
|
|
38
|
+
await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
|
|
35
39
|
const state = await createRun(root, { runId: 'run-1' });
|
|
36
40
|
await bindTestRunState(root, state.runId, 'feature', 'T1');
|
|
37
41
|
await writeArtifact(root, state.runId, 'review-T1.md', validResultArtifact('reviewer', 'T1', 'PASS', 'artifacts/review-T1.md'));
|
|
@@ -50,6 +54,21 @@ test('runSingleTaskLoop completes from supplied review and validation artifacts
|
|
|
50
54
|
const doctorReport = await doctor(root, { latestOnly: true });
|
|
51
55
|
const events = stringifyEvents(await readRunEvents(root, state.runId));
|
|
52
56
|
const tasksMarkdown = await readFile(path.join(root, 'specs', 'feature', 'tasks.md'), 'utf8');
|
|
57
|
+
await execFileAsync('git', ['checkout', '-b', 'feature'], { cwd: root });
|
|
58
|
+
await recordRuntimeArtifactPayload(root, {
|
|
59
|
+
payloadId: runtimeScopedId(state.runId, 'artifacts/validation-T2.md', 'foreign-task'),
|
|
60
|
+
runId: state.runId,
|
|
61
|
+
sourceRunId: state.runId,
|
|
62
|
+
branchSlug: 'feature',
|
|
63
|
+
taskId: 'T2',
|
|
64
|
+
logicalRef: 'artifacts/validation-T2.md',
|
|
65
|
+
physicalPayloadPath: 'artifacts/validation-T2-run-1-foreign-task.md',
|
|
66
|
+
artifactRole: 'validation',
|
|
67
|
+
digest: 'foreign-task',
|
|
68
|
+
status: 'active',
|
|
69
|
+
payload: { logicalRef: 'artifacts/validation-T2.md' }
|
|
70
|
+
});
|
|
71
|
+
const taskEvidence = await readTaskEvidenceView(root, { branch: 'feature', taskId: 'T1' });
|
|
53
72
|
|
|
54
73
|
assert.equal(result.status, 'completed');
|
|
55
74
|
assert.deepEqual(result.acceptedArtifacts, ['artifacts/review-T1.md', 'artifacts/validation-T1.md']);
|
|
@@ -59,7 +78,7 @@ test('runSingleTaskLoop completes from supplied review and validation artifacts
|
|
|
59
78
|
assert.equal(restored.syncBack.proposalPath, 'artifacts/sync-back-proposal.md');
|
|
60
79
|
assert.equal(ingestionInspection.valid, true);
|
|
61
80
|
assert.deepEqual(ingestionInspection.records.map((record) => record.delegationId), ['B-T1-reviewer-001', 'B-T1-validator-001']);
|
|
62
|
-
assert.equal(doctorReport.status, '
|
|
81
|
+
assert.equal(doctorReport.status, 'FAIL');
|
|
63
82
|
assert.match(events, /task_selected/);
|
|
64
83
|
assert.match(events, /review_passed/);
|
|
65
84
|
assert.match(events, /validation_passed/);
|
|
@@ -67,6 +86,45 @@ test('runSingleTaskLoop completes from supplied review and validation artifacts
|
|
|
67
86
|
assert.match(events, /delegation_completed/);
|
|
68
87
|
assert.doesNotMatch(events, /agent_completed/);
|
|
69
88
|
assert.match(tasksMarkdown, /status: pending/);
|
|
89
|
+
assert.equal(taskEvidence.latestEligibleRun?.runId, state.runId);
|
|
90
|
+
assert.equal(taskEvidence.compatibility, 'compatible');
|
|
91
|
+
assert.equal(taskEvidence.payloads.active.some((payload) => payload.logicalRef === 'artifacts/sync-back-proposal.md'), true);
|
|
92
|
+
assert.equal(taskEvidence.payloads.all.some((payload) => payload.taskId === 'T2'), false);
|
|
93
|
+
assert.equal(taskEvidence.validation.runValidation?.status, 'pass');
|
|
94
|
+
assert.equal(taskEvidence.syncBackDecision?.status, 'proposed');
|
|
95
|
+
} finally {
|
|
96
|
+
await rm(root, { recursive: true, force: true });
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('runSingleTaskLoop blocks rejected validation ingestion without accepting the artifact', async () => {
|
|
101
|
+
const root = await mkdtemp(path.join(tmpdir(), 'sdd-loop-rejected-validation-'));
|
|
102
|
+
try {
|
|
103
|
+
await initProject(root);
|
|
104
|
+
await writeBranchDocs(root, 'feature', validTaskMarkdown('T1', []));
|
|
105
|
+
const state = await createRun(root, { runId: 'run-1' });
|
|
106
|
+
await bindTestRunState(root, state.runId, 'feature', 'T1');
|
|
107
|
+
await writeArtifact(root, state.runId, 'review-T1.md', validResultArtifact('reviewer', 'T1', 'PASS', 'artifacts/review-T1.md'));
|
|
108
|
+
await writeArtifact(root, state.runId, 'validation-T1.md', validResultArtifact('validator', 'T1', 'PASS', 'artifacts/validation-T1.md'));
|
|
109
|
+
|
|
110
|
+
const result = await runSingleTaskLoop(root, {
|
|
111
|
+
runId: state.runId,
|
|
112
|
+
branch: 'feature',
|
|
113
|
+
taskId: 'T1',
|
|
114
|
+
reviewArtifact: 'artifacts/review-T1.md',
|
|
115
|
+
validationArtifact: 'artifacts/validation-T1.md'
|
|
116
|
+
});
|
|
117
|
+
const restored = await readRunState(root, state.runId);
|
|
118
|
+
const ingestionInspection = await inspectArtifactResultIngestions(root, state.runId);
|
|
119
|
+
|
|
120
|
+
assert.equal(result.status, 'blocked');
|
|
121
|
+
assert.equal(restored.status, 'blocked');
|
|
122
|
+
assert.equal(restored.validation.status, 'blocked');
|
|
123
|
+
assert.deepEqual(result.acceptedArtifacts, ['artifacts/review-T1.md', 'artifacts/gap-report-T1.md']);
|
|
124
|
+
assert.equal(restored.artifacts.some((artifact) => artifact.path === 'artifacts/validation-T1.md'), false);
|
|
125
|
+
assert.equal(ingestionInspection.valid, true);
|
|
126
|
+
assert.equal(ingestionInspection.records.find((record) => record.artifactPath === 'artifacts/validation-T1.md')?.status, 'rejected');
|
|
127
|
+
assert.equal(result.gaps.some((gap) => /UNSOURCED_PASS/.test(gap.message)), true);
|
|
70
128
|
} finally {
|
|
71
129
|
await rm(root, { recursive: true, force: true });
|
|
72
130
|
}
|
|
@@ -104,6 +162,7 @@ test('runSingleTaskLoop blocks on missing reviewer artifact and creates gap prop
|
|
|
104
162
|
assert.match(rendered, /physical artifact files belong under branch evidence \.sdd\/runs\/<branchSlug>\/evidence\/artifacts\//);
|
|
105
163
|
assert.match(rendered, /artifact_path_scope=CLI flags use run-relative artifacts\/<file>/);
|
|
106
164
|
assert.equal(restored.status, 'blocked');
|
|
165
|
+
assert.match(restored.artifactRoot, /\.sdd[\\/]runs[\\/]feature[\\/]evidence/);
|
|
107
166
|
assert.match(gapReport, /reviewer artifact was not supplied/);
|
|
108
167
|
assert.match(proposal, /Proposal only/);
|
|
109
168
|
const events = stringifyEvents(await readRunEvents(root, state.runId));
|
|
@@ -185,9 +244,10 @@ test('runSingleTaskLoop persists agent and team evidence records', async () => {
|
|
|
185
244
|
assert.equal(teamSession.teamMode.costClass, 'low');
|
|
186
245
|
assert.match(teamSession.teamMode.reason, /review|validation/i);
|
|
187
246
|
assert.equal(inspection.taskRunEvidence.teamSessions.length, inspection.teamSessions.length);
|
|
188
|
-
|
|
189
|
-
assert.equal(
|
|
190
|
-
assert.equal(
|
|
247
|
+
const rejectedRun = status.latestEligibleRunsByTask.flatMap((selection) => selection.rejected).find((candidate) => candidate.runId === result.runId);
|
|
248
|
+
assert.equal(rejectedRun?.reasons.includes('Run is blocked.'), true);
|
|
249
|
+
assert.equal(inspection.taskRunEvidence.agentExecutions.length, 2);
|
|
250
|
+
assert.equal(inspection.taskRunEvidence.teamSessions.length, 1);
|
|
191
251
|
assert.equal(report.checks.some((check) => check.check === 'agent_team_execution_records' && /agent execution record/.test(check.message)), true);
|
|
192
252
|
} finally {
|
|
193
253
|
await rm(root, { recursive: true, force: true });
|
|
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { SDD_RESULT_CONTRACT, SDD_RESULT_VERSION } from '../contracts.js';
|
|
3
3
|
import { artifactKind, writeArtifact } from '../run-state/artifacts.js';
|
|
4
4
|
import { appendEvent } from '../run-state/events.js';
|
|
5
|
-
import type { RunState } from '../run-state/model.js';
|
|
5
|
+
import type { RunState, RunStateTaskRuntime } from '../run-state/model.js';
|
|
6
6
|
import { createRun, readRunState, writeRunState } from '../run-state/run-state.js';
|
|
7
7
|
import { resolveSddContext } from '../sdd-docs/context.js';
|
|
8
8
|
import { bindRunStateToTask } from '../sdd-docs/run-binding.js';
|
|
@@ -13,6 +13,7 @@ import type { TeamModeActivation } from '../router/route-cache.js';
|
|
|
13
13
|
import { routeSddTask } from '../router/route-sdd-task.js';
|
|
14
14
|
import { buildAgentExecutionRecord, buildTeamSessionRecord, writeAgentExecutionRecord, writeTeamSessionRecord } from '../execution/agent-execution-records.js';
|
|
15
15
|
import { runBackgroundExecutor } from '../execution/background-executor.js';
|
|
16
|
+
import { recordRuntimeSyncBackDecision, runtimeScopedId } from '../storage/runtime-store.js';
|
|
16
17
|
|
|
17
18
|
export type SingleTaskLoopStatus = 'completed' | 'blocked' | 'failed';
|
|
18
19
|
|
|
@@ -92,12 +93,23 @@ export async function runSingleTaskLoop(projectRoot: string, options: SingleTask
|
|
|
92
93
|
status: 'blocked',
|
|
93
94
|
phase: 'do',
|
|
94
95
|
taskId: options.taskId,
|
|
95
|
-
taskState:
|
|
96
|
+
taskState: buildRuntimeTaskState(inspected.task, 'blocked', 'blocked', allGaps, [gapArtifact.runRelativePath]),
|
|
96
97
|
validationStatus: 'blocked',
|
|
97
98
|
syncBackProposalPath: proposal.runRelativePath,
|
|
98
99
|
syncBackProposalDigest: proposal.digest,
|
|
99
100
|
artifacts: [{ path: gapArtifact.runRelativePath, kind: 'gap-report', task: options.taskId, agent: 'runtime' }]
|
|
100
101
|
});
|
|
102
|
+
await recordLoopSyncBackDecision(projectRoot, {
|
|
103
|
+
runId,
|
|
104
|
+
branch,
|
|
105
|
+
taskId: options.taskId,
|
|
106
|
+
status: 'proposed',
|
|
107
|
+
proposalPath: proposal.runRelativePath,
|
|
108
|
+
proposalDigest: proposal.digest,
|
|
109
|
+
proposalPayloadId: proposal.payloadId,
|
|
110
|
+
reasons: allGaps.map((gap) => `${gap.severity} ${gap.type} ${gap.field}: ${gap.message}`),
|
|
111
|
+
payload: { sourceVerifyStatus: 'blocked', artifacts: [gapArtifact.runRelativePath] }
|
|
112
|
+
});
|
|
101
113
|
await appendEvent(projectRoot, runId, {
|
|
102
114
|
event: 'gap_detected',
|
|
103
115
|
runId,
|
|
@@ -135,11 +147,11 @@ export async function runSingleTaskLoop(projectRoot: string, options: SingleTask
|
|
|
135
147
|
data: { task: options.taskId, title: inspected.task.title, source: inspected.task.source }
|
|
136
148
|
});
|
|
137
149
|
|
|
138
|
-
const steps = buildLoopSteps(options.taskId, options);
|
|
150
|
+
const steps = buildLoopSteps(options.taskId, options, inspected.task);
|
|
139
151
|
const acceptedArtifacts: string[] = [];
|
|
140
152
|
const gaps: SddTaskGap[] = [];
|
|
141
153
|
let terminalStatus: SingleTaskLoopStatus = 'completed';
|
|
142
|
-
let validationStatus: RunState['validation']['status'] = '
|
|
154
|
+
let validationStatus: RunState['validation']['status'] = 'not_run';
|
|
143
155
|
|
|
144
156
|
for (const step of steps) {
|
|
145
157
|
const stepRouteDecision = await routeSddTask(projectRoot, { taskId: options.taskId, branch, agent: step.agent, teamModeEnabled: options.teamModeEnabled, teamModeActivation: options.teamModeActivation, approved: options.approved });
|
|
@@ -194,7 +206,7 @@ export async function runSingleTaskLoop(projectRoot: string, options: SingleTask
|
|
|
194
206
|
approved: options.approved
|
|
195
207
|
});
|
|
196
208
|
|
|
197
|
-
if (!result.ingestion || !result.ingestion.resultStatus) {
|
|
209
|
+
if (!result.ingestion || result.ingestion.status !== 'accepted' || !result.ingestion.resultStatus) {
|
|
198
210
|
const issueText = result.issues.map((issue) => issue.message).join('; ') || result.message;
|
|
199
211
|
const recommendation = issueText.includes('manual isolation gate') || issueText.includes('requires confirmation')
|
|
200
212
|
? 'Resolve the manual isolation or approval gate for this high-risk task before ingesting execution artifacts.'
|
|
@@ -250,17 +262,30 @@ export async function runSingleTaskLoop(projectRoot: string, options: SingleTask
|
|
|
250
262
|
});
|
|
251
263
|
}
|
|
252
264
|
|
|
253
|
-
const
|
|
265
|
+
const taskState = buildRuntimeTaskState(inspected.task, terminalStatus, validationStatus, gaps, acceptedArtifacts);
|
|
266
|
+
const proposalStatus = taskState.status === 'implemented_pending_validation' ? taskState.status : terminalStatus === 'completed' ? 'completed' : terminalStatus;
|
|
267
|
+
const proposal = await writeSyncBackProposal(projectRoot, runId, options.taskId, proposalStatus, acceptedArtifacts, gaps, terminalStatus === 'completed' ? 'Ingestion-aware task loop accepted implementation evidence; validation may still be pending by task contract.' : terminalStatus === 'blocked' && validationStatus === 'pass_with_gaps' ? 'Ingestion-aware task loop stopped because validator returned PASS_WITH_GAPS; sync-back is a blocked gap proposal, not task completion.' : 'Ingestion-aware task loop stopped with blocking/failing evidence.');
|
|
254
268
|
await persistLoopState(projectRoot, runId, {
|
|
255
269
|
status: terminalStatus,
|
|
256
270
|
phase: 'do',
|
|
257
271
|
taskId: options.taskId,
|
|
258
|
-
taskState
|
|
272
|
+
taskState,
|
|
259
273
|
validationStatus,
|
|
260
274
|
syncBackProposalPath: proposal.runRelativePath,
|
|
261
275
|
syncBackProposalDigest: proposal.digest,
|
|
262
276
|
artifacts: acceptedArtifacts.map((artifactPath) => ({ path: artifactPath, kind: artifactKind(artifactPath), task: options.taskId, agent: agentFromArtifactPath(artifactPath) }))
|
|
263
277
|
});
|
|
278
|
+
await recordLoopSyncBackDecision(projectRoot, {
|
|
279
|
+
runId,
|
|
280
|
+
branch,
|
|
281
|
+
taskId: options.taskId,
|
|
282
|
+
status: 'proposed',
|
|
283
|
+
proposalPath: proposal.runRelativePath,
|
|
284
|
+
proposalDigest: proposal.digest,
|
|
285
|
+
proposalPayloadId: proposal.payloadId,
|
|
286
|
+
reasons: gaps.map((gap) => `${gap.severity} ${gap.type} ${gap.field}: ${gap.message}`),
|
|
287
|
+
payload: { sourceVerifyStatus: terminalStatus, artifacts: acceptedArtifacts }
|
|
288
|
+
});
|
|
264
289
|
await appendEvent(projectRoot, runId, {
|
|
265
290
|
event: 'sync_back_proposed',
|
|
266
291
|
runId,
|
|
@@ -298,7 +323,7 @@ export async function runSingleTaskLoop(projectRoot: string, options: SingleTask
|
|
|
298
323
|
};
|
|
299
324
|
}
|
|
300
325
|
|
|
301
|
-
function buildLoopSteps(taskId: string, options: SingleTaskLoopOptions): LoopAgentStep[] {
|
|
326
|
+
function buildLoopSteps(taskId: string, options: SingleTaskLoopOptions, task: SddTask | null): LoopAgentStep[] {
|
|
302
327
|
const steps: LoopAgentStep[] = [
|
|
303
328
|
{ agent: 'implementer', suppliedArtifact: options.implementArtifact, expectedArtifact: `artifacts/implement-${taskId}.md`, required: false },
|
|
304
329
|
{ agent: 'reviewer', suppliedArtifact: options.reviewArtifact, expectedArtifact: `artifacts/review-${taskId}.md`, required: true }
|
|
@@ -306,15 +331,69 @@ function buildLoopSteps(taskId: string, options: SingleTaskLoopOptions): LoopAge
|
|
|
306
331
|
if (options.debugArtifact) {
|
|
307
332
|
steps.push({ agent: 'debugger', suppliedArtifact: options.debugArtifact, expectedArtifact: `artifacts/debug-${taskId}.md`, required: false });
|
|
308
333
|
}
|
|
309
|
-
steps.push({ agent: 'validator', suppliedArtifact: options.validationArtifact, expectedArtifact: `artifacts/validation-${taskId}.md`, required:
|
|
334
|
+
steps.push({ agent: 'validator', suppliedArtifact: options.validationArtifact, expectedArtifact: `artifacts/validation-${taskId}.md`, required: requiresImmediateValidation(task) });
|
|
310
335
|
return steps;
|
|
311
336
|
}
|
|
312
337
|
|
|
338
|
+
function requiresImmediateValidation(task: SddTask | null): boolean {
|
|
339
|
+
return !task || task.requiresVerifyBeforeNext || task.validationTiming === 'task_end';
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function buildRuntimeTaskState(task: SddTask | null, status: SingleTaskLoopStatus, validationStatus: RunState['validation']['status'], gaps: SddTaskGap[], artifacts: string[]): RunStateTaskRuntime {
|
|
343
|
+
const implementationStatus: NonNullable<RunStateTaskRuntime['implementationStatus']> = status === 'completed' ? 'implemented' : status === 'blocked' ? 'blocked' : 'failed';
|
|
344
|
+
const verificationStatus: NonNullable<RunStateTaskRuntime['verificationStatus']> = verificationStatusForLoop(task, status, validationStatus);
|
|
345
|
+
return {
|
|
346
|
+
status: runtimeTaskStatus(implementationStatus, verificationStatus),
|
|
347
|
+
implementationStatus,
|
|
348
|
+
verificationStatus,
|
|
349
|
+
validationBatch: task?.validationBatch ?? null,
|
|
350
|
+
validationTiming: task?.validationTiming ?? 'task_end',
|
|
351
|
+
requiresVerifyBeforeNext: task?.requiresVerifyBeforeNext ?? true,
|
|
352
|
+
gaps,
|
|
353
|
+
artifacts
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function verificationStatusForLoop(task: SddTask | null, status: SingleTaskLoopStatus, validationStatus: RunState['validation']['status']): NonNullable<RunStateTaskRuntime['verificationStatus']> {
|
|
358
|
+
if (validationStatus === 'pass') {
|
|
359
|
+
return 'pass';
|
|
360
|
+
}
|
|
361
|
+
if (validationStatus === 'pass_with_gaps') {
|
|
362
|
+
return 'pass_with_gaps';
|
|
363
|
+
}
|
|
364
|
+
if (validationStatus === 'blocked') {
|
|
365
|
+
return 'blocked';
|
|
366
|
+
}
|
|
367
|
+
if (validationStatus === 'fail') {
|
|
368
|
+
return 'failed';
|
|
369
|
+
}
|
|
370
|
+
if (status !== 'completed') {
|
|
371
|
+
return status === 'failed' ? 'failed' : 'blocked';
|
|
372
|
+
}
|
|
373
|
+
return task && !requiresImmediateValidation(task) ? 'pending_batch' : 'not_run';
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function runtimeTaskStatus(implementationStatus: NonNullable<RunStateTaskRuntime['implementationStatus']>, verificationStatus: NonNullable<RunStateTaskRuntime['verificationStatus']>): string {
|
|
377
|
+
if (implementationStatus === 'implemented' && verificationStatus === 'pending_batch') {
|
|
378
|
+
return 'implemented_pending_validation';
|
|
379
|
+
}
|
|
380
|
+
if (implementationStatus === 'implemented' && verificationStatus === 'pass') {
|
|
381
|
+
return 'implemented_verified';
|
|
382
|
+
}
|
|
383
|
+
if (verificationStatus === 'pass_with_gaps' || verificationStatus === 'blocked') {
|
|
384
|
+
return 'validation_blocked';
|
|
385
|
+
}
|
|
386
|
+
if (implementationStatus === 'failed' || verificationStatus === 'failed') {
|
|
387
|
+
return 'failed';
|
|
388
|
+
}
|
|
389
|
+
return implementationStatus;
|
|
390
|
+
}
|
|
391
|
+
|
|
313
392
|
async function persistLoopState(projectRoot: string, runId: string, input: {
|
|
314
393
|
status: SingleTaskLoopStatus;
|
|
315
394
|
phase: string;
|
|
316
395
|
taskId: string;
|
|
317
|
-
taskState:
|
|
396
|
+
taskState: RunStateTaskRuntime;
|
|
318
397
|
validationStatus: RunState['validation']['status'];
|
|
319
398
|
syncBackProposalPath: string;
|
|
320
399
|
syncBackProposalDigest: string;
|
|
@@ -351,10 +430,29 @@ async function persistLoopState(projectRoot: string, runId: string, input: {
|
|
|
351
430
|
});
|
|
352
431
|
}
|
|
353
432
|
|
|
354
|
-
async function writeSyncBackProposal(projectRoot: string, runId: string, taskId: string, status: string, artifacts: string[], gaps: SddTaskGap[], summary: string): Promise<{ absolutePath: string; runRelativePath: string; digest: string }> {
|
|
433
|
+
async function writeSyncBackProposal(projectRoot: string, runId: string, taskId: string, status: string, artifacts: string[], gaps: SddTaskGap[], summary: string): Promise<{ absolutePath: string; runRelativePath: string; digest: string; payloadId: string }> {
|
|
355
434
|
const content = `# Sync-back Proposal\n\n## ${taskId}\n\n- status: ${status}\n- summary: ${summary}\n- artifacts:\n${artifacts.length > 0 ? artifacts.map((artifact) => ` - ${artifact}`).join('\n') : ' - none'}\n- gaps:\n${gaps.length > 0 ? gaps.map((gap) => ` - [${gap.severity}] ${gap.type} ${gap.field}: ${gap.message}`).join('\n') : ' - none'}\n\n## Boundaries\n\n- Proposal only; tasks.md/spec.md/plan.md were not modified by runtime.\n- Runtime modeled agent/verify steps through supplied artifacts and contract validation; no external agent API was invoked.\n`;
|
|
435
|
+
const digest = hashDocumentContent(content);
|
|
356
436
|
const written = await writeArtifact(projectRoot, runId, 'sync-back-proposal.md', content);
|
|
357
|
-
return { ...written, digest:
|
|
437
|
+
return { ...written, digest, payloadId: runtimeScopedId(runId, written.runRelativePath, digest) };
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
async function recordLoopSyncBackDecision(projectRoot: string, input: { runId: string; branch: string; taskId: string; status: string; proposalPath: string; proposalDigest: string; proposalPayloadId: string; reasons: string[]; payload: unknown }): Promise<void> {
|
|
441
|
+
const now = new Date().toISOString();
|
|
442
|
+
await recordRuntimeSyncBackDecision(projectRoot, {
|
|
443
|
+
decisionId: runtimeScopedId(input.runId, input.taskId, 'sync-back'),
|
|
444
|
+
runId: input.runId,
|
|
445
|
+
branch: input.branch,
|
|
446
|
+
taskId: input.taskId,
|
|
447
|
+
status: input.status,
|
|
448
|
+
proposalPath: input.proposalPath,
|
|
449
|
+
proposalDigest: input.proposalDigest,
|
|
450
|
+
proposalPayloadId: input.proposalPayloadId,
|
|
451
|
+
reasons: input.reasons,
|
|
452
|
+
createdAt: now,
|
|
453
|
+
updatedAt: now,
|
|
454
|
+
payload: input.payload
|
|
455
|
+
});
|
|
358
456
|
}
|
|
359
457
|
|
|
360
458
|
function renderLoopGapReport(taskId: string, gaps: SddTaskGap[]): string {
|