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.
Files changed (417) hide show
  1. package/README.md +18 -23
  2. package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js +31 -28
  3. package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js.map +1 -1
  4. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js +3 -2
  5. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js.map +1 -1
  6. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.d.ts +1 -1
  7. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js +14 -5
  8. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js.map +1 -1
  9. package/node_modules/@sdd-agent-platform/core/dist/contracts.d.ts +2 -0
  10. package/node_modules/@sdd-agent-platform/core/dist/contracts.js +2 -0
  11. package/node_modules/@sdd-agent-platform/core/dist/contracts.js.map +1 -1
  12. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js +3 -3
  13. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js.map +1 -1
  14. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js +155 -1
  15. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js.map +1 -1
  16. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.d.ts +23 -0
  17. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js +54 -0
  18. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js.map +1 -0
  19. package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/contracts.d.ts +11 -0
  20. package/node_modules/@sdd-agent-platform/core/dist/execution/agent-execution-records.js +15 -8
  21. package/node_modules/@sdd-agent-platform/core/dist/execution/agent-execution-records.js.map +1 -1
  22. package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js +14 -6
  23. package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js.map +1 -1
  24. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.d.ts +112 -0
  25. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js +145 -0
  26. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js.map +1 -0
  27. package/node_modules/@sdd-agent-platform/core/dist/instructions.js +36 -36
  28. package/node_modules/@sdd-agent-platform/core/dist/instructions.js.map +1 -1
  29. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.d.ts +2 -0
  30. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js +37 -17
  31. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js.map +1 -1
  32. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.d.ts +16 -1
  33. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js +174 -16
  34. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js.map +1 -1
  35. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js +2 -2
  36. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js.map +1 -1
  37. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.d.ts +10 -0
  38. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js +31 -1
  39. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js.map +1 -1
  40. package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.d.ts +2 -17
  41. package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.js +222 -10
  42. package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.js.map +1 -1
  43. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js +5 -5
  44. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js.map +1 -1
  45. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime-config.js +27 -12
  46. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime-config.js.map +1 -1
  47. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime.d.ts +59 -1
  48. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.d.ts +3 -1
  49. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js +191 -0
  50. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js.map +1 -1
  51. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js +32 -6
  52. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js.map +1 -1
  53. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-inspection.js +11 -4
  54. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-inspection.js.map +1 -1
  55. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js +31 -3
  56. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js.map +1 -1
  57. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js +48 -15
  58. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js.map +1 -1
  59. package/node_modules/@sdd-agent-platform/core/dist/run-state/events.js +2 -2
  60. package/node_modules/@sdd-agent-platform/core/dist/run-state/events.js.map +1 -1
  61. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.d.ts +3 -1
  62. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js +15 -49
  63. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js.map +1 -1
  64. package/node_modules/@sdd-agent-platform/core/dist/run-state/invocation-ledger.js +2 -2
  65. package/node_modules/@sdd-agent-platform/core/dist/run-state/invocation-ledger.js.map +1 -1
  66. package/node_modules/@sdd-agent-platform/core/dist/run-state/model.d.ts +25 -1
  67. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js +21 -14
  68. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js.map +1 -1
  69. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.d.ts +62 -0
  70. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js +130 -0
  71. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js.map +1 -0
  72. package/node_modules/@sdd-agent-platform/core/dist/run-state.d.ts +1 -0
  73. package/node_modules/@sdd-agent-platform/core/dist/run-state.js +1 -0
  74. package/node_modules/@sdd-agent-platform/core/dist/run-state.js.map +1 -1
  75. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.d.ts +10 -0
  76. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js +44 -14
  77. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js.map +1 -1
  78. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/context.js +1 -1
  79. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/context.js.map +1 -1
  80. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.d.ts +4 -0
  81. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js +189 -0
  82. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js.map +1 -0
  83. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js +12 -3
  84. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js.map +1 -1
  85. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.d.ts +20 -0
  86. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js +101 -21
  87. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js.map +1 -1
  88. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.d.ts +62 -1
  89. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js +192 -4
  90. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js.map +1 -1
  91. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.d.ts +195 -2
  92. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js +499 -2
  93. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js.map +1 -1
  94. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js +23 -1
  95. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js.map +1 -1
  96. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.d.ts +19 -0
  97. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js +114 -12
  98. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js.map +1 -1
  99. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js +21 -0
  100. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js.map +1 -1
  101. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js +16 -2
  102. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js.map +1 -1
  103. package/node_modules/@sdd-agent-platform/core/dist/tsconfig.tsbuildinfo +1 -1
  104. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js +34 -2
  105. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js.map +1 -1
  106. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js +15 -5
  107. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js.map +1 -1
  108. package/node_modules/@sdd-agent-platform/core/dist/verification/review-gate.d.ts +22 -0
  109. package/node_modules/@sdd-agent-platform/core/dist/verification/review-gate.js +53 -0
  110. package/node_modules/@sdd-agent-platform/core/dist/verification/review-gate.js.map +1 -0
  111. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js +102 -9
  112. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js.map +1 -1
  113. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.d.ts +16 -1
  114. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js +355 -69
  115. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js.map +1 -1
  116. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.d.ts +58 -0
  117. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js +428 -0
  118. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js.map +1 -0
  119. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.d.ts +2 -0
  120. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js +116 -18
  121. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js.map +1 -1
  122. package/node_modules/@sdd-agent-platform/core/dist/verification.d.ts +2 -0
  123. package/node_modules/@sdd-agent-platform/core/dist/verification.js +2 -0
  124. package/node_modules/@sdd-agent-platform/core/dist/verification.js.map +1 -1
  125. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.d.ts +24 -0
  126. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js +182 -0
  127. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js.map +1 -0
  128. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.d.ts +4 -0
  129. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js +130 -0
  130. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js.map +1 -0
  131. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.d.ts +4 -0
  132. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js +146 -0
  133. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js.map +1 -0
  134. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.d.ts +89 -0
  135. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.js +2 -0
  136. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.js.map +1 -0
  137. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
  138. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js +16 -1
  139. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
  140. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.d.ts +8 -4
  141. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.js +25 -11
  142. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.js.map +1 -1
  143. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.d.ts +38 -0
  144. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js +122 -0
  145. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js.map +1 -0
  146. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.d.ts +27 -0
  147. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js +166 -37
  148. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js.map +1 -1
  149. package/node_modules/@sdd-agent-platform/core/dist/workflow-state.d.ts +1 -0
  150. package/node_modules/@sdd-agent-platform/core/dist/workflow-state.js +1 -0
  151. package/node_modules/@sdd-agent-platform/core/dist/workflow-state.js.map +1 -1
  152. package/node_modules/@sdd-agent-platform/core/package.json +1 -1
  153. package/node_modules/@sdd-agent-platform/core/src/ai-tools.ts +31 -28
  154. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-result.test.ts +50 -4
  155. package/node_modules/@sdd-agent-platform/core/src/config/init-project.test.ts +13 -10
  156. package/node_modules/@sdd-agent-platform/core/src/config/init-project.ts +3 -2
  157. package/node_modules/@sdd-agent-platform/core/src/config/starter-documents.ts +15 -5
  158. package/node_modules/@sdd-agent-platform/core/src/contracts.ts +2 -0
  159. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-evidence.ts +3 -3
  160. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.test.ts +117 -5
  161. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.ts +164 -1
  162. package/node_modules/@sdd-agent-platform/core/src/evidence/lookup.ts +80 -0
  163. package/node_modules/@sdd-agent-platform/core/src/evidence-runtime/contracts.ts +12 -0
  164. package/node_modules/@sdd-agent-platform/core/src/execution/agent-execution-records.ts +16 -11
  165. package/node_modules/@sdd-agent-platform/core/src/execution/background-executor.test.ts +7 -0
  166. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.test.ts +5 -0
  167. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.ts +14 -6
  168. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.test.ts +102 -0
  169. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.ts +271 -0
  170. package/node_modules/@sdd-agent-platform/core/src/execution/wave-executor.test.ts +4 -0
  171. package/node_modules/@sdd-agent-platform/core/src/governance/policy.test.ts +2 -0
  172. package/node_modules/@sdd-agent-platform/core/src/instructions.test.ts +11 -5
  173. package/node_modules/@sdd-agent-platform/core/src/instructions.ts +36 -36
  174. package/node_modules/@sdd-agent-platform/core/src/lifecycle/ship.ts +39 -17
  175. package/node_modules/@sdd-agent-platform/core/src/phase8-contracts.test.ts +3 -2
  176. package/node_modules/@sdd-agent-platform/core/src/phase8-risk-kernel.test.ts +5 -0
  177. package/node_modules/@sdd-agent-platform/core/src/planning/task-graph.test.ts +2 -0
  178. package/node_modules/@sdd-agent-platform/core/src/planning/wave-plan.test.ts +3 -0
  179. package/node_modules/@sdd-agent-platform/core/src/registries/agent-capability-catalog.ts +269 -17
  180. package/node_modules/@sdd-agent-platform/core/src/registries/agent-registry.ts +2 -2
  181. package/node_modules/@sdd-agent-platform/core/src/registries/agent-runtime-static.ts +41 -1
  182. package/node_modules/@sdd-agent-platform/core/src/registries/capability-sources.ts +238 -15
  183. package/node_modules/@sdd-agent-platform/core/src/registries/registries.test.ts +27 -2
  184. package/node_modules/@sdd-agent-platform/core/src/registries/workflow-gates.ts +5 -5
  185. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime-config.ts +31 -12
  186. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime.ts +66 -1
  187. package/node_modules/@sdd-agent-platform/core/src/router/route-projection.ts +211 -0
  188. package/node_modules/@sdd-agent-platform/core/src/router/route-sdd-task.test.ts +151 -3
  189. package/node_modules/@sdd-agent-platform/core/src/router/routing.ts +35 -6
  190. package/node_modules/@sdd-agent-platform/core/src/router/runtime-inspection.ts +11 -4
  191. package/node_modules/@sdd-agent-platform/core/src/router/runtime-validation.ts +32 -3
  192. package/node_modules/@sdd-agent-platform/core/src/run-state/artifacts.ts +48 -15
  193. package/node_modules/@sdd-agent-platform/core/src/run-state/events.ts +2 -2
  194. package/node_modules/@sdd-agent-platform/core/src/run-state/inspect-run.ts +17 -52
  195. package/node_modules/@sdd-agent-platform/core/src/run-state/invocation-ledger.ts +2 -2
  196. package/node_modules/@sdd-agent-platform/core/src/run-state/model.ts +28 -1
  197. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.test.ts +3 -0
  198. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.ts +22 -18
  199. package/node_modules/@sdd-agent-platform/core/src/run-state/task-evidence.ts +206 -0
  200. package/node_modules/@sdd-agent-platform/core/src/run-state.ts +1 -0
  201. package/node_modules/@sdd-agent-platform/core/src/runtime-paths.ts +54 -14
  202. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/context.ts +1 -1
  203. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/document-hashes.ts +207 -0
  204. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/run-binding.ts +12 -3
  205. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.test.ts +139 -0
  206. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.ts +137 -24
  207. package/node_modules/@sdd-agent-platform/core/src/status/project-status.ts +268 -5
  208. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.test.ts +368 -4
  209. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.ts +697 -2
  210. package/node_modules/@sdd-agent-platform/core/src/sync-back/apply.ts +23 -1
  211. package/node_modules/@sdd-agent-platform/core/src/sync-back/inspect.ts +145 -12
  212. package/node_modules/@sdd-agent-platform/core/src/sync-back/sync-back.test.ts +132 -9
  213. package/node_modules/@sdd-agent-platform/core/src/test-support/fixtures.ts +21 -0
  214. package/node_modules/@sdd-agent-platform/core/src/test-support/run-state.ts +16 -2
  215. package/node_modules/@sdd-agent-platform/core/src/verification/goal-verify.test.ts +1 -1
  216. package/node_modules/@sdd-agent-platform/core/src/verification/goal-verify.ts +38 -5
  217. package/node_modules/@sdd-agent-platform/core/src/verification/rendering.ts +15 -5
  218. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.test.ts +77 -0
  219. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.ts +77 -0
  220. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.test.ts +64 -4
  221. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.ts +110 -12
  222. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.test.ts +72 -25
  223. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.ts +402 -77
  224. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.test.ts +341 -0
  225. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.ts +513 -0
  226. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.test.ts +144 -5
  227. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.ts +129 -18
  228. package/node_modules/@sdd-agent-platform/core/src/verification.ts +2 -0
  229. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/evidence-packet.ts +196 -0
  230. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.test.ts +171 -0
  231. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.ts +143 -0
  232. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.test.ts +137 -0
  233. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.ts +155 -0
  234. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/types.ts +114 -0
  235. package/node_modules/@sdd-agent-platform/core/src/workflow-state/affected-file-conflicts.ts +18 -1
  236. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.test.ts +1 -1
  237. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.ts +33 -11
  238. package/node_modules/@sdd-agent-platform/core/src/workflow-state/latest-eligible-run.ts +156 -0
  239. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.test.ts +351 -2
  240. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.ts +227 -39
  241. package/node_modules/@sdd-agent-platform/core/src/workflow-state.ts +1 -0
  242. package/package.json +1 -1
  243. package/packages/cli/dist/commands/status.js +2 -2
  244. package/packages/cli/dist/commands/status.js.map +1 -1
  245. package/packages/cli/dist/commands/sync-back.js +1 -1
  246. package/packages/cli/dist/commands/sync-back.js.map +1 -1
  247. package/packages/cli/dist/commands/tasks.js +4 -4
  248. package/packages/cli/dist/commands/tasks.js.map +1 -1
  249. package/packages/cli/dist/commands/test.js +94 -5
  250. package/packages/cli/dist/commands/test.js.map +1 -1
  251. package/packages/cli/dist/commands/verifies.js +5 -3
  252. package/packages/cli/dist/commands/verifies.js.map +1 -1
  253. package/packages/cli/dist/commands/verify.js +48 -7
  254. package/packages/cli/dist/commands/verify.js.map +1 -1
  255. package/packages/cli/dist/help.js +32 -18
  256. package/packages/cli/dist/help.js.map +1 -1
  257. package/packages/cli/dist/renderers/artifacts.js +1 -1
  258. package/packages/cli/dist/renderers/artifacts.js.map +1 -1
  259. package/packages/cli/dist/renderers/registry-runtime.js +7 -2
  260. package/packages/cli/dist/renderers/registry-runtime.js.map +1 -1
  261. package/packages/cli/dist/renderers/router.js +4 -2
  262. package/packages/cli/dist/renderers/router.js.map +1 -1
  263. package/packages/cli/dist/renderers/workflow.js +33 -12
  264. package/packages/cli/dist/renderers/workflow.js.map +1 -1
  265. package/packages/cli/dist/tsconfig.tsbuildinfo +1 -1
  266. package/packages/cli/package.json +2 -2
  267. package/packages/core/dist/ai-tools.js +31 -28
  268. package/packages/core/dist/ai-tools.js.map +1 -1
  269. package/packages/core/dist/config/init-project.js +3 -2
  270. package/packages/core/dist/config/init-project.js.map +1 -1
  271. package/packages/core/dist/config/starter-documents.d.ts +1 -1
  272. package/packages/core/dist/config/starter-documents.js +14 -5
  273. package/packages/core/dist/config/starter-documents.js.map +1 -1
  274. package/packages/core/dist/contracts.d.ts +2 -0
  275. package/packages/core/dist/contracts.js +2 -0
  276. package/packages/core/dist/contracts.js.map +1 -1
  277. package/packages/core/dist/doctor/checks/run-evidence.js +3 -3
  278. package/packages/core/dist/doctor/checks/run-evidence.js.map +1 -1
  279. package/packages/core/dist/doctor/doctor.js +155 -1
  280. package/packages/core/dist/doctor/doctor.js.map +1 -1
  281. package/packages/core/dist/evidence/lookup.d.ts +23 -0
  282. package/packages/core/dist/evidence/lookup.js +54 -0
  283. package/packages/core/dist/evidence/lookup.js.map +1 -0
  284. package/packages/core/dist/evidence-runtime/contracts.d.ts +11 -0
  285. package/packages/core/dist/execution/agent-execution-records.js +15 -8
  286. package/packages/core/dist/execution/agent-execution-records.js.map +1 -1
  287. package/packages/core/dist/execution/resident-worker.js +14 -6
  288. package/packages/core/dist/execution/resident-worker.js.map +1 -1
  289. package/packages/core/dist/execution/stage-team-runtime.d.ts +112 -0
  290. package/packages/core/dist/execution/stage-team-runtime.js +145 -0
  291. package/packages/core/dist/execution/stage-team-runtime.js.map +1 -0
  292. package/packages/core/dist/instructions.js +36 -36
  293. package/packages/core/dist/instructions.js.map +1 -1
  294. package/packages/core/dist/lifecycle/ship.d.ts +2 -0
  295. package/packages/core/dist/lifecycle/ship.js +37 -17
  296. package/packages/core/dist/lifecycle/ship.js.map +1 -1
  297. package/packages/core/dist/registries/agent-capability-catalog.d.ts +16 -1
  298. package/packages/core/dist/registries/agent-capability-catalog.js +174 -16
  299. package/packages/core/dist/registries/agent-capability-catalog.js.map +1 -1
  300. package/packages/core/dist/registries/agent-registry.js +2 -2
  301. package/packages/core/dist/registries/agent-registry.js.map +1 -1
  302. package/packages/core/dist/registries/agent-runtime-static.d.ts +10 -0
  303. package/packages/core/dist/registries/agent-runtime-static.js +31 -1
  304. package/packages/core/dist/registries/agent-runtime-static.js.map +1 -1
  305. package/packages/core/dist/registries/capability-sources.d.ts +2 -17
  306. package/packages/core/dist/registries/capability-sources.js +222 -10
  307. package/packages/core/dist/registries/capability-sources.js.map +1 -1
  308. package/packages/core/dist/registries/workflow-gates.js +5 -5
  309. package/packages/core/dist/registries/workflow-gates.js.map +1 -1
  310. package/packages/core/dist/router/agent-runtime-config.js +27 -12
  311. package/packages/core/dist/router/agent-runtime-config.js.map +1 -1
  312. package/packages/core/dist/router/agent-runtime.d.ts +59 -1
  313. package/packages/core/dist/router/route-projection.d.ts +3 -1
  314. package/packages/core/dist/router/route-projection.js +191 -0
  315. package/packages/core/dist/router/route-projection.js.map +1 -1
  316. package/packages/core/dist/router/routing.js +32 -6
  317. package/packages/core/dist/router/routing.js.map +1 -1
  318. package/packages/core/dist/router/runtime-inspection.js +11 -4
  319. package/packages/core/dist/router/runtime-inspection.js.map +1 -1
  320. package/packages/core/dist/router/runtime-validation.js +31 -3
  321. package/packages/core/dist/router/runtime-validation.js.map +1 -1
  322. package/packages/core/dist/run-state/artifacts.js +48 -15
  323. package/packages/core/dist/run-state/artifacts.js.map +1 -1
  324. package/packages/core/dist/run-state/events.js +2 -2
  325. package/packages/core/dist/run-state/events.js.map +1 -1
  326. package/packages/core/dist/run-state/inspect-run.d.ts +3 -1
  327. package/packages/core/dist/run-state/inspect-run.js +15 -49
  328. package/packages/core/dist/run-state/inspect-run.js.map +1 -1
  329. package/packages/core/dist/run-state/invocation-ledger.js +2 -2
  330. package/packages/core/dist/run-state/invocation-ledger.js.map +1 -1
  331. package/packages/core/dist/run-state/model.d.ts +25 -1
  332. package/packages/core/dist/run-state/run-state.js +21 -14
  333. package/packages/core/dist/run-state/run-state.js.map +1 -1
  334. package/packages/core/dist/run-state/task-evidence.d.ts +62 -0
  335. package/packages/core/dist/run-state/task-evidence.js +130 -0
  336. package/packages/core/dist/run-state/task-evidence.js.map +1 -0
  337. package/packages/core/dist/run-state.d.ts +1 -0
  338. package/packages/core/dist/run-state.js +1 -0
  339. package/packages/core/dist/run-state.js.map +1 -1
  340. package/packages/core/dist/runtime-paths.d.ts +10 -0
  341. package/packages/core/dist/runtime-paths.js +44 -14
  342. package/packages/core/dist/runtime-paths.js.map +1 -1
  343. package/packages/core/dist/sdd-docs/context.js +1 -1
  344. package/packages/core/dist/sdd-docs/context.js.map +1 -1
  345. package/packages/core/dist/sdd-docs/document-hashes.d.ts +4 -0
  346. package/packages/core/dist/sdd-docs/document-hashes.js +189 -0
  347. package/packages/core/dist/sdd-docs/document-hashes.js.map +1 -0
  348. package/packages/core/dist/sdd-docs/run-binding.js +12 -3
  349. package/packages/core/dist/sdd-docs/run-binding.js.map +1 -1
  350. package/packages/core/dist/sdd-docs/task-parser.d.ts +20 -0
  351. package/packages/core/dist/sdd-docs/task-parser.js +101 -21
  352. package/packages/core/dist/sdd-docs/task-parser.js.map +1 -1
  353. package/packages/core/dist/status/project-status.d.ts +62 -1
  354. package/packages/core/dist/status/project-status.js +192 -4
  355. package/packages/core/dist/status/project-status.js.map +1 -1
  356. package/packages/core/dist/storage/runtime-store.d.ts +195 -2
  357. package/packages/core/dist/storage/runtime-store.js +499 -2
  358. package/packages/core/dist/storage/runtime-store.js.map +1 -1
  359. package/packages/core/dist/sync-back/apply.js +23 -1
  360. package/packages/core/dist/sync-back/apply.js.map +1 -1
  361. package/packages/core/dist/sync-back/inspect.d.ts +19 -0
  362. package/packages/core/dist/sync-back/inspect.js +114 -12
  363. package/packages/core/dist/sync-back/inspect.js.map +1 -1
  364. package/packages/core/dist/test-support/fixtures.js +21 -0
  365. package/packages/core/dist/test-support/fixtures.js.map +1 -1
  366. package/packages/core/dist/test-support/run-state.js +16 -2
  367. package/packages/core/dist/test-support/run-state.js.map +1 -1
  368. package/packages/core/dist/tsconfig.tsbuildinfo +1 -1
  369. package/packages/core/dist/verification/goal-verify.js +34 -2
  370. package/packages/core/dist/verification/goal-verify.js.map +1 -1
  371. package/packages/core/dist/verification/rendering.js +15 -5
  372. package/packages/core/dist/verification/rendering.js.map +1 -1
  373. package/packages/core/dist/verification/review-gate.d.ts +22 -0
  374. package/packages/core/dist/verification/review-gate.js +53 -0
  375. package/packages/core/dist/verification/review-gate.js.map +1 -0
  376. package/packages/core/dist/verification/single-task-loop.js +102 -9
  377. package/packages/core/dist/verification/single-task-loop.js.map +1 -1
  378. package/packages/core/dist/verification/test-runtime.d.ts +16 -1
  379. package/packages/core/dist/verification/test-runtime.js +355 -69
  380. package/packages/core/dist/verification/test-runtime.js.map +1 -1
  381. package/packages/core/dist/verification/validation-wave.d.ts +58 -0
  382. package/packages/core/dist/verification/validation-wave.js +428 -0
  383. package/packages/core/dist/verification/validation-wave.js.map +1 -0
  384. package/packages/core/dist/verification/verify-contract.d.ts +2 -0
  385. package/packages/core/dist/verification/verify-contract.js +116 -18
  386. package/packages/core/dist/verification/verify-contract.js.map +1 -1
  387. package/packages/core/dist/verification.d.ts +2 -0
  388. package/packages/core/dist/verification.js +2 -0
  389. package/packages/core/dist/verification.js.map +1 -1
  390. package/packages/core/dist/workflow-gate/evidence-packet.d.ts +24 -0
  391. package/packages/core/dist/workflow-gate/evidence-packet.js +182 -0
  392. package/packages/core/dist/workflow-gate/evidence-packet.js.map +1 -0
  393. package/packages/core/dist/workflow-gate/hard-checks.d.ts +4 -0
  394. package/packages/core/dist/workflow-gate/hard-checks.js +130 -0
  395. package/packages/core/dist/workflow-gate/hard-checks.js.map +1 -0
  396. package/packages/core/dist/workflow-gate/policy.d.ts +4 -0
  397. package/packages/core/dist/workflow-gate/policy.js +146 -0
  398. package/packages/core/dist/workflow-gate/policy.js.map +1 -0
  399. package/packages/core/dist/workflow-gate/types.d.ts +89 -0
  400. package/packages/core/dist/workflow-gate/types.js +2 -0
  401. package/packages/core/dist/workflow-gate/types.js.map +1 -0
  402. package/packages/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
  403. package/packages/core/dist/workflow-state/affected-file-conflicts.js +16 -1
  404. package/packages/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
  405. package/packages/core/dist/workflow-state/dependencies.d.ts +8 -4
  406. package/packages/core/dist/workflow-state/dependencies.js +25 -11
  407. package/packages/core/dist/workflow-state/dependencies.js.map +1 -1
  408. package/packages/core/dist/workflow-state/latest-eligible-run.d.ts +38 -0
  409. package/packages/core/dist/workflow-state/latest-eligible-run.js +122 -0
  410. package/packages/core/dist/workflow-state/latest-eligible-run.js.map +1 -0
  411. package/packages/core/dist/workflow-state/resolve.d.ts +27 -0
  412. package/packages/core/dist/workflow-state/resolve.js +166 -37
  413. package/packages/core/dist/workflow-state/resolve.js.map +1 -1
  414. package/packages/core/dist/workflow-state.d.ts +1 -0
  415. package/packages/core/dist/workflow-state.js +1 -0
  416. package/packages/core/dist/workflow-state.js.map +1 -1
  417. package/packages/core/package.json +1 -1
@@ -7,26 +7,26 @@ import { writeArtifact } from '../run-state/artifacts.js';
7
7
  import { resolveSddContext } from '../sdd-docs/context.js';
8
8
  import { bindRunStateToTask } from '../sdd-docs/run-binding.js';
9
9
  import { parseSddBranch } from '../sdd-docs/task-parser.js';
10
- import { recordRuntimeProjection, recordRuntimeTestRun, recordRuntimeTestStep, runtimeScopedId } from '../storage/runtime-store.js';
10
+ import { inspectSddTask } from '../sdd-docs/task-inspection.js';
11
+ import { recordRuntimeAcceptanceEvidenceMap, recordRuntimeDurableGap, recordRuntimeProjection, recordRuntimeTestRun, recordRuntimeTestStep, recordRuntimeValidationEnvironmentSession, recordRuntimeValidationWaveRun, runtimeScopedId, updateRuntimeDurableGapStatus } from '../storage/runtime-store.js';
11
12
  import { ACCEPTANCE_POLICY_RULESET_VERSION, SDD_EVIDENCE_CONTRACT, SDD_EVIDENCE_VERSION, SDD_RESULT_CONTRACT, SDD_RESULT_VERSION, TEST_EVIDENCE_RUN_CONTRACT_VERSION, WORKFLOW_HANDOFF_CONTRACT_VERSION } from '../contracts.js';
12
- import { inspectVerifyContract, writeVerifyContract } from './verify-contract.js';
13
+ import { inspectVerifyContract } from './verify-contract.js';
13
14
  import { ensureTaskOrchestration, inspectOrchestrationGate } from '../orchestration/runtime.js';
14
15
  import { recordStageRunProjection, recordWorkflowHandoffProjection, validateWorkflowHandoff } from '../stage-runtime/runtime.js';
15
16
  import { evaluateTaskWorkflowGate, verifyContractBlockedGate } from '../risk.js';
16
17
  import { validateSddResultArtifact } from '../artifacts/sdd-result.js';
17
18
  import { dependencyBlockingReasonsForTask } from '../workflow-state/dependencies.js';
19
+ import { routeSddTask } from '../router/route-sdd-task.js';
20
+ import { evaluateAndRecordWorkflowGateDecision } from '../workflow-gate/evidence-packet.js';
18
21
  const DEFAULT_TEST_TIMEOUT_MS = 120_000;
19
22
  const MAX_CAPTURE_BYTES = 256 * 1024;
20
23
  export async function runSddTest(projectRoot, options) {
21
24
  const context = await resolveSddContext(projectRoot, { branch: options.branch ?? undefined, branchSource: options.branch ? 'cli_option' : undefined });
22
- let model = await parseSddBranch(projectRoot, context.partition);
23
- let task = model.tasks.find((candidate) => candidate.id === options.taskId) ?? null;
25
+ const model = await parseSddBranch(projectRoot, context.partition);
26
+ const inspected = inspectSddTask(model, options.taskId);
27
+ const task = inspected.task;
24
28
  const verifyContract = await ensureVerifyContractForTest(projectRoot, context.partition);
25
29
  const verifyInspection = verifyContract.inspection;
26
- if (verifyContract.action === 'created' || verifyContract.action === 'refreshed') {
27
- model = await parseSddBranch(projectRoot, context.partition);
28
- task = model.tasks.find((candidate) => candidate.id === options.taskId) ?? null;
29
- }
30
30
  const initialState = options.runId ? await readRunState(projectRoot, options.runId) : await createRun(projectRoot);
31
31
  const state = await bindRunStateToTask(projectRoot, initialState, context, model, task, options.taskId);
32
32
  const testRunId = runtimeScopedId(state.runId, options.taskId, new Date().toISOString(), 'sdd-test');
@@ -34,6 +34,35 @@ export async function runSddTest(projectRoot, options) {
34
34
  const commands = commandInputs.map((input) => input.command);
35
35
  const gaps = [];
36
36
  const startedAt = new Date().toISOString();
37
+ const ownsValidationWave = !options.validationWave;
38
+ const validationWaveRunId = options.validationWave?.waveRunId ?? runtimeScopedId(context.partition, options.taskId, state.runId, testRunId, 'validation-wave');
39
+ const validationEnvironmentSessionId = options.validationWave?.environmentSessionId ?? runtimeScopedId(context.partition, validationWaveRunId, 'validation-env');
40
+ const validationWaveTaskIds = options.validationWave?.taskIds ?? [options.taskId];
41
+ const validationWaveAcceptanceRefs = options.validationWave?.acceptanceRefsByTask?.[options.taskId];
42
+ if (ownsValidationWave) {
43
+ await recordRuntimeValidationEnvironmentSession(projectRoot, {
44
+ sessionId: validationEnvironmentSessionId,
45
+ partition: context.partition,
46
+ runId: state.runId,
47
+ waveRunId: validationWaveRunId,
48
+ status: 'active',
49
+ reuseKey: `${context.partition}:${options.taskId}`,
50
+ createdAt: startedAt,
51
+ updatedAt: startedAt,
52
+ payload: { contract: 'phase-8.17-validation-wave-runtime-v1', mode: 'single-task' }
53
+ });
54
+ await recordRuntimeValidationWaveRun(projectRoot, {
55
+ waveRunId: validationWaveRunId,
56
+ partition: context.partition,
57
+ runId: state.runId,
58
+ taskIds: validationWaveTaskIds,
59
+ status: 'RUNNING',
60
+ environmentSessionId: validationEnvironmentSessionId,
61
+ startedAt,
62
+ completedAt: startedAt,
63
+ payload: { contract: 'phase-8.17-validation-wave-runtime-v1', mode: 'single-task', taskId: options.taskId }
64
+ });
65
+ }
37
66
  await appendEvent(projectRoot, state.runId, {
38
67
  event: 'test_runtime_started',
39
68
  runId: state.runId,
@@ -44,6 +73,7 @@ export async function runSddTest(projectRoot, options) {
44
73
  gaps.push(`Task ${options.taskId} was not found in specs/${context.partition}/tasks.md.`);
45
74
  }
46
75
  if (task) {
76
+ gaps.push(...inspected.gaps.filter((gap) => gap.severity === 'blocking').map((gap) => `${gap.field}: ${gap.message}`));
47
77
  gaps.push(...dependencyBlockingReasonsForTask(model, options.taskId));
48
78
  }
49
79
  if (verifyContract.action === 'blocked') {
@@ -91,7 +121,7 @@ export async function runSddTest(projectRoot, options) {
91
121
  const steps = [];
92
122
  if (gaps.length === 0) {
93
123
  for (const [index, commandInput] of commandInputs.entries()) {
94
- const step = await runCommandStep(projectRoot, state.runId, context.partition, options.taskId, testRunId, index + 1, commandInput, acceptanceRefsForCommand(task, commandInput.command), options.timeoutMs ?? DEFAULT_TEST_TIMEOUT_MS);
124
+ const step = await runCommandStep(projectRoot, state.runId, context.partition, options.taskId, testRunId, index + 1, commandInput, acceptanceRefsForCommand(task, commandInput.command, validationWaveAcceptanceRefs), options.timeoutMs ?? DEFAULT_TEST_TIMEOUT_MS);
95
125
  steps.push(step);
96
126
  await appendEvent(projectRoot, state.runId, {
97
127
  event: 'test_step_completed',
@@ -102,18 +132,39 @@ export async function runSddTest(projectRoot, options) {
102
132
  }
103
133
  }
104
134
  const commandStatus = deriveCommandStatus(gaps, steps);
105
- const acceptanceCoverage = buildAcceptanceCoverage(task, steps, commandStatus);
135
+ const acceptanceCoverage = buildAcceptanceCoverage(task, steps, commandStatus, validationWaveAcceptanceRefs);
106
136
  const evidenceCoverage = summarizeEvidenceCoverage(acceptanceCoverage);
107
137
  const policyJudgment = derivePolicyJudgment(commandStatus, evidenceCoverage);
108
- const status = policyJudgment;
109
- const syncBackReady = status === 'PASS';
110
- const validationArtifact = task ? await writeValidationArtifact(projectRoot, state.runId, task, status, steps, gaps) : null;
111
- const unifiedEvidence = buildUnifiedTestEvidenceRun(testRunId, context.partition, state.runId, options.taskId, commandStatus, evidenceCoverage, policyJudgment, steps, acceptanceCoverage, syncBackReady, gaps);
138
+ await recordAcceptanceEvidenceMaps(projectRoot, validationWaveRunId, testRunId, context.partition, state.runId, options.taskId, acceptanceCoverage);
139
+ const validationStatus = policyJudgment;
140
+ const syncBackReady = false;
141
+ const capabilityRoute = task ? await routeSddTask(projectRoot, { taskId: options.taskId, branch: context.partition, approved: options.approved }) : null;
142
+ const capabilityEvidence = buildCapabilityEvidenceClassification(capabilityRoute?.capabilityDecision ?? null, steps);
143
+ const validationArtifact = task ? await writeValidationArtifact(projectRoot, state.runId, task, validationStatus, steps, gaps, capabilityEvidence) : null;
144
+ const evidenceBeforeIndex = [validationArtifact?.runRelativePath, ...steps.map((step) => step.outputArtifact)].filter((item) => Boolean(item));
145
+ await persistTestRunState(projectRoot, state, options.taskId, validationStatus, commands, evidenceBeforeIndex, validationArtifact?.runRelativePath ?? null);
146
+ await resolveTestRuntimeDurableGap(projectRoot, context.partition, state.runId, options.taskId, validationStatus, gaps);
147
+ const gateDecision = (await evaluateAndRecordWorkflowGateDecision(projectRoot, {
148
+ branch: context.partition,
149
+ taskId: options.taskId,
150
+ runId: state.runId,
151
+ decisionKind: 'test'
152
+ })).decision;
153
+ const runtimeJudgment = gateDecision.status;
154
+ const status = finalStatusForTest(validationStatus, runtimeJudgment);
155
+ await recordTestRuntimeDurableGap(projectRoot, context.partition, state.runId, options.taskId, status, validationStatus, runtimeJudgment, gaps, evidenceBeforeIndex);
156
+ const unifiedEvidence = buildUnifiedTestEvidenceRun(testRunId, context.partition, state.runId, options.taskId, commandStatus, evidenceCoverage, policyJudgment, status, runtimeJudgment, steps, acceptanceCoverage, capabilityEvidence, syncBackReady, gaps, workflowGate.nextAction, gateDecision);
112
157
  const indexArtifact = await writeIndexArtifact(projectRoot, state.runId, {
113
158
  testRunId,
159
+ validationWaveRunId,
160
+ validationEnvironmentSessionId,
114
161
  branch: context.partition,
115
162
  taskId: options.taskId,
116
163
  status,
164
+ validationStatus,
165
+ workflowGateStatus: gateDecision.status,
166
+ runtimeJudgment,
167
+ workflowGateDecision: gateDecision,
117
168
  verifyContractStatus: verifyInspection.status,
118
169
  verifyContractAction: verifyContract.action,
119
170
  lifecycleGate: workflowGate.lifecycleGate,
@@ -125,6 +176,7 @@ export async function runSddTest(projectRoot, options) {
125
176
  evidenceCoverage,
126
177
  policyJudgment,
127
178
  acceptanceCoverage,
179
+ capabilityEvidence,
128
180
  syncBackReady,
129
181
  commands,
130
182
  steps,
@@ -133,9 +185,6 @@ export async function runSddTest(projectRoot, options) {
133
185
  });
134
186
  const completedAt = new Date().toISOString();
135
187
  const evidence = [validationArtifact?.runRelativePath, indexArtifact.runRelativePath, ...steps.map((step) => step.outputArtifact)].filter((item) => Boolean(item));
136
- const syncBackProposal = syncBackReady
137
- ? await writeTestSyncBackProposal(projectRoot, state.runId, options.taskId, evidence, acceptanceCoverage)
138
- : null;
139
188
  await recordRuntimeTestRun(projectRoot, {
140
189
  testRunId,
141
190
  runId: state.runId,
@@ -144,7 +193,7 @@ export async function runSddTest(projectRoot, options) {
144
193
  status,
145
194
  startedAt,
146
195
  completedAt,
147
- payload: { verifyContractStatus: verifyInspection.status, verifyContractAction: verifyContract.action, lifecycleGate: workflowGate.lifecycleGate, lifecycleProfile: workflowGate.lifecycleProfile, approvalPolicy: workflowGate.approvalPolicy, requiredStages: workflowGate.requiredStages, primaryReason: workflowGate.primaryReason, commandStatus, evidenceCoverage, policyJudgment, acceptanceCoverage, syncBackReady, commands, commandInputs, evidence, gaps, syncBackProposal: syncBackProposal?.path ?? null }
196
+ payload: { verifyContractStatus: verifyInspection.status, verifyContractAction: verifyContract.action, lifecycleGate: workflowGate.lifecycleGate, lifecycleProfile: workflowGate.lifecycleProfile, approvalPolicy: workflowGate.approvalPolicy, requiredStages: workflowGate.requiredStages, primaryReason: workflowGate.primaryReason, commandStatus, evidenceCoverage, policyJudgment, validationStatus, workflowGateStatus: gateDecision.status, runtimeJudgment, workflowGateDecision: gateDecision, acceptanceCoverage, capabilityEvidence, syncBackReady, commands, commandInputs, evidence, gaps }
148
197
  });
149
198
  await recordRuntimeProjection(projectRoot, 'test_runtime', `${context.partition}:${options.taskId}:${state.runId}`, {
150
199
  contract: 'sdd-test-runtime-v1',
@@ -152,6 +201,9 @@ export async function runSddTest(projectRoot, options) {
152
201
  runId: state.runId,
153
202
  taskId: options.taskId,
154
203
  status,
204
+ validationStatus,
205
+ workflowGateStatus: gateDecision.status,
206
+ runtimeJudgment,
155
207
  lifecycleGate: workflowGate.lifecycleGate,
156
208
  primaryReason: workflowGate.primaryReason,
157
209
  evidence,
@@ -167,20 +219,50 @@ export async function runSddTest(projectRoot, options) {
167
219
  gaps,
168
220
  riskDecision: orchestration.riskDecision
169
221
  });
170
- await persistTestRunState(projectRoot, state, options.taskId, status, commands, evidence, validationArtifact?.runRelativePath ?? null, syncBackProposal);
222
+ await persistTestGateOutcome(projectRoot, state.runId, options.taskId, status, validationStatus, commands, evidence, validationArtifact?.runRelativePath ?? null, gateDecision);
223
+ if (ownsValidationWave) {
224
+ await recordRuntimeValidationWaveRun(projectRoot, {
225
+ waveRunId: validationWaveRunId,
226
+ partition: context.partition,
227
+ runId: state.runId,
228
+ taskIds: validationWaveTaskIds,
229
+ status,
230
+ environmentSessionId: validationEnvironmentSessionId,
231
+ startedAt,
232
+ completedAt,
233
+ payload: { contract: 'phase-8.17-validation-wave-runtime-v1', mode: 'single-task', taskId: options.taskId, testRunId, evidence, gaps, workflowGateDecision: gateDecision }
234
+ });
235
+ await recordRuntimeValidationEnvironmentSession(projectRoot, {
236
+ sessionId: validationEnvironmentSessionId,
237
+ partition: context.partition,
238
+ runId: state.runId,
239
+ waveRunId: validationWaveRunId,
240
+ status: status === 'PASS' ? 'completed' : status === 'FAIL' ? 'failed' : 'blocked',
241
+ reuseKey: `${context.partition}:${options.taskId}`,
242
+ createdAt: startedAt,
243
+ updatedAt: completedAt,
244
+ payload: { contract: 'phase-8.17-validation-wave-runtime-v1', mode: 'single-task', taskId: options.taskId, validationStatus, workflowGateStatus: gateDecision.status, status }
245
+ });
246
+ }
171
247
  await appendEvent(projectRoot, state.runId, {
172
- event: status === 'PASS' ? 'test_runtime_passed' : 'test_runtime_failed',
248
+ event: status === 'PASS' ? 'test_runtime_passed' : 'test_runtime_blocked',
173
249
  runId: state.runId,
174
250
  summary: `SDD test runtime ${status} for ${options.taskId}`,
175
- data: { taskId: options.taskId, testRunId, status, evidence, gaps }
251
+ data: { taskId: options.taskId, testRunId, status, validationStatus, evidence, gaps, gateDecisionId: gateDecision.decisionId, gateStatus: gateDecision.status }
176
252
  });
177
253
  return {
178
254
  contract: 'sdd-test-runtime-v1',
179
255
  runId: state.runId,
180
256
  testRunId,
257
+ validationWaveRunId,
258
+ validationEnvironmentSessionId,
181
259
  branch: context.partition,
182
260
  taskId: options.taskId,
183
261
  status,
262
+ validationStatus,
263
+ workflowGateStatus: gateDecision.status,
264
+ runtimeJudgment,
265
+ workflowGateDecision: gateDecision,
184
266
  verifyContractStatus: verifyInspection.status,
185
267
  verifyContractAction: verifyContract.action,
186
268
  lifecycleGate: workflowGate.lifecycleGate,
@@ -192,15 +274,35 @@ export async function runSddTest(projectRoot, options) {
192
274
  evidenceCoverage,
193
275
  policyJudgment,
194
276
  acceptanceCoverage,
277
+ capabilityEvidence,
195
278
  syncBackReady,
196
279
  commands,
197
280
  steps,
198
281
  validationArtifact: validationArtifact?.runRelativePath ?? null,
199
282
  indexArtifact: indexArtifact.runRelativePath,
200
283
  gaps,
201
- next: nextForTestResult(status, context.partition, options.taskId, state.runId, indexArtifact.runRelativePath, workflowGate.nextAction)
284
+ next: nextForTestResult(status, runtimeJudgment, context.partition, options.taskId, state.runId, indexArtifact.runRelativePath, workflowGate.nextAction, gateDecision)
202
285
  };
203
286
  }
287
+ async function recordAcceptanceEvidenceMaps(projectRoot, waveRunId, testRunId, partition, runId, taskId, acceptanceCoverage) {
288
+ const createdAt = new Date().toISOString();
289
+ for (const coverage of acceptanceCoverage) {
290
+ await recordRuntimeAcceptanceEvidenceMap(projectRoot, {
291
+ mapId: runtimeScopedId(waveRunId, testRunId, taskId, coverage.acceptanceRef),
292
+ waveRunId,
293
+ testRunId,
294
+ partition,
295
+ runId,
296
+ taskId,
297
+ acceptanceRef: coverage.acceptanceRef,
298
+ status: coverage.status,
299
+ evidenceRefs: coverage.evidenceRefs.map((ref) => ref.ref),
300
+ gaps: coverage.gaps,
301
+ createdAt,
302
+ payload: coverage
303
+ });
304
+ }
305
+ }
204
306
  async function recordTestWorkflowProjection(projectRoot, input) {
205
307
  const outputRefs = input.evidence.map((ref) => ({ kind: 'artifact', ref }));
206
308
  const completedStage = {
@@ -233,19 +335,8 @@ async function recordTestWorkflowProjection(projectRoot, input) {
233
335
  await recordWorkflowHandoffProjection(projectRoot, validation.valid ? handoff : { ...handoff, status: 'blocked', blockingGaps: validation.issues, decidedAt: input.completedAt });
234
336
  }
235
337
  async function ensureVerifyContractForTest(projectRoot, branch) {
236
- let inspection = await inspectVerifyContract(projectRoot, { branch, branchSource: 'cli_option' });
237
- if (inspection.status === 'BLOCKED') {
238
- return { inspection, action: 'blocked' };
239
- }
240
- if (inspection.status === 'PASS') {
241
- return { inspection, action: 'none' };
242
- }
243
- const written = await writeVerifyContract(projectRoot, { branch, branchSource: 'cli_option', force: inspection.exists });
244
- inspection = await inspectVerifyContract(projectRoot, { branch, branchSource: 'cli_option' });
245
- if (inspection.status !== 'PASS') {
246
- return { inspection, action: 'blocked' };
247
- }
248
- return { inspection, action: written.status === 'created' ? 'created' : 'refreshed' };
338
+ const inspection = await inspectVerifyContract(projectRoot, { branch, branchSource: 'cli_option' });
339
+ return { inspection, action: inspection.status === 'PASS' ? 'none' : 'blocked' };
249
340
  }
250
341
  function verifyContractBlocker(inspection) {
251
342
  const issueSummary = inspection.issues.map((issue) => `${issue.field}: ${issue.message}`).join(' ');
@@ -272,8 +363,14 @@ export function renderSddTestResult(result) {
272
363
  '',
273
364
  resultSentenceForTest(result),
274
365
  '',
366
+ 'Decision:',
367
+ `- validation_status=${result.validationStatus}`,
368
+ `- workflow_gate_status=${result.workflowGateStatus}`,
369
+ `- workflow_gate_decision=${result.workflowGateDecision.decisionId}`,
370
+ '',
275
371
  'Why:',
276
372
  `- ${result.primaryReason}`,
373
+ `- capability_evidence=${capabilityEvidenceSummary(result.capabilityEvidence)}`,
277
374
  '',
278
375
  'Next:',
279
376
  `- ${result.next}`
@@ -386,28 +483,57 @@ function executeCommand(projectRoot, commandInput, timeoutMs) {
386
483
  child.on('close', (code, signal) => finish({ exitCode: code, signal, error: null }));
387
484
  });
388
485
  }
389
- async function writeValidationArtifact(projectRoot, runId, task, status, steps, gaps) {
390
- const artifactPath = `validation-${task.id}.md`;
486
+ async function writeValidationArtifact(projectRoot, runId, task, status, steps, gaps, capabilityEvidence) {
487
+ const artifactPath = `test-validation-${task.id}.md`;
391
488
  const runRelativePath = `artifacts/${artifactPath}`;
392
489
  const resultStatus = status === 'PASS' ? 'PASS' : status === 'FAIL' ? 'FAIL' : 'BLOCKED';
393
- const content = `# Validation ${task.id}\n\n\`\`\`sdd-result\ncontract: ${SDD_RESULT_CONTRACT}\nversion: ${SDD_RESULT_VERSION}\nagent: validator\ntask: ${task.id}\nstatus: ${resultStatus}\nartifacts:\n - ${runRelativePath}\n\`\`\`\n\n## Test Runtime\n\n- status: ${status}\n- commands:\n${steps.length > 0 ? steps.map((step) => ` - [${step.status}] ${step.command}`).join('\n') : ' - none'}\n- gaps:\n${gaps.length > 0 ? gaps.map((gap) => ` - ${gap}`).join('\n') : ' - none'}\n\n## Acceptance Evidence\n\n${renderEvidenceBlocks(task, status, runRelativePath, steps)}\n`;
490
+ const content = `# Test Validation ${task.id}\n\n\`\`\`sdd-result\ncontract: ${SDD_RESULT_CONTRACT}\nversion: ${SDD_RESULT_VERSION}\nagent: validator\ntask: ${task.id}\nstatus: ${resultStatus}\nartifacts:\n - ${runRelativePath}\n\`\`\`\n\n## Test Runtime\n\n- status: ${status}\n- commands:\n${steps.length > 0 ? steps.map((step) => ` - [${step.status}] ${step.command}`).join('\n') : ' - none'}\n- gaps:\n${gaps.length > 0 ? gaps.map((gap) => ` - ${gap}`).join('\n') : ' - none'}\n\n## Capability Evidence Classification\n\n${renderCapabilityEvidenceClassification(capabilityEvidence)}\n\n## Acceptance Evidence\n\n${renderEvidenceBlocks(task, status, runRelativePath, steps)}\n`;
394
491
  return writeArtifact(projectRoot, runId, artifactPath, content);
395
492
  }
396
- async function writeTestSyncBackProposal(projectRoot, runId, taskId, artifacts, acceptanceCoverage) {
397
- const content = `# Sync-back Proposal\n\n## ${taskId}\n\n- status: verified\n- summary: /sdd:test passed with complete command and acceptance evidence.\n- artifacts:\n${artifacts.length > 0 ? artifacts.map((artifact) => ` - ${artifact}`).join('\n') : ' - none'}\n- acceptance_coverage:\n${acceptanceCoverage.length > 0 ? acceptanceCoverage.map((coverage) => ` - [${coverage.status}] ${coverage.acceptanceRef}`).join('\n') : ' - none'}\n- gaps:\n - none\n\n## Boundaries\n\n- Proposal only; tasks.md/spec.md/plan.md were not modified by runtime.\n- /sdd:test executed declared validation commands and mapped evidence to acceptance refs.\n`;
398
- const written = await writeArtifact(projectRoot, runId, 'sync-back-proposal.md', content);
399
- return { path: written.runRelativePath, digest: hashDocumentContent(content) };
400
- }
401
493
  async function writeIndexArtifact(projectRoot, runId, payload) {
402
494
  return writeArtifact(projectRoot, runId, `test-index-${payload.taskId}.json`, `${JSON.stringify({ contract: 'sdd-test-runtime-v1', runId, ...payload }, null, 2)}\n`);
403
495
  }
404
- async function persistTestRunState(projectRoot, state, taskId, status, commands, evidence, validationArtifact, syncBackProposal) {
496
+ async function persistTestRunState(projectRoot, state, taskId, validationStatus, commands, evidence, validationArtifact) {
405
497
  const latest = await readRunState(projectRoot, state.runId);
406
498
  const knownArtifacts = new Set(latest.artifacts.map((artifact) => artifact.path));
407
499
  const now = new Date().toISOString();
408
500
  const nextArtifacts = evidence
409
501
  .filter((artifactPath) => !knownArtifacts.has(artifactPath))
410
- .map((artifactPath) => ({ path: artifactPath, kind: artifactPath.includes('validation-') ? 'validation' : 'test', task: taskId, agent: artifactPath === validationArtifact ? 'validator' : 'test-runtime', createdAt: now }));
502
+ .map((artifactPath) => ({ path: artifactPath, kind: testArtifactKind(artifactPath), task: taskId, agent: 'test-runtime', createdAt: now }));
503
+ const existingTaskState = latest.tasks[taskId];
504
+ await writeRunState(projectRoot, {
505
+ ...latest,
506
+ status: validationStatus === 'PASS' ? 'running' : validationStatus === 'FAIL' ? 'failed' : 'blocked',
507
+ phase: 'test',
508
+ currentTask: taskId,
509
+ tasks: {
510
+ ...latest.tasks,
511
+ [taskId]: {
512
+ ...baseRuntimeTaskState(existingTaskState),
513
+ status: validationStatus === 'PASS' ? 'validation_passed_pending_gate' : validationStatus === 'FAIL' ? 'validation_failed' : 'validation_blocked',
514
+ implementationStatus: existingTaskState?.implementationStatus ?? 'implemented',
515
+ verificationStatus: verificationStatusFromTest(validationStatus),
516
+ testStatus: validationStatus,
517
+ evidence
518
+ }
519
+ },
520
+ artifacts: [...latest.artifacts, ...nextArtifacts],
521
+ validation: {
522
+ status: validationStatus === 'PASS' ? 'pass' : validationStatus === 'FAIL' ? 'fail' : 'blocked',
523
+ commands,
524
+ evidence
525
+ },
526
+ syncBack: latest.syncBack
527
+ });
528
+ }
529
+ async function persistTestGateOutcome(projectRoot, runId, taskId, status, validationStatus, commands, evidence, validationArtifact, gateDecision) {
530
+ const latest = await readRunState(projectRoot, runId);
531
+ const knownArtifacts = new Set(latest.artifacts.map((artifact) => artifact.path));
532
+ const now = new Date().toISOString();
533
+ const nextArtifacts = evidence
534
+ .filter((artifactPath) => !knownArtifacts.has(artifactPath))
535
+ .map((artifactPath) => ({ path: artifactPath, kind: testArtifactKind(artifactPath), task: taskId, agent: 'test-runtime', createdAt: now }));
536
+ const existingTaskState = latest.tasks[taskId];
411
537
  await writeRunState(projectRoot, {
412
538
  ...latest,
413
539
  status: status === 'PASS' ? 'completed' : status === 'FAIL' ? 'failed' : 'blocked',
@@ -416,28 +542,67 @@ async function persistTestRunState(projectRoot, state, taskId, status, commands,
416
542
  tasks: {
417
543
  ...latest.tasks,
418
544
  [taskId]: {
419
- status: status === 'PASS' ? 'tested' : 'blocked',
545
+ ...baseRuntimeTaskState(existingTaskState),
546
+ status: runtimeTaskStatusAfterGate(status, validationStatus),
547
+ implementationStatus: existingTaskState?.implementationStatus ?? 'implemented',
548
+ verificationStatus: verificationStatusFromTest(validationStatus),
420
549
  testStatus: status,
550
+ validationStatus,
551
+ workflowGateStatus: gateDecision.status,
552
+ workflowGateDecisionId: gateDecision.decisionId,
421
553
  evidence
422
554
  }
423
555
  },
424
556
  artifacts: [...latest.artifacts, ...nextArtifacts],
425
557
  validation: {
426
- status: status === 'PASS' ? 'pass' : status === 'FAIL' ? 'fail' : 'blocked',
558
+ status: validationStatus === 'PASS' ? 'pass' : validationStatus === 'FAIL' ? 'fail' : 'blocked',
427
559
  commands,
428
560
  evidence
429
561
  },
430
- syncBack: syncBackProposal
431
- ? {
432
- mode: 'proposal',
433
- proposalPath: syncBackProposal.path,
434
- proposalDigest: syncBackProposal.digest,
435
- sourceVerifyStatus: status,
436
- status: 'proposed'
437
- }
438
- : latest.syncBack
562
+ syncBack: latest.syncBack
439
563
  });
440
564
  }
565
+ function testArtifactKind(artifactPath) {
566
+ const fileName = artifactPath.split('/').pop() ?? artifactPath;
567
+ if (fileName.startsWith('test-validation-')) {
568
+ return 'test-validation';
569
+ }
570
+ if (fileName.startsWith('test-index-')) {
571
+ return 'test-index';
572
+ }
573
+ return 'test';
574
+ }
575
+ function baseRuntimeTaskState(existing) {
576
+ return {
577
+ status: existing?.status ?? 'not_started',
578
+ implementationStatus: existing?.implementationStatus ?? 'not_started',
579
+ verificationStatus: existing?.verificationStatus ?? 'not_run',
580
+ validationBatch: existing?.validationBatch ?? null,
581
+ validationTiming: existing?.validationTiming ?? 'task_end',
582
+ requiresVerifyBeforeNext: existing?.requiresVerifyBeforeNext ?? true,
583
+ gaps: existing?.gaps,
584
+ artifacts: existing?.artifacts,
585
+ testStatus: existing?.testStatus,
586
+ workflowGateStatus: existing?.workflowGateStatus,
587
+ workflowGateDecisionId: existing?.workflowGateDecisionId,
588
+ evidence: existing?.evidence
589
+ };
590
+ }
591
+ function verificationStatusFromTest(validationStatus) {
592
+ if (validationStatus === 'PASS') {
593
+ return 'pass';
594
+ }
595
+ return validationStatus === 'FAIL' ? 'failed' : 'blocked';
596
+ }
597
+ function runtimeTaskStatusAfterGate(status, validationStatus) {
598
+ if (status === 'PASS') {
599
+ return 'implemented_verified';
600
+ }
601
+ if (validationStatus === 'PASS') {
602
+ return 'workflow_gate_blocked';
603
+ }
604
+ return validationStatus === 'FAIL' ? 'validation_failed' : 'validation_blocked';
605
+ }
441
606
  function deriveCommandStatus(gaps, steps) {
442
607
  if (gaps.length > 0 || steps.some((step) => step.status === 'blocked')) {
443
608
  return 'BLOCKED';
@@ -447,8 +612,8 @@ function deriveCommandStatus(gaps, steps) {
447
612
  }
448
613
  return 'PASS';
449
614
  }
450
- function buildAcceptanceCoverage(task, steps, commandStatus) {
451
- const acceptanceRefs = task ? taskAcceptanceRefs(task) : [];
615
+ function buildAcceptanceCoverage(task, steps, commandStatus, acceptanceRefsOverride) {
616
+ const acceptanceRefs = acceptanceRefsOverride && acceptanceRefsOverride.length > 0 ? [...new Set(acceptanceRefsOverride)] : task ? taskAcceptanceRefs(task) : [];
452
617
  return acceptanceRefs.map((acceptanceRef) => {
453
618
  const mappedSteps = steps.filter((step) => step.acceptanceRefs.includes(acceptanceRef));
454
619
  const hasPassingEvidence = mappedSteps.some((step) => step.status === 'pass');
@@ -462,7 +627,7 @@ function buildAcceptanceCoverage(task, steps, commandStatus) {
462
627
  acceptanceRef,
463
628
  status,
464
629
  evidenceRefs: mappedSteps.map((step) => ({ kind: 'artifact', ref: step.outputArtifact })),
465
- gaps: status === 'complete' ? [] : [`Acceptance ${acceptanceRef} has no complete non-stale evidence from /sdd:test.`]
630
+ gaps: status === 'complete' ? [] : [`Acceptance ${acceptanceRef} has no complete non-stale evidence from sdd test task.`]
466
631
  };
467
632
  });
468
633
  }
@@ -487,7 +652,51 @@ function derivePolicyJudgment(commandStatus, evidenceCoverage) {
487
652
  }
488
653
  return 'PASS';
489
654
  }
490
- function buildUnifiedTestEvidenceRun(id, branch, runId, taskId, commandStatus, evidenceCoverage, policyJudgment, steps, acceptanceCoverage, syncBackReady, gaps) {
655
+ async function resolveTestRuntimeDurableGap(projectRoot, branch, runId, taskId, validationStatus, gaps) {
656
+ if (validationStatus !== 'PASS' || gaps.length > 0) {
657
+ return;
658
+ }
659
+ await updateRuntimeDurableGapStatus(projectRoot, {
660
+ gapId: testRuntimeGapId(branch, runId, taskId),
661
+ status: 'resolved',
662
+ source: 'gate_policy',
663
+ payload: { validationStatus, gaps }
664
+ });
665
+ }
666
+ async function recordTestRuntimeDurableGap(projectRoot, branch, runId, taskId, status, validationStatus, runtimeJudgment, gaps, evidenceRefs) {
667
+ if (status === 'PASS' && gaps.length === 0) {
668
+ return;
669
+ }
670
+ const message = gaps[0] ?? (runtimeJudgment === 'PASS' ? `Validation status is ${validationStatus}.` : `Workflow gate status is ${runtimeJudgment}.`);
671
+ await recordRuntimeDurableGap(projectRoot, {
672
+ gapId: testRuntimeGapId(branch, runId, taskId),
673
+ partition: branch,
674
+ taskId,
675
+ runId,
676
+ stage: 'test',
677
+ gate: 'test',
678
+ source: 'runtime',
679
+ category: runtimeJudgment === 'PASS' ? 'validation' : 'workflow_gate',
680
+ severity: 'blocking',
681
+ status: 'open',
682
+ message,
683
+ recommendation: `Resolve test runtime gaps for ${taskId}, then rerun sdd test task ${taskId} --branch ${branch}.`,
684
+ evidenceRefs,
685
+ proposalRefs: [],
686
+ sourceRefs: [],
687
+ payload: { status, validationStatus, runtimeJudgment, gaps }
688
+ });
689
+ }
690
+ function testRuntimeGapId(branch, _runId, taskId) {
691
+ return runtimeScopedId(branch, taskId, 'test-runtime-gap');
692
+ }
693
+ function finalStatusForTest(validationStatus, runtimeJudgment) {
694
+ if (validationStatus !== 'PASS') {
695
+ return validationStatus;
696
+ }
697
+ return runtimeJudgment === 'PASS' ? 'PASS' : 'BLOCKED';
698
+ }
699
+ function buildUnifiedTestEvidenceRun(id, branch, runId, taskId, commandStatus, evidenceCoverage, policyJudgment, status, runtimeJudgment, steps, acceptanceCoverage, capabilityEvidence, syncBackReady, gaps, gateNextAction, gateDecision) {
491
700
  return {
492
701
  contract: TEST_EVIDENCE_RUN_CONTRACT_VERSION,
493
702
  id,
@@ -505,24 +714,98 @@ function buildUnifiedTestEvidenceRun(id, branch, runId, taskId, commandStatus, e
505
714
  completedAt: new Date().toISOString()
506
715
  })),
507
716
  acceptanceCoverage,
717
+ capabilityEvidence,
508
718
  syncBackReady,
509
719
  gaps: [...gaps, ...acceptanceCoverage.flatMap((coverage) => coverage.gaps)],
510
- next: nextForTestResult(policyJudgment, branch, taskId, runId, `artifacts/test-index-${taskId}.json`, null),
720
+ next: nextForTestResult(status, runtimeJudgment, branch, taskId, runId, `artifacts/test-index-${taskId}.json`, gateNextAction, gateDecision),
511
721
  generatedAt: new Date().toISOString()
512
722
  };
513
723
  }
514
- function nextForTestResult(status, branch, taskId, runId, indexArtifact, gateNextAction) {
724
+ function buildCapabilityEvidenceClassification(decision, steps) {
725
+ if (!decision) {
726
+ return [{
727
+ class: 'diagnostic',
728
+ source: 'runtime_diagnostic',
729
+ domainOrSourceId: 'capability-routing',
730
+ evidenceRefs: [],
731
+ acceptanceRefs: [],
732
+ provenanceRefs: [],
733
+ reason: 'Capability routing did not run; no capability output is accepted as test evidence.'
734
+ }];
735
+ }
736
+ const acceptanceRefs = [...new Set(steps.flatMap((step) => step.acceptanceRefs))];
737
+ const professionalEvidence = decision.selectedDomains.map((domain) => ({
738
+ class: 'candidate',
739
+ source: 'professional_capability',
740
+ domainOrSourceId: domain.domain,
741
+ evidenceRefs: [],
742
+ acceptanceRefs,
743
+ provenanceRefs: [{ kind: 'projection', ref: `capability:${domain.capabilityId}` }],
744
+ reason: `${domain.reason}; capability output is advisory candidate evidence until accepted by command evidence and policy refs.`
745
+ }));
746
+ const externalEvidence = decision.rejectedExternalSources.map((source) => ({
747
+ class: capabilityClassForRejectedSource(source.quarantineStatus),
748
+ source: 'external_source',
749
+ domainOrSourceId: source.sourceId,
750
+ evidenceRefs: [],
751
+ acceptanceRefs: [],
752
+ provenanceRefs: [{ kind: 'external', ref: source.sourceId }],
753
+ reason: source.reason
754
+ }));
755
+ return [...professionalEvidence, ...externalEvidence];
756
+ }
757
+ function capabilityClassForRejectedSource(status) {
758
+ if (status === 'denied') {
759
+ return 'blocked';
760
+ }
761
+ if (status === 'required' || status === 'quarantined') {
762
+ return 'quarantined';
763
+ }
764
+ return 'diagnostic';
765
+ }
766
+ function renderCapabilityEvidenceClassification(items) {
767
+ if (items.length === 0) {
768
+ return '- none';
769
+ }
770
+ return items.map((item) => `- [${item.class}] ${item.source}:${item.domainOrSourceId} — ${item.reason}`).join('\n');
771
+ }
772
+ function capabilityEvidenceSummary(items) {
773
+ if (items.length === 0) {
774
+ return 'none';
775
+ }
776
+ const counts = new Map();
777
+ for (const item of items) {
778
+ counts.set(item.class, (counts.get(item.class) ?? 0) + 1);
779
+ }
780
+ return [...counts.entries()].map(([kind, count]) => `${kind}:${count}`).join(',');
781
+ }
782
+ function nextForTestResult(status, runtimeJudgment, branch, taskId, _runId, indexArtifact, gateNextAction, gateDecision) {
515
783
  if (status === 'PASS') {
516
- return `sdd sync-back inspect ${runId} --branch ${branch} --task ${taskId}`;
784
+ return `sdd ship --branch ${branch} --dry-run`;
785
+ }
786
+ if (gateNextAction) {
787
+ return gateNextAction;
788
+ }
789
+ if (runtimeJudgment === 'HUMAN_REQUIRED') {
790
+ return gateDecision ? `Create a decision card for workflow gate ${gateDecision.decisionId}, then rerun sdd test task ${taskId} --branch ${branch}.` : `Create a decision card, then rerun sdd test task ${taskId} --branch ${branch}.`;
791
+ }
792
+ if (runtimeJudgment === 'WARN') {
793
+ return gateDecision ? `Review workflow gate ${gateDecision.decisionId} warnings, then rerun sdd test task ${taskId} --branch ${branch} or proceed only with explicit review.` : `Review workflow gate warnings, then rerun sdd test task ${taskId} --branch ${branch}.`;
517
794
  }
518
- return gateNextAction ?? `Inspect ${indexArtifact}, fix command/evidence gaps, then rerun sdd test task ${taskId} --branch ${branch}.`;
795
+ if (runtimeJudgment === 'ADVISORY_ONLY') {
796
+ return `Inspect advisor assessments for ${taskId}; advisory output cannot satisfy the test gate.`;
797
+ }
798
+ if (status === 'FAIL') {
799
+ return `Inspect ${indexArtifact}, fix failing validation commands, then rerun sdd test task ${taskId} --branch ${branch}.`;
800
+ }
801
+ return gateDecision ? `Inspect ${indexArtifact} and workflow gate ${gateDecision.decisionId}, resolve blockers, then rerun sdd test task ${taskId} --branch ${branch}.` : `Inspect ${indexArtifact}, fix command/evidence gaps, then rerun sdd test task ${taskId} --branch ${branch}.`;
519
802
  }
520
803
  function resultSentenceForTest(result) {
521
- if (result.status === 'PASS' && result.lifecycleGate === 'direct') {
522
- return 'Validation passed and sync-back is ready.';
523
- }
524
804
  if (result.status === 'PASS') {
525
- return 'Validation passed; sync-back needs review.';
805
+ return 'Validation and workflow gate passed; proceed to release readiness.';
806
+ }
807
+ if (result.validationStatus === 'PASS' && result.workflowGateStatus !== 'PASS') {
808
+ return `Validation passed, but workflow gate returned ${result.workflowGateStatus}.`;
526
809
  }
527
810
  if (result.commandStatus === 'BLOCKED') {
528
811
  return 'Blocked before validation commands ran.';
@@ -564,7 +847,10 @@ function normalizeTestCommandInput(input) {
564
847
  }
565
848
  throw new Error('Command input must include command or argv.');
566
849
  }
567
- function acceptanceRefsForCommand(task, command) {
850
+ function acceptanceRefsForCommand(task, command, acceptanceRefsOverride) {
851
+ if (acceptanceRefsOverride && acceptanceRefsOverride.length > 0) {
852
+ return [...new Set(acceptanceRefsOverride)];
853
+ }
568
854
  return [...new Set((task?.validationCommands ?? [])
569
855
  .filter((entry) => entry.command === command)
570
856
  .flatMap((entry) => entry.acceptanceRefs))];