sdd-agent-platform 0.4.2 → 0.5.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 (834) hide show
  1. package/README.md +34 -41
  2. package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js +56 -73
  3. package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js.map +1 -1
  4. package/node_modules/@sdd-agent-platform/core/dist/artifacts/ingestion.js +9 -64
  5. package/node_modules/@sdd-agent-platform/core/dist/artifacts/ingestion.js.map +1 -1
  6. package/node_modules/@sdd-agent-platform/core/dist/artifacts/sdd-evidence.js +1 -1
  7. package/node_modules/@sdd-agent-platform/core/dist/artifacts/sdd-evidence.js.map +1 -1
  8. package/node_modules/@sdd-agent-platform/core/dist/artifacts/sdd-result.js +17 -26
  9. package/node_modules/@sdd-agent-platform/core/dist/artifacts/sdd-result.js.map +1 -1
  10. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.d.ts +8 -7
  11. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js +8 -12
  12. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js.map +1 -1
  13. package/node_modules/@sdd-agent-platform/core/dist/config/project-config.d.ts +1 -1
  14. package/node_modules/@sdd-agent-platform/core/dist/config/project-config.js +1 -1
  15. package/node_modules/@sdd-agent-platform/core/dist/config/project-config.js.map +1 -1
  16. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.d.ts +3 -4
  17. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js +377 -411
  18. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js.map +1 -1
  19. package/node_modules/@sdd-agent-platform/core/dist/context/build-package.d.ts +1 -1
  20. package/node_modules/@sdd-agent-platform/core/dist/context/build-package.js +18 -25
  21. package/node_modules/@sdd-agent-platform/core/dist/context/build-package.js.map +1 -1
  22. package/node_modules/@sdd-agent-platform/core/dist/context/evidence-summary.js +8 -26
  23. package/node_modules/@sdd-agent-platform/core/dist/context/evidence-summary.js.map +1 -1
  24. package/node_modules/@sdd-agent-platform/core/dist/context/log-worker.js +2 -2
  25. package/node_modules/@sdd-agent-platform/core/dist/context/log-worker.js.map +1 -1
  26. package/node_modules/@sdd-agent-platform/core/dist/context-offload/contracts.d.ts +1 -1
  27. package/node_modules/@sdd-agent-platform/core/dist/contracts.d.ts +6 -1
  28. package/node_modules/@sdd-agent-platform/core/dist/contracts.js +5 -0
  29. package/node_modules/@sdd-agent-platform/core/dist/contracts.js.map +1 -1
  30. package/node_modules/@sdd-agent-platform/core/dist/delegation/model.d.ts +0 -3
  31. package/node_modules/@sdd-agent-platform/core/dist/delegation/validation.d.ts +0 -3
  32. package/node_modules/@sdd-agent-platform/core/dist/delegation/validation.js +4 -7
  33. package/node_modules/@sdd-agent-platform/core/dist/delegation/validation.js.map +1 -1
  34. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/document-chain.js +3 -13
  35. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/document-chain.js.map +1 -1
  36. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/local-run-index.js +1 -9
  37. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/local-run-index.js.map +1 -1
  38. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/project.js +9 -9
  39. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/project.js.map +1 -1
  40. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/registries.js +1 -0
  41. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/registries.js.map +1 -1
  42. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js +4 -4
  43. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js.map +1 -1
  44. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-trust.js +24 -0
  45. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-trust.js.map +1 -1
  46. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/runtime-contracts.js +2 -2
  47. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/runtime-contracts.js.map +1 -1
  48. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js +43 -180
  49. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js.map +1 -1
  50. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.d.ts +1 -1
  51. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js +7 -14
  52. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js.map +1 -1
  53. package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/coordination.js +110 -0
  54. package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/coordination.js.map +1 -0
  55. package/node_modules/@sdd-agent-platform/core/dist/execution/background-executor.js +4 -4
  56. package/node_modules/@sdd-agent-platform/core/dist/execution/background-executor.js.map +1 -1
  57. package/node_modules/@sdd-agent-platform/core/dist/execution/foreground-subagents.js +3 -3
  58. package/node_modules/@sdd-agent-platform/core/dist/execution/foreground-subagents.js.map +1 -1
  59. package/node_modules/@sdd-agent-platform/core/dist/execution/host-invocation.js +85 -86
  60. package/node_modules/@sdd-agent-platform/core/dist/execution/host-invocation.js.map +1 -1
  61. package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js +2 -3
  62. package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js.map +1 -1
  63. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js +2 -2
  64. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js.map +1 -1
  65. package/node_modules/@sdd-agent-platform/core/dist/governance/policy.d.ts +1 -1
  66. package/node_modules/@sdd-agent-platform/core/dist/governance/policy.js +1 -1
  67. package/node_modules/@sdd-agent-platform/core/dist/governance/policy.js.map +1 -1
  68. package/node_modules/@sdd-agent-platform/core/dist/instructions.d.ts +1 -1
  69. package/node_modules/@sdd-agent-platform/core/dist/instructions.js +31 -67
  70. package/node_modules/@sdd-agent-platform/core/dist/instructions.js.map +1 -1
  71. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/decision-gate.js +1 -1
  72. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/decision-gate.js.map +1 -1
  73. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.d.ts +0 -1
  74. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js +59 -85
  75. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js.map +1 -1
  76. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/contracts.d.ts +159 -0
  77. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/contracts.js +7 -0
  78. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/contracts.js.map +1 -0
  79. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/kernel.d.ts +16 -0
  80. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/kernel.js +461 -0
  81. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/kernel.js.map +1 -0
  82. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph.d.ts +2 -0
  83. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph.js +3 -0
  84. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph.js.map +1 -0
  85. package/node_modules/@sdd-agent-platform/core/dist/orchestration/contracts.d.ts +1 -1
  86. package/node_modules/@sdd-agent-platform/core/dist/orchestration/runtime.d.ts +2 -12
  87. package/node_modules/@sdd-agent-platform/core/dist/orchestration/runtime.js +32 -80
  88. package/node_modules/@sdd-agent-platform/core/dist/orchestration/runtime.js.map +1 -1
  89. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.d.ts +2 -5
  90. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js +27 -69
  91. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js.map +1 -1
  92. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js +118 -34
  93. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js.map +1 -1
  94. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js +1 -1
  95. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js.map +1 -1
  96. package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.js +1 -1
  97. package/node_modules/@sdd-agent-platform/core/dist/registries/command-team-runtime.d.ts +1 -1
  98. package/node_modules/@sdd-agent-platform/core/dist/registries/command-team-runtime.js +8 -15
  99. package/node_modules/@sdd-agent-platform/core/dist/registries/command-team-runtime.js.map +1 -1
  100. package/node_modules/@sdd-agent-platform/core/dist/registries/eval-learning-context.js +4 -4
  101. package/node_modules/@sdd-agent-platform/core/dist/registries/eval-learning-context.js.map +1 -1
  102. package/node_modules/@sdd-agent-platform/core/dist/registries/plan-scout-domains.d.ts +13 -0
  103. package/node_modules/@sdd-agent-platform/core/dist/registries/plan-scout-domains.js +76 -0
  104. package/node_modules/@sdd-agent-platform/core/dist/registries/plan-scout-domains.js.map +1 -0
  105. package/node_modules/@sdd-agent-platform/core/dist/registries/query-status.js +2 -2
  106. package/node_modules/@sdd-agent-platform/core/dist/registries/query-status.js.map +1 -1
  107. package/node_modules/@sdd-agent-platform/core/dist/registries/skill-capabilities.js +7 -7
  108. package/node_modules/@sdd-agent-platform/core/dist/registries/skill-capabilities.js.map +1 -1
  109. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-capabilities.js +4 -4
  110. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-capabilities.js.map +1 -1
  111. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-plugins.js +2 -2
  112. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-plugins.js.map +1 -1
  113. package/node_modules/@sdd-agent-platform/core/dist/registries/worker-adapters.js +11 -11
  114. package/node_modules/@sdd-agent-platform/core/dist/registries/worker-adapters.js.map +1 -1
  115. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.d.ts +1 -1
  116. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js +21 -21
  117. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js.map +1 -1
  118. package/node_modules/@sdd-agent-platform/core/dist/risk/consumer-diagnostics.js +2 -1
  119. package/node_modules/@sdd-agent-platform/core/dist/risk/consumer-diagnostics.js.map +1 -1
  120. package/node_modules/@sdd-agent-platform/core/dist/risk/kernel.js +6 -6
  121. package/node_modules/@sdd-agent-platform/core/dist/risk/kernel.js.map +1 -1
  122. package/node_modules/@sdd-agent-platform/core/dist/risk/legacy-adapters.js +11 -23
  123. package/node_modules/@sdd-agent-platform/core/dist/risk/legacy-adapters.js.map +1 -1
  124. package/node_modules/@sdd-agent-platform/core/dist/risk/workflow-gates.d.ts +2 -2
  125. package/node_modules/@sdd-agent-platform/core/dist/risk/workflow-gates.js +18 -20
  126. package/node_modules/@sdd-agent-platform/core/dist/risk/workflow-gates.js.map +1 -1
  127. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime.d.ts +0 -2
  128. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js +1 -1
  129. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js.map +1 -1
  130. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js +16 -48
  131. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js.map +1 -1
  132. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-import.js +11 -1
  133. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-import.js.map +1 -1
  134. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js +2 -2
  135. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js.map +1 -1
  136. package/node_modules/@sdd-agent-platform/core/dist/router/stage-route-binding.d.ts +2 -2
  137. package/node_modules/@sdd-agent-platform/core/dist/router/stage-route-binding.js +20 -28
  138. package/node_modules/@sdd-agent-platform/core/dist/router/stage-route-binding.js.map +1 -1
  139. package/node_modules/@sdd-agent-platform/core/dist/router.d.ts +0 -1
  140. package/node_modules/@sdd-agent-platform/core/dist/router.js +0 -1
  141. package/node_modules/@sdd-agent-platform/core/dist/router.js.map +1 -1
  142. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.d.ts +6 -6
  143. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js +13 -124
  144. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js.map +1 -1
  145. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.d.ts +2 -0
  146. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js +5 -7
  147. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js.map +1 -1
  148. package/node_modules/@sdd-agent-platform/core/dist/run-state/model.d.ts +28 -28
  149. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-index.d.ts +3 -2
  150. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-index.js +15 -66
  151. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-index.js.map +1 -1
  152. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js +26 -36
  153. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js.map +1 -1
  154. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.d.ts +0 -4
  155. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js +5 -51
  156. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js.map +1 -1
  157. package/node_modules/@sdd-agent-platform/core/dist/run-state.d.ts +0 -1
  158. package/node_modules/@sdd-agent-platform/core/dist/run-state.js +0 -1
  159. package/node_modules/@sdd-agent-platform/core/dist/run-state.js.map +1 -1
  160. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/build.js +1 -1
  161. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/build.js.map +1 -1
  162. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/findings.js +7 -16
  163. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/findings.js.map +1 -1
  164. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/model.d.ts +1 -2
  165. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.d.ts +0 -1
  166. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js +1 -4
  167. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js.map +1 -1
  168. package/node_modules/@sdd-agent-platform/core/dist/runtime-projection-p0.d.ts +2 -2
  169. package/node_modules/@sdd-agent-platform/core/dist/runtime-projection-p0.js +11 -0
  170. package/node_modules/@sdd-agent-platform/core/dist/runtime-projection-p0.js.map +1 -1
  171. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/artifact-depth.d.ts +14 -0
  172. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/artifact-depth.js +179 -0
  173. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/artifact-depth.js.map +1 -0
  174. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.d.ts +0 -2
  175. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js +10 -97
  176. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js.map +1 -1
  177. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.d.ts +1 -1
  178. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js +6 -8
  179. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js.map +1 -1
  180. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.d.ts +5 -2
  181. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js +85 -68
  182. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js.map +1 -1
  183. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-rendering.js +2 -2
  184. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-rendering.js.map +1 -1
  185. package/node_modules/@sdd-agent-platform/core/dist/spec-entry.js +40 -0
  186. package/node_modules/@sdd-agent-platform/core/dist/spec-entry.js.map +1 -0
  187. package/node_modules/@sdd-agent-platform/core/dist/spec-manager-contracts.d.ts +12 -0
  188. package/node_modules/@sdd-agent-platform/core/dist/spec-manager-contracts.js +2 -0
  189. package/node_modules/@sdd-agent-platform/core/dist/spec-manager-contracts.js.map +1 -0
  190. package/node_modules/@sdd-agent-platform/core/dist/stage-artifacts.d.ts +2 -2
  191. package/node_modules/@sdd-agent-platform/core/dist/stage-artifacts.js +19 -26
  192. package/node_modules/@sdd-agent-platform/core/dist/stage-artifacts.js.map +1 -1
  193. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration-contracts.d.ts +1 -1
  194. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration-contracts.js +3 -6
  195. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration-contracts.js.map +1 -1
  196. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration.d.ts +111 -263
  197. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration.js +1272 -1124
  198. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration.js.map +1 -1
  199. package/node_modules/@sdd-agent-platform/core/dist/stage-runtime/runtime.js +5 -5
  200. package/node_modules/@sdd-agent-platform/core/dist/stage-runtime/runtime.js.map +1 -1
  201. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.d.ts +1 -44
  202. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js +47 -170
  203. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js.map +1 -1
  204. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js +73 -73
  205. package/node_modules/@sdd-agent-platform/core/dist/subagents/contracts.d.ts +1 -1
  206. package/node_modules/@sdd-agent-platform/core/dist/subagents/runtime.js +7 -7
  207. package/node_modules/@sdd-agent-platform/core/dist/subagents/runtime.js.map +1 -1
  208. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.d.ts +1 -0
  209. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js +2 -0
  210. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js.map +1 -0
  211. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.d.ts +1 -0
  212. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js +2 -0
  213. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js.map +1 -0
  214. package/node_modules/@sdd-agent-platform/core/dist/sync-back.d.ts +1 -0
  215. package/node_modules/@sdd-agent-platform/core/dist/sync-back.js +2 -0
  216. package/node_modules/@sdd-agent-platform/core/dist/sync-back.js.map +1 -0
  217. package/node_modules/@sdd-agent-platform/core/dist/task-execution-contract.d.ts +167 -0
  218. package/node_modules/@sdd-agent-platform/core/dist/task-execution-contract.js +377 -0
  219. package/node_modules/@sdd-agent-platform/core/dist/task-execution-contract.js.map +1 -0
  220. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js +329 -314
  221. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js.map +1 -1
  222. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.d.ts +1 -0
  223. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js +53 -7
  224. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js.map +1 -1
  225. package/node_modules/@sdd-agent-platform/core/dist/truth-reconciliation.js +9 -12
  226. package/node_modules/@sdd-agent-platform/core/dist/truth-reconciliation.js.map +1 -1
  227. package/node_modules/@sdd-agent-platform/core/dist/tsconfig.tsbuildinfo +1 -1
  228. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.d.ts +0 -48
  229. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js +1 -520
  230. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js.map +1 -1
  231. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.d.ts +5 -5
  232. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js +14 -14
  233. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js.map +1 -1
  234. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.d.ts +1 -0
  235. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js +111 -159
  236. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js.map +1 -1
  237. package/node_modules/@sdd-agent-platform/core/dist/verification/task-evidence-judgment.d.ts +49 -0
  238. package/node_modules/@sdd-agent-platform/core/dist/verification/task-evidence-judgment.js +521 -0
  239. package/node_modules/@sdd-agent-platform/core/dist/verification/task-evidence-judgment.js.map +1 -0
  240. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js +21 -21
  241. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js.map +1 -1
  242. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.d.ts +0 -18
  243. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js +5 -27
  244. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js.map +1 -1
  245. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js +45 -45
  246. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js.map +1 -1
  247. package/node_modules/@sdd-agent-platform/core/dist/verification.d.ts +3 -3
  248. package/node_modules/@sdd-agent-platform/core/dist/verification.js +2 -2
  249. package/node_modules/@sdd-agent-platform/core/dist/verification.js.map +1 -1
  250. package/node_modules/@sdd-agent-platform/core/dist/work-units/contracts.d.ts +1 -1
  251. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js +9 -227
  252. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js.map +1 -1
  253. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js +9 -50
  254. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js.map +1 -1
  255. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js +4 -42
  256. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js.map +1 -1
  257. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.d.ts +2 -3
  258. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
  259. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js +2 -1
  260. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
  261. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.js +1 -1
  262. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.d.ts +1 -0
  263. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js +23 -63
  264. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js.map +1 -1
  265. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.d.ts +2 -2
  266. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js +43 -65
  267. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js.map +1 -1
  268. package/node_modules/@sdd-agent-platform/core/package.json +5 -2
  269. package/node_modules/@sdd-agent-platform/core/src/ai-tools.test.ts +238 -185
  270. package/node_modules/@sdd-agent-platform/core/src/ai-tools.ts +56 -73
  271. package/node_modules/@sdd-agent-platform/core/src/artifacts/ingestion.test.ts +189 -227
  272. package/node_modules/@sdd-agent-platform/core/src/artifacts/ingestion.ts +222 -278
  273. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-evidence.test.ts +28 -28
  274. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-evidence.ts +301 -301
  275. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-result.test.ts +181 -181
  276. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-result.ts +231 -240
  277. package/node_modules/@sdd-agent-platform/core/src/artifacts/templates.ts +99 -99
  278. package/node_modules/@sdd-agent-platform/core/src/artifacts.ts +4 -4
  279. package/node_modules/@sdd-agent-platform/core/src/coding-facts/contracts.ts +79 -79
  280. package/node_modules/@sdd-agent-platform/core/src/coding-facts.ts +1 -1
  281. package/node_modules/@sdd-agent-platform/core/src/config/init-project.test.ts +314 -318
  282. package/node_modules/@sdd-agent-platform/core/src/config/init-project.ts +128 -123
  283. package/node_modules/@sdd-agent-platform/core/src/config/project-config.ts +265 -265
  284. package/node_modules/@sdd-agent-platform/core/src/config/project-detection.ts +147 -147
  285. package/node_modules/@sdd-agent-platform/core/src/config/starter-documents.ts +400 -432
  286. package/node_modules/@sdd-agent-platform/core/src/context/budget.ts +30 -30
  287. package/node_modules/@sdd-agent-platform/core/src/context/build-package.ts +304 -311
  288. package/node_modules/@sdd-agent-platform/core/src/context/command-summary.ts +45 -45
  289. package/node_modules/@sdd-agent-platform/core/src/context/context-build.test.ts +188 -189
  290. package/node_modules/@sdd-agent-platform/core/src/context/evidence-summary.ts +144 -163
  291. package/node_modules/@sdd-agent-platform/core/src/context/log-worker.ts +48 -48
  292. package/node_modules/@sdd-agent-platform/core/src/context/source-refs.ts +41 -41
  293. package/node_modules/@sdd-agent-platform/core/src/context-offload/contracts.ts +47 -47
  294. package/node_modules/@sdd-agent-platform/core/src/context-offload/runtime.test.ts +71 -71
  295. package/node_modules/@sdd-agent-platform/core/src/context-offload/runtime.ts +178 -178
  296. package/node_modules/@sdd-agent-platform/core/src/context-offload.ts +2 -2
  297. package/node_modules/@sdd-agent-platform/core/src/context.ts +6 -6
  298. package/node_modules/@sdd-agent-platform/core/src/contracts/issues.ts +13 -13
  299. package/node_modules/@sdd-agent-platform/core/src/contracts.test.ts +9 -9
  300. package/node_modules/@sdd-agent-platform/core/src/contracts.ts +121 -116
  301. package/node_modules/@sdd-agent-platform/core/src/delegation/delegation.test.ts +183 -183
  302. package/node_modules/@sdd-agent-platform/core/src/delegation/model.ts +23 -26
  303. package/node_modules/@sdd-agent-platform/core/src/delegation/queue.ts +58 -58
  304. package/node_modules/@sdd-agent-platform/core/src/delegation/run-state.ts +14 -14
  305. package/node_modules/@sdd-agent-platform/core/src/delegation/state-machine.ts +90 -90
  306. package/node_modules/@sdd-agent-platform/core/src/delegation/validation.ts +124 -127
  307. package/node_modules/@sdd-agent-platform/core/src/delegation.ts +26 -26
  308. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/ai-entries.ts +28 -28
  309. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/document-chain.ts +104 -112
  310. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/local-run-index.ts +19 -27
  311. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/project.ts +84 -84
  312. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/registries.ts +252 -251
  313. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-evidence.ts +330 -330
  314. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-records.ts +79 -79
  315. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-trust.ts +128 -107
  316. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/runtime-contracts.ts +300 -300
  317. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.test.ts +628 -755
  318. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.ts +301 -453
  319. package/node_modules/@sdd-agent-platform/core/src/doctor/model.ts +13 -13
  320. package/node_modules/@sdd-agent-platform/core/src/doctor/summary.ts +11 -11
  321. package/node_modules/@sdd-agent-platform/core/src/doctor.ts +2 -2
  322. package/node_modules/@sdd-agent-platform/core/src/evidence/lookup.ts +80 -88
  323. package/node_modules/@sdd-agent-platform/core/src/evidence-runtime/contracts.ts +48 -48
  324. package/node_modules/@sdd-agent-platform/core/src/evidence-runtime.ts +1 -1
  325. package/node_modules/@sdd-agent-platform/core/src/execution/agent-execution-records.ts +195 -195
  326. package/node_modules/@sdd-agent-platform/core/src/execution/background-executor.test.ts +187 -235
  327. package/node_modules/@sdd-agent-platform/core/src/execution/background-executor.ts +305 -305
  328. package/node_modules/@sdd-agent-platform/core/src/execution/foreground-subagents.test.ts +97 -106
  329. package/node_modules/@sdd-agent-platform/core/src/execution/foreground-subagents.ts +453 -453
  330. package/node_modules/@sdd-agent-platform/core/src/execution/host-invocation.ts +225 -226
  331. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.test.ts +132 -143
  332. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.ts +436 -437
  333. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.test.ts +102 -102
  334. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.ts +271 -271
  335. package/node_modules/@sdd-agent-platform/core/src/execution/wave-executor.test.ts +111 -121
  336. package/node_modules/@sdd-agent-platform/core/src/execution/wave-executor.ts +231 -231
  337. package/node_modules/@sdd-agent-platform/core/src/execution.ts +5 -5
  338. package/node_modules/@sdd-agent-platform/core/src/governance/policy.test.ts +57 -65
  339. package/node_modules/@sdd-agent-platform/core/src/governance/policy.ts +175 -175
  340. package/node_modules/@sdd-agent-platform/core/src/governance.ts +1 -1
  341. package/node_modules/@sdd-agent-platform/core/src/instructions.test.ts +80 -64
  342. package/node_modules/@sdd-agent-platform/core/src/instructions.ts +32 -68
  343. package/node_modules/@sdd-agent-platform/core/src/lifecycle/decision-gate.test.ts +174 -174
  344. package/node_modules/@sdd-agent-platform/core/src/lifecycle/decision-gate.ts +373 -373
  345. package/node_modules/@sdd-agent-platform/core/src/lifecycle/rendering.ts +29 -29
  346. package/node_modules/@sdd-agent-platform/core/src/lifecycle/risk-signals.ts +146 -146
  347. package/node_modules/@sdd-agent-platform/core/src/lifecycle/ship.test.ts +47 -47
  348. package/node_modules/@sdd-agent-platform/core/src/lifecycle/ship.ts +255 -280
  349. package/node_modules/@sdd-agent-platform/core/src/lifecycle-graph/contracts.ts +179 -0
  350. package/node_modules/@sdd-agent-platform/core/src/lifecycle-graph/kernel.ts +522 -0
  351. package/node_modules/@sdd-agent-platform/core/src/lifecycle-graph.ts +2 -0
  352. package/node_modules/@sdd-agent-platform/core/src/lifecycle.ts +4 -4
  353. package/node_modules/@sdd-agent-platform/core/src/orchestration/contracts.ts +50 -50
  354. package/node_modules/@sdd-agent-platform/core/src/orchestration/index.ts +2 -2
  355. package/node_modules/@sdd-agent-platform/core/src/orchestration/runtime.ts +331 -394
  356. package/node_modules/@sdd-agent-platform/core/src/path-safety.test.ts +22 -22
  357. package/node_modules/@sdd-agent-platform/core/src/phase8-contracts.test.ts +243 -242
  358. package/node_modules/@sdd-agent-platform/core/src/phase8-projection-compat.test.ts +152 -153
  359. package/node_modules/@sdd-agent-platform/core/src/phase8-risk-kernel.test.ts +277 -277
  360. package/node_modules/@sdd-agent-platform/core/src/phase9-lifecycle-graph.test.ts +103 -0
  361. package/node_modules/@sdd-agent-platform/core/src/planning/task-graph.test.ts +88 -88
  362. package/node_modules/@sdd-agent-platform/core/src/planning/task-graph.ts +222 -222
  363. package/node_modules/@sdd-agent-platform/core/src/planning/wave-plan.test.ts +79 -79
  364. package/node_modules/@sdd-agent-platform/core/src/planning/wave-plan.ts +160 -160
  365. package/node_modules/@sdd-agent-platform/core/src/planning.ts +2 -2
  366. package/node_modules/@sdd-agent-platform/core/src/registries/agent-capability-catalog.ts +426 -473
  367. package/node_modules/@sdd-agent-platform/core/src/registries/agent-registry.ts +230 -146
  368. package/node_modules/@sdd-agent-platform/core/src/registries/agent-runtime-static.ts +142 -142
  369. package/node_modules/@sdd-agent-platform/core/src/registries/capability-sources.ts +253 -253
  370. package/node_modules/@sdd-agent-platform/core/src/registries/command-team-runtime.ts +302 -309
  371. package/node_modules/@sdd-agent-platform/core/src/registries/eval-learning-context.ts +246 -246
  372. package/node_modules/@sdd-agent-platform/core/src/registries/plan-scout-domains.ts +89 -0
  373. package/node_modules/@sdd-agent-platform/core/src/registries/query-status.ts +119 -119
  374. package/node_modules/@sdd-agent-platform/core/src/registries/registries.test.ts +454 -445
  375. package/node_modules/@sdd-agent-platform/core/src/registries/skill-capabilities.ts +37 -37
  376. package/node_modules/@sdd-agent-platform/core/src/registries/tool-capabilities.ts +135 -135
  377. package/node_modules/@sdd-agent-platform/core/src/registries/tool-plugins.ts +132 -132
  378. package/node_modules/@sdd-agent-platform/core/src/registries/worker-adapters.ts +144 -144
  379. package/node_modules/@sdd-agent-platform/core/src/registries/workflow-gates.ts +111 -111
  380. package/node_modules/@sdd-agent-platform/core/src/registries.ts +42 -42
  381. package/node_modules/@sdd-agent-platform/core/src/risk/consumer-diagnostics.ts +98 -97
  382. package/node_modules/@sdd-agent-platform/core/src/risk/contracts.ts +63 -63
  383. package/node_modules/@sdd-agent-platform/core/src/risk/kernel.ts +233 -233
  384. package/node_modules/@sdd-agent-platform/core/src/risk/legacy-adapters.ts +251 -263
  385. package/node_modules/@sdd-agent-platform/core/src/risk/workflow-gates.ts +203 -205
  386. package/node_modules/@sdd-agent-platform/core/src/risk.ts +5 -5
  387. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime-config.ts +327 -327
  388. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime.ts +388 -390
  389. package/node_modules/@sdd-agent-platform/core/src/router/profile-resolution.ts +154 -154
  390. package/node_modules/@sdd-agent-platform/core/src/router/risk-policy.ts +33 -33
  391. package/node_modules/@sdd-agent-platform/core/src/router/route-cache.ts +100 -100
  392. package/node_modules/@sdd-agent-platform/core/src/router/route-projection.ts +356 -356
  393. package/node_modules/@sdd-agent-platform/core/src/router/route-sdd-task.test.ts +428 -665
  394. package/node_modules/@sdd-agent-platform/core/src/router/route-sdd-task.ts +2 -2
  395. package/node_modules/@sdd-agent-platform/core/src/router/routing-rules.ts +73 -73
  396. package/node_modules/@sdd-agent-platform/core/src/router/routing.ts +189 -223
  397. package/node_modules/@sdd-agent-platform/core/src/router/runtime-import.ts +464 -453
  398. package/node_modules/@sdd-agent-platform/core/src/router/runtime-inspection.ts +124 -124
  399. package/node_modules/@sdd-agent-platform/core/src/router/runtime-registry.ts +123 -123
  400. package/node_modules/@sdd-agent-platform/core/src/router/runtime-validation.ts +277 -277
  401. package/node_modules/@sdd-agent-platform/core/src/router/stage-route-binding.ts +273 -279
  402. package/node_modules/@sdd-agent-platform/core/src/router/team-mode.ts +170 -170
  403. package/node_modules/@sdd-agent-platform/core/src/router.ts +5 -6
  404. package/node_modules/@sdd-agent-platform/core/src/run-state/artifacts.ts +126 -240
  405. package/node_modules/@sdd-agent-platform/core/src/run-state/events.ts +27 -27
  406. package/node_modules/@sdd-agent-platform/core/src/run-state/inspect-run.ts +172 -172
  407. package/node_modules/@sdd-agent-platform/core/src/run-state/invocation-ledger.ts +109 -109
  408. package/node_modules/@sdd-agent-platform/core/src/run-state/model.ts +252 -253
  409. package/node_modules/@sdd-agent-platform/core/src/run-state/run-index.test.ts +80 -52
  410. package/node_modules/@sdd-agent-platform/core/src/run-state/run-index.ts +301 -352
  411. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.test.ts +70 -118
  412. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.ts +406 -416
  413. package/node_modules/@sdd-agent-platform/core/src/run-state/task-evidence.ts +198 -252
  414. package/node_modules/@sdd-agent-platform/core/src/run-state/timing.ts +146 -146
  415. package/node_modules/@sdd-agent-platform/core/src/run-state.ts +8 -9
  416. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis/build.ts +60 -60
  417. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis/findings.ts +249 -256
  418. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis/model.ts +139 -140
  419. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis.test.ts +65 -66
  420. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis.ts +2 -2
  421. package/node_modules/@sdd-agent-platform/core/src/runtime-paths.ts +249 -253
  422. package/node_modules/@sdd-agent-platform/core/src/runtime-projection-p0.test.ts +101 -96
  423. package/node_modules/@sdd-agent-platform/core/src/runtime-projection-p0.ts +314 -292
  424. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/artifact-depth.test.ts +380 -0
  425. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/artifact-depth.ts +207 -0
  426. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/context.ts +111 -111
  427. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/document-hashes.ts +207 -306
  428. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/run-binding.ts +95 -97
  429. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-inspection.ts +39 -39
  430. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.test.ts +467 -523
  431. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.ts +738 -709
  432. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-rendering.ts +81 -81
  433. package/node_modules/@sdd-agent-platform/core/src/sdd-docs.ts +5 -5
  434. package/node_modules/@sdd-agent-platform/core/src/spec-manager-contracts.ts +13 -0
  435. package/node_modules/@sdd-agent-platform/core/src/stage-artifacts.ts +435 -450
  436. package/node_modules/@sdd-agent-platform/core/src/stage-collaboration-contracts.ts +316 -322
  437. package/node_modules/@sdd-agent-platform/core/src/stage-collaboration.test.ts +2963 -2902
  438. package/node_modules/@sdd-agent-platform/core/src/stage-collaboration.ts +5856 -5831
  439. package/node_modules/@sdd-agent-platform/core/src/stage-runtime/contracts.ts +40 -40
  440. package/node_modules/@sdd-agent-platform/core/src/stage-runtime/runtime.test.ts +209 -209
  441. package/node_modules/@sdd-agent-platform/core/src/stage-runtime/runtime.ts +360 -360
  442. package/node_modules/@sdd-agent-platform/core/src/stage-runtime.ts +2 -2
  443. package/node_modules/@sdd-agent-platform/core/src/status/project-status.test.ts +288 -511
  444. package/node_modules/@sdd-agent-platform/core/src/status/project-status.ts +651 -851
  445. package/node_modules/@sdd-agent-platform/core/src/status.ts +2 -2
  446. package/node_modules/@sdd-agent-platform/core/src/storage/json-io.ts +10 -10
  447. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.test.ts +489 -681
  448. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.ts +1981 -1981
  449. package/node_modules/@sdd-agent-platform/core/src/subagents/contracts.ts +45 -45
  450. package/node_modules/@sdd-agent-platform/core/src/subagents/runtime.test.ts +232 -232
  451. package/node_modules/@sdd-agent-platform/core/src/subagents/runtime.ts +307 -307
  452. package/node_modules/@sdd-agent-platform/core/src/subagents.ts +2 -2
  453. package/node_modules/@sdd-agent-platform/core/src/task-execution-contract.test.ts +141 -0
  454. package/node_modules/@sdd-agent-platform/core/src/task-execution-contract.ts +566 -0
  455. package/node_modules/@sdd-agent-platform/core/src/task-risk-profile.ts +193 -193
  456. package/node_modules/@sdd-agent-platform/core/src/test-support/fixtures.ts +413 -398
  457. package/node_modules/@sdd-agent-platform/core/src/test-support/run-state.ts +102 -56
  458. package/node_modules/@sdd-agent-platform/core/src/test-support.ts +2 -2
  459. package/node_modules/@sdd-agent-platform/core/src/truth-reconciliation.test.ts +72 -72
  460. package/node_modules/@sdd-agent-platform/core/src/truth-reconciliation.ts +9 -12
  461. package/node_modules/@sdd-agent-platform/core/src/verification/rendering.ts +137 -137
  462. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.test.ts +77 -84
  463. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.ts +77 -77
  464. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.ts +455 -506
  465. package/node_modules/@sdd-agent-platform/core/src/verification/{goal-verify.test.ts → task-evidence-judgment.test.ts} +261 -261
  466. package/node_modules/@sdd-agent-platform/core/src/verification/{goal-verify.ts → task-evidence-judgment.ts} +619 -619
  467. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.ts +1190 -1190
  468. package/node_modules/@sdd-agent-platform/core/src/verification/validation-cache.ts +106 -106
  469. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.ts +513 -556
  470. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.ts +334 -334
  471. package/node_modules/@sdd-agent-platform/core/src/verification.ts +8 -8
  472. package/node_modules/@sdd-agent-platform/core/src/work-units/contracts.ts +26 -26
  473. package/node_modules/@sdd-agent-platform/core/src/work-units/runtime.test.ts +88 -88
  474. package/node_modules/@sdd-agent-platform/core/src/work-units/runtime.ts +112 -112
  475. package/node_modules/@sdd-agent-platform/core/src/work-units.ts +2 -2
  476. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/evidence-packet.ts +190 -425
  477. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.test.ts +169 -507
  478. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.ts +136 -182
  479. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.test.ts +135 -174
  480. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.ts +153 -194
  481. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/types.ts +111 -115
  482. package/node_modules/@sdd-agent-platform/core/src/workflow-state/affected-file-conflicts.ts +95 -93
  483. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.test.ts +32 -32
  484. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.ts +114 -114
  485. package/node_modules/@sdd-agent-platform/core/src/workflow-state/latest-eligible-run.ts +184 -224
  486. package/node_modules/@sdd-agent-platform/core/src/workflow-state/migration-recovery.ts +158 -158
  487. package/node_modules/@sdd-agent-platform/core/src/workflow-state/repair-contract.ts +77 -77
  488. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve-task-run.ts +114 -114
  489. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.test.ts +969 -956
  490. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.ts +967 -992
  491. package/node_modules/@sdd-agent-platform/core/src/workflow-state/runtime-projections.ts +712 -712
  492. package/node_modules/@sdd-agent-platform/core/src/workflow-state.ts +2 -2
  493. package/node_modules/@sdd-agent-platform/core/src/worktree/isolation.ts +130 -130
  494. package/node_modules/@sdd-agent-platform/core/src/worktree/lifecycle.ts +269 -269
  495. package/node_modules/@sdd-agent-platform/core/src/worktree/worktree.test.ts +150 -150
  496. package/node_modules/@sdd-agent-platform/core/src/worktree.ts +2 -2
  497. package/node_modules/@sdd-agent-platform/core/tsconfig.json +15 -15
  498. package/package.json +2 -2
  499. package/packages/cli/dist/args.js +2 -2
  500. package/packages/cli/dist/args.js.map +1 -1
  501. package/packages/cli/dist/commands/ai-tools.js +2 -13
  502. package/packages/cli/dist/commands/ai-tools.js.map +1 -1
  503. package/packages/cli/dist/commands/{verifies.d.ts → artifact.d.ts} +1 -1
  504. package/packages/cli/dist/commands/artifact.js +168 -0
  505. package/packages/cli/dist/commands/artifact.js.map +1 -0
  506. package/packages/cli/dist/commands/context.js +1 -1
  507. package/packages/cli/dist/commands/context.js.map +1 -1
  508. package/packages/cli/dist/commands/evidence.js.map +1 -0
  509. package/packages/cli/dist/commands/execution.js +127 -49
  510. package/packages/cli/dist/commands/execution.js.map +1 -1
  511. package/packages/cli/dist/commands/governance.js +1 -1
  512. package/packages/cli/dist/commands/governance.js.map +1 -1
  513. package/packages/cli/dist/commands/init.js +1 -6
  514. package/packages/cli/dist/commands/init.js.map +1 -1
  515. package/packages/cli/dist/commands/instructions.d.ts +1 -1
  516. package/packages/cli/dist/commands/instructions.js +15 -1
  517. package/packages/cli/dist/commands/instructions.js.map +1 -1
  518. package/packages/cli/dist/commands/registry/runtime.js +63 -40
  519. package/packages/cli/dist/commands/registry/runtime.js.map +1 -1
  520. package/packages/cli/dist/commands/run.js +13 -52
  521. package/packages/cli/dist/commands/run.js.map +1 -1
  522. package/packages/cli/dist/commands/stage-close.d.ts +60 -0
  523. package/packages/cli/dist/commands/stage-close.js +270 -41
  524. package/packages/cli/dist/commands/stage-close.js.map +1 -1
  525. package/packages/cli/dist/commands/status.js +9 -68
  526. package/packages/cli/dist/commands/status.js.map +1 -1
  527. package/packages/cli/dist/commands/tasks.js.map +1 -1
  528. package/packages/cli/dist/dispatch.js +6 -26
  529. package/packages/cli/dist/dispatch.js.map +1 -1
  530. package/packages/cli/dist/help.js +153 -159
  531. package/packages/cli/dist/help.js.map +1 -1
  532. package/packages/cli/dist/renderers/artifacts.d.ts +5 -0
  533. package/packages/cli/dist/renderers/artifacts.js +43 -0
  534. package/packages/cli/dist/renderers/artifacts.js.map +1 -0
  535. package/packages/cli/dist/renderers/doctor.js +1 -2
  536. package/packages/cli/dist/renderers/doctor.js.map +1 -1
  537. package/packages/cli/dist/renderers/execution.js +1 -1
  538. package/packages/cli/dist/renderers/execution.js.map +1 -1
  539. package/packages/cli/dist/renderers/json.d.ts +0 -1
  540. package/packages/cli/dist/renderers/json.js +0 -3
  541. package/packages/cli/dist/renderers/json.js.map +1 -1
  542. package/packages/cli/dist/renderers/registry-runtime.d.ts +1 -2
  543. package/packages/cli/dist/renderers/registry-runtime.js +0 -20
  544. package/packages/cli/dist/renderers/registry-runtime.js.map +1 -1
  545. package/packages/cli/dist/renderers/router.js +1 -1
  546. package/packages/cli/dist/renderers/router.js.map +1 -1
  547. package/packages/cli/dist/renderers/workflow.d.ts +53 -0
  548. package/packages/cli/dist/renderers/workflow.js +93 -34
  549. package/packages/cli/dist/renderers/workflow.js.map +1 -1
  550. package/packages/cli/dist/tsconfig.tsbuildinfo +1 -1
  551. package/packages/cli/package.json +2 -2
  552. package/packages/core/dist/ai-tools.js +56 -73
  553. package/packages/core/dist/ai-tools.js.map +1 -1
  554. package/packages/core/dist/artifacts/ingestion.js +9 -64
  555. package/packages/core/dist/artifacts/ingestion.js.map +1 -1
  556. package/packages/core/dist/artifacts/sdd-evidence.js +1 -1
  557. package/packages/core/dist/artifacts/sdd-evidence.js.map +1 -1
  558. package/packages/core/dist/artifacts/sdd-result.js +17 -26
  559. package/packages/core/dist/artifacts/sdd-result.js.map +1 -1
  560. package/packages/core/dist/config/init-project.d.ts +8 -7
  561. package/packages/core/dist/config/init-project.js +8 -12
  562. package/packages/core/dist/config/init-project.js.map +1 -1
  563. package/packages/core/dist/config/project-config.d.ts +1 -1
  564. package/packages/core/dist/config/project-config.js +1 -1
  565. package/packages/core/dist/config/project-config.js.map +1 -1
  566. package/packages/core/dist/config/starter-documents.d.ts +3 -4
  567. package/packages/core/dist/config/starter-documents.js +377 -411
  568. package/packages/core/dist/config/starter-documents.js.map +1 -1
  569. package/packages/core/dist/context/build-package.d.ts +1 -1
  570. package/packages/core/dist/context/build-package.js +18 -25
  571. package/packages/core/dist/context/build-package.js.map +1 -1
  572. package/packages/core/dist/context/evidence-summary.js +8 -26
  573. package/packages/core/dist/context/evidence-summary.js.map +1 -1
  574. package/packages/core/dist/context/log-worker.js +2 -2
  575. package/packages/core/dist/context/log-worker.js.map +1 -1
  576. package/packages/core/dist/context-offload/contracts.d.ts +1 -1
  577. package/packages/core/dist/contracts.d.ts +6 -1
  578. package/packages/core/dist/contracts.js +5 -0
  579. package/packages/core/dist/contracts.js.map +1 -1
  580. package/packages/core/dist/delegation/model.d.ts +0 -3
  581. package/packages/core/dist/delegation/validation.d.ts +0 -3
  582. package/packages/core/dist/delegation/validation.js +4 -7
  583. package/packages/core/dist/delegation/validation.js.map +1 -1
  584. package/packages/core/dist/doctor/checks/document-chain.js +3 -13
  585. package/packages/core/dist/doctor/checks/document-chain.js.map +1 -1
  586. package/packages/core/dist/doctor/checks/local-run-index.js +1 -9
  587. package/packages/core/dist/doctor/checks/local-run-index.js.map +1 -1
  588. package/packages/core/dist/doctor/checks/project.js +9 -9
  589. package/packages/core/dist/doctor/checks/project.js.map +1 -1
  590. package/packages/core/dist/doctor/checks/registries.js +1 -0
  591. package/packages/core/dist/doctor/checks/registries.js.map +1 -1
  592. package/packages/core/dist/doctor/checks/run-evidence.js +4 -4
  593. package/packages/core/dist/doctor/checks/run-evidence.js.map +1 -1
  594. package/packages/core/dist/doctor/checks/run-trust.js +24 -0
  595. package/packages/core/dist/doctor/checks/run-trust.js.map +1 -1
  596. package/packages/core/dist/doctor/checks/runtime-contracts.js +2 -2
  597. package/packages/core/dist/doctor/checks/runtime-contracts.js.map +1 -1
  598. package/packages/core/dist/doctor/doctor.js +43 -180
  599. package/packages/core/dist/doctor/doctor.js.map +1 -1
  600. package/packages/core/dist/evidence/lookup.d.ts +1 -1
  601. package/packages/core/dist/evidence/lookup.js +7 -14
  602. package/packages/core/dist/evidence/lookup.js.map +1 -1
  603. package/packages/core/dist/evidence-runtime/coordination.js +110 -0
  604. package/packages/core/dist/evidence-runtime/coordination.js.map +1 -0
  605. package/packages/core/dist/execution/background-executor.js +4 -4
  606. package/packages/core/dist/execution/background-executor.js.map +1 -1
  607. package/packages/core/dist/execution/foreground-subagents.js +3 -3
  608. package/packages/core/dist/execution/foreground-subagents.js.map +1 -1
  609. package/packages/core/dist/execution/host-invocation.js +85 -86
  610. package/packages/core/dist/execution/host-invocation.js.map +1 -1
  611. package/packages/core/dist/execution/resident-worker.js +2 -3
  612. package/packages/core/dist/execution/resident-worker.js.map +1 -1
  613. package/packages/core/dist/execution/stage-team-runtime.js +2 -2
  614. package/packages/core/dist/execution/stage-team-runtime.js.map +1 -1
  615. package/packages/core/dist/governance/policy.d.ts +1 -1
  616. package/packages/core/dist/governance/policy.js +1 -1
  617. package/packages/core/dist/governance/policy.js.map +1 -1
  618. package/packages/core/dist/instructions.d.ts +1 -1
  619. package/packages/core/dist/instructions.js +31 -67
  620. package/packages/core/dist/instructions.js.map +1 -1
  621. package/packages/core/dist/lifecycle/decision-gate.js +1 -1
  622. package/packages/core/dist/lifecycle/decision-gate.js.map +1 -1
  623. package/packages/core/dist/lifecycle/ship.d.ts +0 -1
  624. package/packages/core/dist/lifecycle/ship.js +59 -85
  625. package/packages/core/dist/lifecycle/ship.js.map +1 -1
  626. package/packages/core/dist/lifecycle-graph/contracts.d.ts +159 -0
  627. package/packages/core/dist/lifecycle-graph/contracts.js +7 -0
  628. package/packages/core/dist/lifecycle-graph/contracts.js.map +1 -0
  629. package/packages/core/dist/lifecycle-graph/kernel.d.ts +16 -0
  630. package/packages/core/dist/lifecycle-graph/kernel.js +461 -0
  631. package/packages/core/dist/lifecycle-graph/kernel.js.map +1 -0
  632. package/packages/core/dist/lifecycle-graph.d.ts +2 -0
  633. package/packages/core/dist/lifecycle-graph.js +3 -0
  634. package/packages/core/dist/lifecycle-graph.js.map +1 -0
  635. package/packages/core/dist/orchestration/contracts.d.ts +1 -1
  636. package/packages/core/dist/orchestration/runtime.d.ts +2 -12
  637. package/packages/core/dist/orchestration/runtime.js +32 -80
  638. package/packages/core/dist/orchestration/runtime.js.map +1 -1
  639. package/packages/core/dist/registries/agent-capability-catalog.d.ts +2 -5
  640. package/packages/core/dist/registries/agent-capability-catalog.js +27 -69
  641. package/packages/core/dist/registries/agent-capability-catalog.js.map +1 -1
  642. package/packages/core/dist/registries/agent-registry.js +118 -34
  643. package/packages/core/dist/registries/agent-registry.js.map +1 -1
  644. package/packages/core/dist/registries/agent-runtime-static.js +1 -1
  645. package/packages/core/dist/registries/agent-runtime-static.js.map +1 -1
  646. package/packages/core/dist/registries/capability-sources.js +1 -1
  647. package/packages/core/dist/registries/command-team-runtime.d.ts +1 -1
  648. package/packages/core/dist/registries/command-team-runtime.js +8 -15
  649. package/packages/core/dist/registries/command-team-runtime.js.map +1 -1
  650. package/packages/core/dist/registries/eval-learning-context.js +4 -4
  651. package/packages/core/dist/registries/eval-learning-context.js.map +1 -1
  652. package/packages/core/dist/registries/plan-scout-domains.d.ts +13 -0
  653. package/packages/core/dist/registries/plan-scout-domains.js +76 -0
  654. package/packages/core/dist/registries/plan-scout-domains.js.map +1 -0
  655. package/packages/core/dist/registries/query-status.js +2 -2
  656. package/packages/core/dist/registries/query-status.js.map +1 -1
  657. package/packages/core/dist/registries/skill-capabilities.js +7 -7
  658. package/packages/core/dist/registries/skill-capabilities.js.map +1 -1
  659. package/packages/core/dist/registries/tool-capabilities.js +4 -4
  660. package/packages/core/dist/registries/tool-capabilities.js.map +1 -1
  661. package/packages/core/dist/registries/tool-plugins.js +2 -2
  662. package/packages/core/dist/registries/tool-plugins.js.map +1 -1
  663. package/packages/core/dist/registries/worker-adapters.js +11 -11
  664. package/packages/core/dist/registries/worker-adapters.js.map +1 -1
  665. package/packages/core/dist/registries/workflow-gates.d.ts +1 -1
  666. package/packages/core/dist/registries/workflow-gates.js +21 -21
  667. package/packages/core/dist/registries/workflow-gates.js.map +1 -1
  668. package/packages/core/dist/risk/consumer-diagnostics.js +2 -1
  669. package/packages/core/dist/risk/consumer-diagnostics.js.map +1 -1
  670. package/packages/core/dist/risk/kernel.js +6 -6
  671. package/packages/core/dist/risk/kernel.js.map +1 -1
  672. package/packages/core/dist/risk/legacy-adapters.js +11 -23
  673. package/packages/core/dist/risk/legacy-adapters.js.map +1 -1
  674. package/packages/core/dist/risk/workflow-gates.d.ts +2 -2
  675. package/packages/core/dist/risk/workflow-gates.js +18 -20
  676. package/packages/core/dist/risk/workflow-gates.js.map +1 -1
  677. package/packages/core/dist/router/agent-runtime.d.ts +0 -2
  678. package/packages/core/dist/router/route-projection.js +1 -1
  679. package/packages/core/dist/router/route-projection.js.map +1 -1
  680. package/packages/core/dist/router/routing.js +16 -48
  681. package/packages/core/dist/router/routing.js.map +1 -1
  682. package/packages/core/dist/router/runtime-import.js +11 -1
  683. package/packages/core/dist/router/runtime-import.js.map +1 -1
  684. package/packages/core/dist/router/runtime-validation.js +2 -2
  685. package/packages/core/dist/router/runtime-validation.js.map +1 -1
  686. package/packages/core/dist/router/stage-route-binding.d.ts +2 -2
  687. package/packages/core/dist/router/stage-route-binding.js +20 -28
  688. package/packages/core/dist/router/stage-route-binding.js.map +1 -1
  689. package/packages/core/dist/router.d.ts +0 -1
  690. package/packages/core/dist/router.js +0 -1
  691. package/packages/core/dist/router.js.map +1 -1
  692. package/packages/core/dist/run-state/artifacts.d.ts +6 -6
  693. package/packages/core/dist/run-state/artifacts.js +13 -124
  694. package/packages/core/dist/run-state/artifacts.js.map +1 -1
  695. package/packages/core/dist/run-state/inspect-run.d.ts +2 -0
  696. package/packages/core/dist/run-state/inspect-run.js +5 -7
  697. package/packages/core/dist/run-state/inspect-run.js.map +1 -1
  698. package/packages/core/dist/run-state/model.d.ts +28 -28
  699. package/packages/core/dist/run-state/run-index.d.ts +3 -2
  700. package/packages/core/dist/run-state/run-index.js +15 -66
  701. package/packages/core/dist/run-state/run-index.js.map +1 -1
  702. package/packages/core/dist/run-state/run-state.js +26 -36
  703. package/packages/core/dist/run-state/run-state.js.map +1 -1
  704. package/packages/core/dist/run-state/task-evidence.d.ts +0 -4
  705. package/packages/core/dist/run-state/task-evidence.js +5 -51
  706. package/packages/core/dist/run-state/task-evidence.js.map +1 -1
  707. package/packages/core/dist/run-state.d.ts +0 -1
  708. package/packages/core/dist/run-state.js +0 -1
  709. package/packages/core/dist/run-state.js.map +1 -1
  710. package/packages/core/dist/runtime-analysis/build.js +1 -1
  711. package/packages/core/dist/runtime-analysis/build.js.map +1 -1
  712. package/packages/core/dist/runtime-analysis/findings.js +7 -16
  713. package/packages/core/dist/runtime-analysis/findings.js.map +1 -1
  714. package/packages/core/dist/runtime-analysis/model.d.ts +1 -2
  715. package/packages/core/dist/runtime-paths.d.ts +0 -1
  716. package/packages/core/dist/runtime-paths.js +1 -4
  717. package/packages/core/dist/runtime-paths.js.map +1 -1
  718. package/packages/core/dist/runtime-projection-p0.d.ts +2 -2
  719. package/packages/core/dist/runtime-projection-p0.js +11 -0
  720. package/packages/core/dist/runtime-projection-p0.js.map +1 -1
  721. package/packages/core/dist/sdd-docs/artifact-depth.d.ts +14 -0
  722. package/packages/core/dist/sdd-docs/artifact-depth.js +179 -0
  723. package/packages/core/dist/sdd-docs/artifact-depth.js.map +1 -0
  724. package/packages/core/dist/sdd-docs/document-hashes.d.ts +0 -2
  725. package/packages/core/dist/sdd-docs/document-hashes.js +10 -97
  726. package/packages/core/dist/sdd-docs/document-hashes.js.map +1 -1
  727. package/packages/core/dist/sdd-docs/run-binding.d.ts +1 -1
  728. package/packages/core/dist/sdd-docs/run-binding.js +6 -8
  729. package/packages/core/dist/sdd-docs/run-binding.js.map +1 -1
  730. package/packages/core/dist/sdd-docs/task-parser.d.ts +5 -2
  731. package/packages/core/dist/sdd-docs/task-parser.js +85 -68
  732. package/packages/core/dist/sdd-docs/task-parser.js.map +1 -1
  733. package/packages/core/dist/sdd-docs/task-rendering.js +2 -2
  734. package/packages/core/dist/sdd-docs/task-rendering.js.map +1 -1
  735. package/packages/core/dist/spec-entry.js +40 -0
  736. package/packages/core/dist/spec-entry.js.map +1 -0
  737. package/packages/core/dist/spec-manager-contracts.d.ts +12 -0
  738. package/packages/core/dist/spec-manager-contracts.js +2 -0
  739. package/packages/core/dist/spec-manager-contracts.js.map +1 -0
  740. package/packages/core/dist/stage-artifacts.d.ts +2 -2
  741. package/packages/core/dist/stage-artifacts.js +19 -26
  742. package/packages/core/dist/stage-artifacts.js.map +1 -1
  743. package/packages/core/dist/stage-collaboration-contracts.d.ts +1 -1
  744. package/packages/core/dist/stage-collaboration-contracts.js +3 -6
  745. package/packages/core/dist/stage-collaboration-contracts.js.map +1 -1
  746. package/packages/core/dist/stage-collaboration.d.ts +111 -263
  747. package/packages/core/dist/stage-collaboration.js +1272 -1124
  748. package/packages/core/dist/stage-collaboration.js.map +1 -1
  749. package/packages/core/dist/stage-runtime/runtime.js +5 -5
  750. package/packages/core/dist/stage-runtime/runtime.js.map +1 -1
  751. package/packages/core/dist/status/project-status.d.ts +1 -44
  752. package/packages/core/dist/status/project-status.js +47 -170
  753. package/packages/core/dist/status/project-status.js.map +1 -1
  754. package/packages/core/dist/storage/runtime-store.js +73 -73
  755. package/packages/core/dist/subagents/contracts.d.ts +1 -1
  756. package/packages/core/dist/subagents/runtime.js +7 -7
  757. package/packages/core/dist/subagents/runtime.js.map +1 -1
  758. package/packages/core/dist/sync-back/apply.d.ts +1 -0
  759. package/packages/core/dist/sync-back/apply.js +2 -0
  760. package/packages/core/dist/sync-back/apply.js.map +1 -0
  761. package/packages/core/dist/sync-back/inspect.d.ts +1 -0
  762. package/packages/core/dist/sync-back/inspect.js +2 -0
  763. package/packages/core/dist/sync-back/inspect.js.map +1 -0
  764. package/packages/core/dist/sync-back.d.ts +1 -0
  765. package/packages/core/dist/sync-back.js +2 -0
  766. package/packages/core/dist/sync-back.js.map +1 -0
  767. package/packages/core/dist/task-execution-contract.d.ts +167 -0
  768. package/packages/core/dist/task-execution-contract.js +377 -0
  769. package/packages/core/dist/task-execution-contract.js.map +1 -0
  770. package/packages/core/dist/test-support/fixtures.js +329 -314
  771. package/packages/core/dist/test-support/fixtures.js.map +1 -1
  772. package/packages/core/dist/test-support/run-state.d.ts +1 -0
  773. package/packages/core/dist/test-support/run-state.js +53 -7
  774. package/packages/core/dist/test-support/run-state.js.map +1 -1
  775. package/packages/core/dist/truth-reconciliation.js +9 -12
  776. package/packages/core/dist/truth-reconciliation.js.map +1 -1
  777. package/packages/core/dist/tsconfig.tsbuildinfo +1 -1
  778. package/packages/core/dist/verification/goal-verify.d.ts +0 -48
  779. package/packages/core/dist/verification/goal-verify.js +1 -520
  780. package/packages/core/dist/verification/goal-verify.js.map +1 -1
  781. package/packages/core/dist/verification/rendering.d.ts +5 -5
  782. package/packages/core/dist/verification/rendering.js +14 -14
  783. package/packages/core/dist/verification/rendering.js.map +1 -1
  784. package/packages/core/dist/verification/single-task-loop.d.ts +1 -0
  785. package/packages/core/dist/verification/single-task-loop.js +111 -159
  786. package/packages/core/dist/verification/single-task-loop.js.map +1 -1
  787. package/packages/core/dist/verification/task-evidence-judgment.d.ts +49 -0
  788. package/packages/core/dist/verification/task-evidence-judgment.js +521 -0
  789. package/packages/core/dist/verification/task-evidence-judgment.js.map +1 -0
  790. package/packages/core/dist/verification/test-runtime.js +21 -21
  791. package/packages/core/dist/verification/test-runtime.js.map +1 -1
  792. package/packages/core/dist/verification/validation-wave.d.ts +0 -18
  793. package/packages/core/dist/verification/validation-wave.js +5 -27
  794. package/packages/core/dist/verification/validation-wave.js.map +1 -1
  795. package/packages/core/dist/verification/verify-contract.js +45 -45
  796. package/packages/core/dist/verification/verify-contract.js.map +1 -1
  797. package/packages/core/dist/verification.d.ts +3 -3
  798. package/packages/core/dist/verification.js +2 -2
  799. package/packages/core/dist/verification.js.map +1 -1
  800. package/packages/core/dist/work-units/contracts.d.ts +1 -1
  801. package/packages/core/dist/workflow-gate/evidence-packet.js +9 -227
  802. package/packages/core/dist/workflow-gate/evidence-packet.js.map +1 -1
  803. package/packages/core/dist/workflow-gate/hard-checks.js +9 -50
  804. package/packages/core/dist/workflow-gate/hard-checks.js.map +1 -1
  805. package/packages/core/dist/workflow-gate/policy.js +4 -42
  806. package/packages/core/dist/workflow-gate/policy.js.map +1 -1
  807. package/packages/core/dist/workflow-gate/types.d.ts +2 -3
  808. package/packages/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
  809. package/packages/core/dist/workflow-state/affected-file-conflicts.js +2 -1
  810. package/packages/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
  811. package/packages/core/dist/workflow-state/dependencies.js +1 -1
  812. package/packages/core/dist/workflow-state/latest-eligible-run.d.ts +1 -0
  813. package/packages/core/dist/workflow-state/latest-eligible-run.js +23 -63
  814. package/packages/core/dist/workflow-state/latest-eligible-run.js.map +1 -1
  815. package/packages/core/dist/workflow-state/resolve.d.ts +2 -2
  816. package/packages/core/dist/workflow-state/resolve.js +43 -65
  817. package/packages/core/dist/workflow-state/resolve.js.map +1 -1
  818. package/packages/core/package.json +5 -2
  819. package/tsconfig.build.json +6 -7
  820. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.test.ts +0 -269
  821. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.test.ts +0 -492
  822. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.test.ts +0 -383
  823. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.test.ts +0 -188
  824. package/packages/cli/dist/commands/lifecycle.d.ts +0 -6
  825. package/packages/cli/dist/commands/lifecycle.js +0 -125
  826. package/packages/cli/dist/commands/lifecycle.js.map +0 -1
  827. package/packages/cli/dist/commands/test.d.ts +0 -6
  828. package/packages/cli/dist/commands/test.js +0 -373
  829. package/packages/cli/dist/commands/test.js.map +0 -1
  830. package/packages/cli/dist/commands/verifies.js +0 -87
  831. package/packages/cli/dist/commands/verifies.js.map +0 -1
  832. package/packages/cli/dist/commands/verify.d.ts +0 -6
  833. package/packages/cli/dist/commands/verify.js +0 -330
  834. package/packages/cli/dist/commands/verify.js.map +0 -1
@@ -1,992 +1,967 @@
1
- import { readFile } from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { WORKFLOW_STATE_RESOLVER_CONTRACT_VERSION, type RuntimeProjectionEnvelope, type RuntimeRef, type SddStage } from '../contracts.js';
4
- import { listRuntimeProjections, listRuntimeRepairs, recordRuntimeProjection, type RuntimeRepairRecord } from '../storage/runtime-store.js';
5
- import type { RunState, RunStateTaskRuntime, RunSummary } from '../run-state/model.js';
6
- import { affectedFileConflictsForSelectedRun, type WorkflowAffectedFileConflict } from './affected-file-conflicts.js';
7
- import { readAllRunStates, summarizeRunState } from '../run-state/run-state.js';
8
- import { resolveSddContext, type ContextBranchSource, type ContextResolverContract } from '../sdd-docs/context.js';
9
- import { parseSddBranch, type SddTask, type SddTaskGap, type SddTaskModel } from '../sdd-docs/task-parser.js';
10
- import { dependencyBlockingReasonsForTask, workflowDependencyBlockers, type WorkflowDependencyBlocker } from './dependencies.js';
11
- import { selectLatestEligibleRunsByTask, type DocumentCompatibilityClass, type LatestEligibleRunSelection } from './latest-eligible-run.js';
12
- import {
13
- DO_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
14
- GOAL_VERIFY_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
15
- PLAN_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
16
- readTruthAlignmentProjection,
17
- SHIP_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
18
- SPEC_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
19
- TASKS_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
20
- TEST_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
21
- VERIFIES_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
22
- type TruthAlignmentProjection
23
- } from '../stage-collaboration.js';
24
- import { buildTruthReconciliationDecision, minimalReworkFrontier, recordTruthReconciliationDecision, truthDriftClassForAlignment, truthReconciliationOwnerStage, type TruthReconciliationDecision } from '../truth-reconciliation.js';
25
- import { normalizePortablePath } from '../path-safety.js';
26
- import { hashDocumentContent } from '../sdd-docs/document-hashes.js';
27
- import { recordWorkflowRuntimeProjections } from './runtime-projections.js';
28
-
29
- export interface WorkflowTaskCounts {
30
- total: number;
31
- pending: number;
32
- inProgress: number;
33
- completed: number;
34
- blocked: number;
35
- deferred: number;
36
- unknown: number;
37
- gaps: number;
38
- }
39
-
40
- export interface WorkflowLatestTaskRun {
41
- partition: string;
42
- gitBranch: string | null;
43
- taskId: string;
44
- runId: string;
45
- runStatus: RunState['status'];
46
- validationStatus: RunState['validation']['status'];
47
- affectedFiles: string[];
48
- updatedAt: string;
49
- compatibility: DocumentCompatibilityClass;
50
- eligibleForDefaultApply: boolean;
51
- reasons: string[];
52
- }
53
-
54
- export type WorkflowCommandSemantics = 'inspection_navigation' | 'gate_execution';
55
- export type WorkflowHostProjectionStatus = 'active' | 'future' | 'unsupported';
56
- export type SddCommandBundle = 'spec' | 'plan' | 'tasks' | 'do' | 'test' | 'ship';
57
- export type BundleResumeMode = 'start' | 'resume' | 'repair' | 'reconcile';
58
- export type WorkflowNextStage = SddCommandBundle;
59
- export type WorkflowNextIntentKind = 'start_spec' | 'resolve_task_gaps' | 'inspect_dependency' | 'workflow_complete' | 'ship_readiness' | 'inspect_task' | 'list_tasks' | 'continue_do' | 'run_task_validation' | 'run_batch_validation' | 'run_wave_validation' | 'run_verifies' | 'run_goal_verify' | 'repair_failure' | 'reconcile_truth';
60
-
61
- export const COMMAND_BUNDLES: Record<SddCommandBundle, readonly SddStage[]> = {
62
- spec: ['spec'],
63
- plan: ['plan'],
64
- tasks: ['tasks', 'verifies'],
65
- do: ['do'],
66
- test: ['test', 'goal-verify'],
67
- ship: ['ship']
68
- };
69
-
70
- export interface CommandBundlePlan {
71
- contract: 'sdd-command-bundle-plan-v1';
72
- branch: string;
73
- bundle: SddCommandBundle;
74
- stages: SddStage[];
75
- targetRuntimeStage: SddStage;
76
- resumeMode: BundleResumeMode;
77
- canonicalCommand: string;
78
- displayCommand: string;
79
- canAutoAdvanceWithinBundle: boolean;
80
- autoAdvanceTo: SddStage | null;
81
- stopReasons: string[];
82
- evidenceSurface: string[];
83
- }
84
-
85
- export interface WorkflowReadinessSummary {
86
- requiredTaskIds: string[];
87
- acceptedTaskIds: string[];
88
- missingTaskIds: string[];
89
- readyForShip: boolean;
90
- whyNotShip: string[];
91
- }
92
-
93
- export interface WorkflowHostCommandProjection {
94
- host: 'claude_code' | 'codex' | 'opencode';
95
- status: WorkflowHostProjectionStatus;
96
- entry: string | null;
97
- projectionSurfaces: string[];
98
- permissionProjection: string;
99
- reason: string;
100
- }
101
-
102
- export interface WorkflowNextIntent {
103
- stage: WorkflowNextStage;
104
- bundle: SddCommandBundle;
105
- targetRuntimeStage: SddStage;
106
- resumeMode: BundleResumeMode;
107
- intent: WorkflowNextIntentKind;
108
- canonicalCommand: string;
109
- displayCommand: string;
110
- commandSemantics: WorkflowCommandSemantics;
111
- evidenceRequirement: string;
112
- blockingReason: string | null;
113
- canAutoAdvanceWithinBundle: boolean;
114
- autoAdvanceTo: SddStage | null;
115
- stopReasons: string[];
116
- evidenceSurface: string[];
117
- commandBundle: CommandBundlePlan;
118
- hostProjections: WorkflowHostCommandProjection[];
119
- }
120
-
121
-
122
- export interface WorkflowStateResolution {
123
- contract: typeof WORKFLOW_STATE_RESOLVER_CONTRACT_VERSION;
124
- generatedAt: string;
125
- branch: string;
126
- workflowStatus: 'active' | 'not_started';
127
- context: ContextResolverContract;
128
- documents: SddTaskModel['documents'];
129
- model: SddTaskModel;
130
- taskCounts: WorkflowTaskCounts;
131
- visibleGaps: SddTaskGap[];
132
- latestRun: RunSummary | null;
133
- latestRunState: RunState | null;
134
- latestRunsByTask: WorkflowLatestTaskRun[];
135
- latestEligibleRunsByTask: LatestEligibleRunSelection[];
136
- affectedFileConflicts: WorkflowAffectedFileConflict[];
137
- blockingReasons: string[];
138
- dependencyBlockers: WorkflowDependencyBlocker[];
139
- openRepairs: RuntimeRepairRecord[];
140
- workflowReadiness: WorkflowReadinessSummary;
141
- whyNotShip: string[];
142
- recommendedNextCommand: string;
143
- nextIntent: WorkflowNextIntent;
144
- truthReconciliation: TruthReconciliationDecision | null;
145
- }
146
-
147
- export async function resolveWorkflowState(projectRoot: string, options: { branch?: string | null; branchSource?: ContextBranchSource; taskId?: string | null } = {}): Promise<WorkflowStateResolution> {
148
- const context = await resolveSddContext(projectRoot, options);
149
- const branch = context.partition;
150
- const [model, states, openRepairs, truthAlignmentEnvelope] = await Promise.all([parseSddBranch(projectRoot, branch), readAllRunStates(projectRoot), listRuntimeRepairs(projectRoot, { branchSlug: branch, status: 'open' }), readTruthAlignmentProjection(projectRoot, { branch })]);
151
- const visibleGaps = workflowIsActive(model) ? model.gaps : [];
152
- const latestEligibleRunsByTask = selectLatestEligibleRunsByTask({ states, model, partition: branch, currentGitBranch: context.currentGitBranch });
153
- const latestRunsByTask = selectedLatestTaskRuns(latestEligibleRunsByTask);
154
- const selectedTaskRun = options.taskId
155
- ? latestRunsByTask.find((entry) => entry.taskId === options.taskId) ?? null
156
- : latestRunsByTask.slice().sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt))[0] ?? null;
157
- const latestRunState = selectedTaskRun ? states.find((state) => state.runId === selectedTaskRun.runId) ?? null : null;
158
- const affectedFileConflicts = latestRunState ? affectedFileConflictsForSelectedRun(states, latestRunState) : [];
159
- const runtimeByTask = latestRuntimeTaskStates(latestEligibleRunsByTask, states);
160
- const dependencyBlockers = workflowDependencyBlockers(model, { runtimeByTask });
161
- const readiness = workflowReadinessSummary(model, latestRunsByTask);
162
- const generatedAt = new Date().toISOString();
163
- const blockingReasons = [...blockingWorkflowReasons(visibleGaps, affectedFileConflicts, dependencyBlockers), ...openRepairs.map(formatOpenRepairReason)];
164
- const truthReconciliation = await resolveTruthReconciliationDecision(projectRoot, branch, truthAlignmentEnvelope?.payload ?? null, generatedAt, { states, model });
165
- const resolution: WorkflowStateResolution = {
166
- contract: WORKFLOW_STATE_RESOLVER_CONTRACT_VERSION,
167
- generatedAt,
168
- branch,
169
- workflowStatus: workflowIsActive(model) ? 'active' : 'not_started',
170
- context,
171
- documents: model.documents,
172
- model,
173
- taskCounts: taskCounts(model, visibleGaps),
174
- visibleGaps,
175
- latestRun: latestRunState ? summarizeRunState(latestRunState) : null,
176
- latestRunState,
177
- latestRunsByTask,
178
- latestEligibleRunsByTask,
179
- affectedFileConflicts,
180
- dependencyBlockers,
181
- openRepairs,
182
- blockingReasons,
183
- workflowReadiness: readiness,
184
- whyNotShip: readiness.whyNotShip,
185
- nextIntent: recommendedWorkflowNextIntent(context, model, latestRunsByTask, visibleGaps, dependencyBlockers, runtimeByTask, readiness, openRepairs, truthReconciliation),
186
- truthReconciliation,
187
- recommendedNextCommand: ''
188
- };
189
- resolution.recommendedNextCommand = resolution.nextIntent.canonicalCommand;
190
- try {
191
- await recordRuntimeProjection(projectRoot, 'workflow_state', branch, projectWorkflowStateProjection(resolution));
192
- await recordWorkflowRuntimeProjections(projectRoot, resolution);
193
- } catch {
194
- // Projection writes are rebuildable and must not block workflow resolution.
195
- }
196
- return resolution;
197
- }
198
-
199
- function workflowIsActive(model: SddTaskModel): boolean {
200
- return model.documents.specExists || model.documents.planExists || model.documents.tasksExists;
201
- }
202
-
203
- function taskCounts(model: SddTaskModel, gaps: SddTaskGap[]): WorkflowTaskCounts {
204
- return {
205
- total: model.tasks.length,
206
- pending: model.tasks.filter((task) => task.status === 'pending').length,
207
- inProgress: model.tasks.filter((task) => task.status === 'in_progress').length,
208
- completed: model.tasks.filter((task) => task.status === 'completed').length,
209
- blocked: model.tasks.filter((task) => task.status === 'blocked').length,
210
- deferred: model.tasks.filter((task) => task.status === 'deferred').length,
211
- unknown: model.tasks.filter((task) => task.status === 'unknown').length,
212
- gaps: gaps.length
213
- };
214
- }
215
-
216
- function selectedLatestTaskRuns(selections: LatestEligibleRunSelection[]): WorkflowLatestTaskRun[] {
217
- return selections
218
- .flatMap((selection) => selection.selected ? [selection.selected] : [])
219
- .map((candidate) => ({
220
- partition: candidate.partition,
221
- gitBranch: candidate.gitBranch,
222
- taskId: candidate.taskId,
223
- runId: candidate.runId,
224
- runStatus: candidate.runStatus,
225
- validationStatus: candidate.validationStatus,
226
- affectedFiles: candidate.affectedFiles,
227
- updatedAt: candidate.updatedAt,
228
- compatibility: candidate.compatibility,
229
- eligibleForDefaultApply: candidate.eligibleForDefaultApply,
230
- reasons: candidate.reasons
231
- }))
232
- .sort((left, right) => left.taskId.localeCompare(right.taskId));
233
- }
234
-
235
-
236
- function blockingWorkflowReasons(gaps: SddTaskGap[], conflicts: WorkflowAffectedFileConflict[], dependencyBlockers: WorkflowDependencyBlocker[]): string[] {
237
- const reasons = gaps.filter((gap) => gap.severity === 'blocking').map((gap) => `${gap.field}: ${gap.message}`);
238
- for (const conflict of conflicts) {
239
- reasons.push(`Affected file ${conflict.file} is active in run ${conflict.runId} for ${conflict.partition}/${conflict.taskId}.`);
240
- }
241
- for (const blocker of dependencyBlockers) {
242
- reasons.push(blocker.reason);
243
- }
244
- return reasons;
245
- }
246
-
247
- async function resolveTruthReconciliationDecision(projectRoot: string, branch: string, truthAlignment: TruthAlignmentProjection | null, generatedAt: string, progress: { states: RunState[]; model: SddTaskModel }): Promise<TruthReconciliationDecision | null> {
248
- if (!truthAlignment) {
249
- return null;
250
- }
251
- const freshness = await refreshAlignedTruthAlignmentFreshness(projectRoot, branch, truthAlignment);
252
- if (freshness.truthAlignment.status === 'aligned') {
253
- return null;
254
- }
255
- const changeKind = truthDriftClassForAlignment(freshness.truthAlignment);
256
- const ownerStage = truthReconciliationOwnerStage(changeKind, freshness.truthAlignment.ownerStage);
257
- const minimalFrontier = minimalReworkFrontier({ ownerStage, semanticImpact: freshness.truthAlignment.semanticImpact, invalidatesStages: freshness.truthAlignment.invalidatesStages });
258
- const targetStage = await activeTruthReconciliationStage(projectRoot, minimalFrontier, freshness.truthAlignment, progress);
259
- const nextIntent = truthReconciliationNextIntent(branch, targetStage, freshness.truthAlignment.reasons);
260
- const decision = buildTruthReconciliationDecision({
261
- truthAlignment: freshness.truthAlignment,
262
- nextIntent,
263
- changeKind,
264
- changedRef: freshness.changedRef,
265
- oldHash: freshness.oldHash,
266
- newHash: freshness.newHash
267
- });
268
- await recordTruthReconciliationDecision(projectRoot, decision, generatedAt);
269
- return decision;
270
- }
271
-
272
- interface TruthAlignmentFreshness {
273
- truthAlignment: TruthAlignmentProjection;
274
- changedRef?: RuntimeRef;
275
- oldHash?: string;
276
- newHash?: string;
277
- }
278
-
279
- async function refreshAlignedTruthAlignmentFreshness(projectRoot: string, branch: string, truthAlignment: TruthAlignmentProjection): Promise<TruthAlignmentFreshness> {
280
- if (truthAlignment.status !== 'aligned') {
281
- return { truthAlignment };
282
- }
283
- const staleRefs: Array<{ ref: RuntimeRef; currentHash: string }> = [];
284
- for (const ref of [...truthAlignment.declaredTruthRefs, ...truthAlignment.acceptedRealityRefs]) {
285
- if (!ref.hash || ref.kind === 'projection' || ref.kind === 'run') {
286
- continue;
287
- }
288
- const currentHash = await currentTruthRefHash(projectRoot, ref);
289
- if (currentHash !== ref.hash) {
290
- staleRefs.push({ ref, currentHash });
291
- }
292
- }
293
- const unresolvedStaleRefs = await unresolvedStaleTruthRefs(projectRoot, branch, truthAlignment, staleRefs);
294
- const firstStaleRef = unresolvedStaleRefs[0];
295
- if (!firstStaleRef) {
296
- return { truthAlignment };
297
- }
298
- const ownerStage = ownerStageForTruthRef(branch, firstStaleRef.ref) ?? truthAlignment.ownerStage ?? 'ship';
299
- const semanticImpact = semanticImpactForTruthRef(branch, firstStaleRef.ref);
300
- const reasons = [
301
- ...truthAlignment.reasons,
302
- ...unresolvedStaleRefs.map((entry) => `TruthAlignment ref hash is stale for ${entry.ref.ref}: expected ${entry.ref.hash ?? 'unknown'}, actual ${entry.currentHash}.`)
303
- ];
304
- return {
305
- truthAlignment: {
306
- ...truthAlignment,
307
- status: 'update_required',
308
- ownerStage,
309
- semanticImpact,
310
- staleRefs: uniqueRuntimeRefs([...truthAlignment.staleRefs, ...unresolvedStaleRefs.map((entry) => entry.ref)]),
311
- invalidatesStages: uniqueStages([...truthAlignment.invalidatesStages, ownerStage]),
312
- reasons: uniqueStrings(reasons)
313
- },
314
- changedRef: firstStaleRef.ref,
315
- oldHash: firstStaleRef.ref.hash,
316
- newHash: firstStaleRef.currentHash
317
- };
318
- }
319
-
320
- async function unresolvedStaleTruthRefs(projectRoot: string, branch: string, truthAlignment: TruthAlignmentProjection, staleRefs: Array<{ ref: RuntimeRef; currentHash: string }>): Promise<Array<{ ref: RuntimeRef; currentHash: string }>> {
321
- const unresolved: Array<{ ref: RuntimeRef; currentHash: string }> = [];
322
- for (const entry of staleRefs) {
323
- if (!await staleTruthRefReconciledAfterAlignment(projectRoot, branch, truthAlignment, entry)) {
324
- unresolved.push(entry);
325
- }
326
- }
327
- return unresolved;
328
- }
329
-
330
- async function staleTruthRefReconciledAfterAlignment(projectRoot: string, branch: string, truthAlignment: TruthAlignmentProjection, entry: { ref: RuntimeRef; currentHash: string }): Promise<boolean> {
331
- const stage = ownerStageForTruthRef(branch, entry.ref);
332
- return stage ? await stageCloseAcceptedTruthRefAfterTruthAlignment(projectRoot, truthAlignment, stage, entry.ref, entry.currentHash) : false;
333
- }
334
-
335
- async function activeTruthReconciliationStage(projectRoot: string, frontier: SddStage[], truthAlignment: TruthAlignmentProjection, progress: { states: RunState[]; model: SddTaskModel }): Promise<SddStage> {
336
- for (const stage of frontier) {
337
- if (!await truthReconciliationStageCompleted(projectRoot, stage, truthAlignment, progress)) {
338
- return stage;
339
- }
340
- }
341
- return frontier[frontier.length - 1] ?? truthAlignment.ownerStage ?? 'ship';
342
- }
343
-
344
- async function truthReconciliationStageCompleted(projectRoot: string, stage: SddStage, truthAlignment: TruthAlignmentProjection, progress: { states: RunState[]; model: SddTaskModel }): Promise<boolean> {
345
- if (await stageCloseCompletedAfterTruthAlignment(projectRoot, truthAlignment, stage)) {
346
- return true;
347
- }
348
- const taskIds = reconciliationTaskIds(truthAlignment, progress);
349
- if (stage === 'do') {
350
- return taskIds.every((taskId) => progress.states.some((state) => stateAfterTruthAlignment(state, truthAlignment) && stateTaskImplemented(state.tasks[taskId])));
351
- }
352
- if (stage === 'test') {
353
- return taskIds.every((taskId) => progress.states.some((state) => stateAfterTruthAlignment(state, truthAlignment) && stateTaskValidationPassed(state.tasks[taskId], state)));
354
- }
355
- if (stage === 'goal-verify') {
356
- return truthAlignment.status === 'aligned';
357
- }
358
- return false;
359
- }
360
-
361
- function reconciliationTaskIds(truthAlignment: TruthAlignmentProjection, progress: { states: RunState[]; model: SddTaskModel }): string[] {
362
- const requiredIds = requiredTaskIds(progress.model);
363
- const requiredIdSet = new Set(requiredIds);
364
- const targetRefs = new Set([...truthAlignment.staleRefs, ...truthAlignment.acceptedRealityRefs].map((ref) => normalizePortablePath(ref.ref)).filter(Boolean));
365
- const taskIds = new Set<string>();
366
- for (const state of progress.states) {
367
- if (state.partition && state.partition !== truthAlignment.branch) {
368
- continue;
369
- }
370
- if (!stateReferencesAnyRef(state, targetRefs)) {
371
- continue;
372
- }
373
- for (const taskId of stateTaskIds(state)) {
374
- if (requiredIdSet.has(taskId)) {
375
- taskIds.add(taskId);
376
- }
377
- }
378
- }
379
- const scopedTaskIds = [...taskIds].sort();
380
- return scopedTaskIds.length > 0 ? scopedTaskIds : requiredIds;
381
- }
382
-
383
- function stateReferencesAnyRef(state: RunState, targetRefs: Set<string>): boolean {
384
- if (targetRefs.size === 0) {
385
- return false;
386
- }
387
- const refs = [
388
- ...state.artifacts.map((artifact) => artifact.path),
389
- ...Object.values(state.tasks).flatMap((runtime) => [...(runtime.artifacts ?? []), ...(runtime.evidence ?? [])])
390
- ];
391
- return refs.some((ref) => refMatchesTarget(ref, targetRefs));
392
- }
393
-
394
- function refMatchesTarget(ref: string, targetRefs: Set<string>): boolean {
395
- const normalized = normalizePortablePath(ref);
396
- return Boolean(normalized && [...targetRefs].some((target) => normalized === target || normalized.endsWith(`/${target}`) || target.endsWith(`/${normalized}`)));
397
- }
398
-
399
- function stateTaskIds(state: RunState): string[] {
400
- return [...new Set([state.taskId, state.currentTask, ...Object.keys(state.tasks)].filter((taskId): taskId is string => typeof taskId === 'string' && taskId.length > 0))];
401
- }
402
-
403
- async function stageCloseCompletedAfterTruthAlignment(projectRoot: string, truthAlignment: TruthAlignmentProjection, stage: SddStage): Promise<boolean> {
404
- const projectionType = stageAdjudicationProjectionType(stage);
405
- if (!projectionType) {
406
- return false;
407
- }
408
- const projections = await listRuntimeProjections(projectRoot, [projectionType]);
409
- return projections
410
- .map((projection) => projection.payload as RuntimeProjectionEnvelope<StageCloseAdjudicationProjection>)
411
- .some((envelope) => stageAdjudicationCompletedAfterTruthAlignment(envelope, truthAlignment, stage));
412
- }
413
-
414
- interface StageCloseAdjudicationProjection {
415
- stage?: SddStage;
416
- scope?: { branch?: string };
417
- health?: string | null;
418
- stageDecision?: { status?: string | null; health?: string | null; acceptedDecisionRefs?: RuntimeRef[] };
419
- closureRefs?: Record<string, unknown>;
420
- }
421
-
422
- function stageAdjudicationProjectionType(stage: SddStage): string | null {
423
- const projectionTypes: Record<SddStage, string> = {
424
- spec: SPEC_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
425
- plan: PLAN_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
426
- tasks: TASKS_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
427
- verifies: VERIFIES_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
428
- do: DO_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
429
- test: TEST_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
430
- 'goal-verify': GOAL_VERIFY_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
431
- ship: SHIP_COLLABORATION_ADJUDICATION_PROJECTION_TYPE
432
- };
433
- return projectionTypes[stage] ?? null;
434
- }
435
-
436
- async function stageCloseAcceptedTruthRefAfterTruthAlignment(projectRoot: string, truthAlignment: TruthAlignmentProjection, stage: SddStage, staleRef: RuntimeRef, currentHash: string): Promise<boolean> {
437
- const projectionType = stageAdjudicationProjectionType(stage);
438
- if (!projectionType) {
439
- return false;
440
- }
441
- const projections = await listRuntimeProjections(projectRoot, [projectionType]);
442
- return projections
443
- .map((projection) => projection.payload as RuntimeProjectionEnvelope<StageCloseAdjudicationProjection>)
444
- .some((envelope) => stageAdjudicationCompletedAfterTruthAlignment(envelope, truthAlignment, stage)
445
- && acceptedStageRefs(envelope.payload).some((acceptedRef) => acceptedTruthRefMatchesCurrent(acceptedRef, staleRef, currentHash)));
446
- }
447
-
448
- function acceptedTruthRefMatchesCurrent(acceptedRef: RuntimeRef, staleRef: RuntimeRef, currentHash: string): boolean {
449
- return acceptedRef.kind === staleRef.kind
450
- && normalizePortablePath(acceptedRef.ref) === normalizePortablePath(staleRef.ref)
451
- && acceptedRef.hash === currentHash;
452
- }
453
-
454
- function stageAdjudicationCompletedAfterTruthAlignment(envelope: RuntimeProjectionEnvelope<StageCloseAdjudicationProjection>, truthAlignment: TruthAlignmentProjection, stage: SddStage): boolean {
455
- const expectedHealth = expectedStageCloseHealth(stage);
456
- return envelope.payload?.scope?.branch === truthAlignment.branch
457
- && envelope.payload.stage === stage
458
- && Date.parse(envelope.generatedAt) > Date.parse(truthAlignment.createdAt)
459
- && envelope.payload.stageDecision?.status === 'completed'
460
- && (envelope.payload.health === expectedHealth || envelope.payload.stageDecision?.health === expectedHealth)
461
- && acceptedStageRefs(envelope.payload).some((ref) => ownerStageForTruthRef(truthAlignment.branch, ref) === stage);
462
- }
463
-
464
- function expectedStageCloseHealth(stage: SddStage): string {
465
- const expectedHealth: Record<SddStage, string> = {
466
- spec: 'ready_for_plan',
467
- plan: 'ready_for_tasks',
468
- tasks: 'ready_for_verifies',
469
- verifies: 'ready_for_do',
470
- do: 'ready_for_test',
471
- test: 'ready_for_goal_verify',
472
- 'goal-verify': 'ready_for_ship',
473
- ship: 'ship_ready'
474
- };
475
- return expectedHealth[stage];
476
- }
477
-
478
- function acceptedStageRefs(adjudication: StageCloseAdjudicationProjection): RuntimeRef[] {
479
- const refs = Array.isArray(adjudication.stageDecision?.acceptedDecisionRefs) ? adjudication.stageDecision.acceptedDecisionRefs : [];
480
- const closureRefs = adjudication.closureRefs ?? {};
481
- const closureRefKeys = [
482
- 'acceptedSpecRef',
483
- 'acceptedPlanRef',
484
- 'acceptedTasksRef',
485
- 'acceptedVerifyRef',
486
- 'acceptedImplementationRef',
487
- 'acceptedTestEvidenceRef',
488
- 'acceptedGoalVerificationRef',
489
- 'acceptedShipReadinessRef'
490
- ];
491
- return [
492
- ...refs,
493
- ...closureRefKeys.map((key) => runtimeRefFromUnknown(closureRefs[key]))
494
- ].filter((ref): ref is RuntimeRef => ref !== null);
495
- }
496
-
497
- function runtimeRefFromUnknown(value: unknown): RuntimeRef | null {
498
- if (!value || typeof value !== 'object') {
499
- return null;
500
- }
501
- const candidate = value as Partial<RuntimeRef>;
502
- if (typeof candidate.kind !== 'string' || typeof candidate.ref !== 'string') {
503
- return null;
504
- }
505
- return {
506
- kind: candidate.kind as RuntimeRef['kind'],
507
- ref: candidate.ref,
508
- hash: typeof candidate.hash === 'string' ? candidate.hash : undefined
509
- };
510
- }
511
-
512
- function requiredTaskIds(model: SddTaskModel): string[] {
513
- return model.tasks.filter((task) => task.status !== 'deferred').map((task) => task.id);
514
- }
515
-
516
- function stateAfterTruthAlignment(state: RunState, truthAlignment: TruthAlignmentProjection): boolean {
517
- return Date.parse(state.updatedAt) > Date.parse(truthAlignment.createdAt);
518
- }
519
-
520
- function stateTaskImplemented(runtime: RunStateTaskRuntime | undefined): boolean {
521
- return runtimeTaskImplemented(runtime);
522
- }
523
-
524
- function stateTaskValidationPassed(runtime: RunStateTaskRuntime | undefined, state: RunState): boolean {
525
- return runtime?.verificationStatus === 'pass' || runtime?.status === 'implemented_verified' || state.validation.status === 'pass';
526
- }
527
-
528
- async function currentTruthRefHash(projectRoot: string, ref: RuntimeRef): Promise<string> {
529
- const normalized = normalizePortablePath(ref.ref);
530
- if (!normalized || normalized === '.' || normalized === '..' || normalized.includes('..') || path.isAbsolute(ref.ref)) {
531
- return 'unsafe-ref';
532
- }
533
- const projectPath = path.resolve(projectRoot);
534
- const filePath = path.resolve(projectPath, normalized);
535
- if (!filePath.startsWith(`${projectPath}${path.sep}`)) {
536
- return 'escaped-ref';
537
- }
538
- try {
539
- return hashDocumentContent(await readFile(filePath, 'utf8'));
540
- } catch {
541
- return 'missing-ref';
542
- }
543
- }
544
-
545
- function ownerStageForTruthRef(branch: string, ref: RuntimeRef): SddStage | null {
546
- const normalized = normalizePortablePath(ref.ref);
547
- if (!normalized) {
548
- return null;
549
- }
550
- if (normalized === `specs/${branch}/spec.md`) {
551
- return 'spec';
552
- }
553
- if (normalized === `specs/${branch}/plan.md`) {
554
- return 'plan';
555
- }
556
- if (normalized === `specs/${branch}/tasks.md`) {
557
- return 'tasks';
558
- }
559
- if (normalized === `specs/${branch}/verify.md`) {
560
- return 'verifies';
561
- }
562
- if (normalized === `specs/${branch}/release.md`) {
563
- return 'ship';
564
- }
565
- const runStage = normalized.match(new RegExp(`^\\.sdd/runs/${escapeRegExp(branch)}/([^/]+)/`))?.[1];
566
- return runStage && isSddStage(runStage) ? runStage : null;
567
- }
568
-
569
- function semanticImpactForTruthRef(branch: string, ref: RuntimeRef): TruthAlignmentProjection['semanticImpact'] {
570
- const ownerStage = ownerStageForTruthRef(branch, ref);
571
- return ref.kind === 'document' || ownerStage === 'spec' || ownerStage === 'plan' || ownerStage === 'tasks' || ownerStage === 'verifies' ? 'none' : 'material';
572
- }
573
-
574
- function uniqueRuntimeRefs(refs: RuntimeRef[]): RuntimeRef[] {
575
- const seen = new Set<string>();
576
- const result: RuntimeRef[] = [];
577
- for (const ref of refs) {
578
- const key = `${ref.kind}:${ref.ref}:${ref.hash ?? ''}`;
579
- if (!seen.has(key)) {
580
- seen.add(key);
581
- result.push(ref);
582
- }
583
- }
584
- return result;
585
- }
586
-
587
- function uniqueStages(stages: SddStage[]): SddStage[] {
588
- return ['spec', 'plan', 'tasks', 'verifies', 'do', 'test', 'goal-verify', 'ship'].filter((stage): stage is SddStage => stages.includes(stage as SddStage));
589
- }
590
-
591
- function uniqueStrings(values: string[]): string[] {
592
- return [...new Set(values)];
593
- }
594
-
595
- function escapeRegExp(value: string): string {
596
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
597
- }
598
-
599
- function truthReconciliationNextIntent(branch: string, ownerStage: SddStage, reasons: string[]): WorkflowNextIntent {
600
- const bundle = commandBundleForRuntimeStage(ownerStage);
601
- return workflowNextIntent(bundle, 'reconcile_truth', truthReconciliationCommand(branch, ownerStage), `Reconcile truth drift in ${ownerStage}-manager before downstream ship readiness.`, reasons.join('; ') || 'truthAlignment requires reconciliation', {
602
- targetRuntimeStage: ownerStage,
603
- resumeMode: 'reconcile',
604
- canAutoAdvanceWithinBundle: ownerStage === 'verifies' || ownerStage === 'goal-verify',
605
- evidenceSurface: [...evidenceSurfaceForRuntimeStage(ownerStage), 'truthReconciliation projection']
606
- });
607
- }
608
-
609
- function truthReconciliationCommand(branch: string, ownerStage: SddStage): string {
610
- if (ownerStage === 'do') {
611
- return `sdd do task <task_id> --branch ${branch}`;
612
- }
613
- return stageCloseCommandForRuntimeStage(branch, ownerStage);
614
- }
615
-
616
- function stageCloseCommandForRuntimeStage(branch: string, stage: SddStage): string {
617
- if (stage === 'verifies') {
618
- return `sdd tasks close --branch ${branch} --target verifies --compact-json`;
619
- }
620
- if (stage === 'goal-verify') {
621
- return `sdd test close --branch ${branch} --target goal-verify --compact-json`;
622
- }
623
- return `sdd ${stage} close --branch ${branch} --compact-json`;
624
- }
625
-
626
- function formatOpenRepairReason(repair: RuntimeRepairRecord): string {
627
- return `Open ${repair.repairType} ${repair.repairId}: ${repair.blockers.join('; ')}`;
628
- }
629
-
630
- function recommendedWorkflowNextIntent(
631
- context: ContextResolverContract,
632
- model: SddTaskModel,
633
- latestRunsByTask: WorkflowLatestTaskRun[],
634
- gaps: SddTaskGap[],
635
- dependencyBlockers: WorkflowDependencyBlocker[],
636
- runtimeByTask: Map<string, RunStateTaskRuntime>,
637
- readiness: WorkflowReadinessSummary,
638
- openRepairs: RuntimeRepairRecord[],
639
- truthReconciliation: TruthReconciliationDecision | null
640
- ): WorkflowNextIntent {
641
- if (!workflowIsActive(model)) {
642
- return workflowNextIntent('spec', 'start_spec', `sdd spec --branch ${context.partition}`, 'Start the spec stage before planning or task execution.', null);
643
- }
644
- const blockingGap = gaps.find((gap) => gap.severity === 'blocking');
645
- if (blockingGap) {
646
- return workflowNextIntent('tasks', 'resolve_task_gaps', `sdd tasks gaps --branch ${context.partition}`, 'Resolve blocking task document gaps before execution evidence can be trusted.', `${blockingGap.field}: ${blockingGap.message}`);
647
- }
648
- const openRepair = openRepairs[0];
649
- if (openRepair) {
650
- return workflowNextIntent('test', 'repair_failure', openRepair.recommendedCommands[0] ?? `sdd doctor --branch ${context.partition} --latest-only`, openRepair.requiredEvidence.join('; ') || 'Resolve the open repair with new accepted evidence or a fresh gate PASS.', formatOpenRepairReason(openRepair));
651
- }
652
-
653
- if (truthReconciliation) {
654
- return truthReconciliation.nextIntent;
655
- }
656
-
657
- const strictTask = model.tasks.find((task) => needsTaskValidation(task, runtimeByTask.get(task.id)));
658
- if (strictTask) {
659
- return workflowNextIntent('test', 'run_task_validation', validationUnitCommand(context.partition, validationUnitIdForTask(strictTask)), 'Validate this verify.md validation unit before more implementation proceeds.', null);
660
- }
661
-
662
- const readyBoundary = readyValidationBoundary(model, runtimeByTask);
663
- if (readyBoundary?.kind === 'batch') {
664
- return workflowNextIntent('test', 'run_batch_validation', validationUnitCommand(context.partition, readyBoundary.id), `Validate accumulated implementation evidence for validation unit ${readyBoundary.id}.`, null);
665
- }
666
- if (readyBoundary?.kind === 'wave') {
667
- return workflowNextIntent('test', 'run_wave_validation', validationUnitCommand(context.partition, readyBoundary.id), `Validate accumulated implementation evidence for validation unit ${readyBoundary.id}.`, null);
668
- }
669
-
670
- if (readiness.readyForShip) {
671
- if (goalVerificationPassedForShip(model, runtimeByTask)) {
672
- return workflowNextIntent('ship', 'ship_readiness', `sdd ship close --branch ${context.partition} --compact-json`, 'Goal verification passed; close ship readiness with ship-stage evidence.', null);
673
- }
674
- return workflowNextIntent('test', 'run_goal_verify', stageCloseCommandForRuntimeStage(context.partition, 'goal-verify'), 'Close goal verification inside the /sdd:test bundle and compute truthAlignment before ship readiness can run.', null, {
675
- targetRuntimeStage: 'goal-verify',
676
- resumeMode: 'resume',
677
- canAutoAdvanceWithinBundle: true,
678
- evidenceSurface: ['.sdd/runs/<branch>/goal-verify/*.md', 'truthAlignment projection']
679
- });
680
- }
681
-
682
- const nextTask = model.tasks.find((task) => task.status === 'pending' && !runtimeTaskImplemented(runtimeByTask.get(task.id)) && dependencyBlockingReasonsForTask(model, task.id, { runtimeByTask }).length === 0);
683
- if (nextTask) {
684
- return workflowNextIntent('do', 'continue_do', `sdd do task ${nextTask.id} --branch ${context.partition}`, 'Continue sequential implementation; validation can wait until the declared task or batch boundary.', null);
685
- }
686
-
687
- const dependencyBlocker = dependencyBlockers[0];
688
- if (dependencyBlocker) {
689
- return workflowNextIntent('tasks', 'inspect_dependency', `sdd tasks inspect ${dependencyBlocker.dependencyId} --branch ${context.partition}`, 'Inspect the dependency task before continuing this workflow.', dependencyBlocker.reason);
690
- }
691
-
692
- const pendingTask = model.tasks.find((task) => task.status === 'pending');
693
- return pendingTask
694
- ? workflowNextIntent('tasks', 'inspect_task', `sdd tasks inspect ${pendingTask.id} --branch ${context.partition}`, 'Inspect task boundary, acceptance, validation, and capability needs before do/test.', null)
695
- : workflowNextIntent('tasks', 'list_tasks', `sdd tasks list --branch ${context.partition}`, 'Inspect task state and decide whether to continue or ship.', null);
696
- }
697
-
698
- export function latestRuntimeTaskStates(selections: LatestEligibleRunSelection[], states: RunState[]): Map<string, RunStateTaskRuntime> {
699
- const stateByRunId = new Map(states.map((state) => [state.runId, state]));
700
- const result = new Map<string, RunStateTaskRuntime>();
701
- for (const selection of selections) {
702
- const selected = selection.selected;
703
- if (!selected) {
704
- continue;
705
- }
706
- const taskState = stateByRunId.get(selected.runId)?.tasks[selected.taskId];
707
- if (taskState) {
708
- result.set(selected.taskId, taskState);
709
- }
710
- }
711
- return result;
712
- }
713
-
714
- function needsTaskValidation(task: SddTask, runtime: RunStateTaskRuntime | undefined): boolean {
715
- return Boolean(runtimeTaskImplemented(runtime) && runtime?.verificationStatus !== 'pass' && (task.requiresVerifyBeforeNext || task.validationTiming === 'task_end'));
716
- }
717
-
718
- function validationUnitIdForTask(task: SddTask): string {
719
- return task.validationBatch ?? `task-${task.id}`;
720
- }
721
-
722
-
723
- function readyValidationBoundary(model: SddTaskModel, runtimeByTask: Map<string, RunStateTaskRuntime>): { kind: 'batch'; id: string } | { kind: 'wave'; id: string } | null {
724
- const batchGroups = new Map<string, SddTask[]>();
725
- const waveGroups = new Map<string, SddTask[]>();
726
- for (const task of model.tasks) {
727
- if (task.validationTiming === 'batch_end' && task.validationBatch) {
728
- batchGroups.set(task.validationBatch, [...(batchGroups.get(task.validationBatch) ?? []), task]);
729
- }
730
- if (task.validationTiming === 'wave_end') {
731
- const id = validationUnitIdForTask(task);
732
- waveGroups.set(id, [...(waveGroups.get(id) ?? []), task]);
733
- }
734
- }
735
- for (const [id, tasks] of batchGroups) {
736
- if (validationBoundaryReady(tasks, runtimeByTask)) {
737
- return { kind: 'batch', id };
738
- }
739
- }
740
- for (const [id, tasks] of waveGroups) {
741
- if (validationBoundaryReady(tasks, runtimeByTask)) {
742
- return { kind: 'wave', id };
743
- }
744
- }
745
- return null;
746
- }
747
-
748
- function validationBoundaryReady(tasks: SddTask[], runtimeByTask: Map<string, RunStateTaskRuntime>): boolean {
749
- return tasks.every((task) => runtimeTaskImplemented(runtimeByTask.get(task.id)))
750
- && tasks.some((task) => runtimeByTask.get(task.id)?.verificationStatus !== 'pass');
751
- }
752
-
753
- function runtimeTaskImplemented(runtime: RunStateTaskRuntime | undefined): boolean {
754
- return runtime?.implementationStatus === 'implemented' || runtime?.status === 'implemented_pending_validation' || runtime?.status === 'implemented_verified';
755
- }
756
-
757
- function latestEligibleRunReadyForShip(run: WorkflowLatestTaskRun): boolean {
758
- return run.runStatus === 'completed' && run.validationStatus === 'pass';
759
- }
760
-
761
- function goalVerificationPassedForShip(model: SddTaskModel, runtimeByTask: Map<string, RunStateTaskRuntime>): boolean {
762
- const requiredTasks = model.tasks.filter((task) => task.status !== 'deferred');
763
- return requiredTasks.length > 0 && requiredTasks.every((task) => {
764
- const runtime = runtimeByTask.get(task.id);
765
- return runtime?.verifyStatus === 'PASS' || runtime?.status === 'implemented_verified';
766
- });
767
- }
768
-
769
- function workflowReadinessSummary(model: SddTaskModel, latestRunsByTask: WorkflowLatestTaskRun[]): WorkflowReadinessSummary {
770
- const requiredTaskIds = model.tasks.filter((task) => task.status !== 'deferred').map((task) => task.id).sort();
771
- const acceptedTaskIds = requiredTaskIds.filter((taskId) => latestRunsByTask.some((run) => run.taskId === taskId && latestEligibleRunReadyForShip(run))).sort();
772
- const missingTaskIds = requiredTaskIds.filter((taskId) => !acceptedTaskIds.includes(taskId));
773
- return {
774
- requiredTaskIds,
775
- acceptedTaskIds,
776
- missingTaskIds,
777
- readyForShip: requiredTaskIds.length > 0 && missingTaskIds.length === 0,
778
- whyNotShip: missingTaskIds.length === 0 ? [] : missingTaskIds.map((taskId) => `Task ${taskId} has no accepted validation PASS evidence.`)
779
- };
780
- }
781
-
782
- function validationUnitCommand(branch: string, validationUnitId: string): string {
783
- return `sdd test ${validationUnitId} --branch ${branch}`;
784
- }
785
-
786
-
787
- export interface WorkflowNextIntentOptions {
788
- targetRuntimeStage?: SddStage;
789
- resumeMode?: BundleResumeMode;
790
- displayCommand?: string;
791
- canAutoAdvanceWithinBundle?: boolean;
792
- autoAdvanceTo?: SddStage | null;
793
- stopReasons?: string[];
794
- evidenceSurface?: string[];
795
- }
796
-
797
- export function workflowNextIntent(
798
- stage: WorkflowNextStage,
799
- intent: WorkflowNextIntentKind,
800
- canonicalCommand: string,
801
- evidenceRequirement: string,
802
- blockingReason: string | null,
803
- options: WorkflowNextIntentOptions = {}
804
- ): WorkflowNextIntent {
805
- const targetRuntimeStage = options.targetRuntimeStage ?? runtimeStageForCommand(canonicalCommand, stage);
806
- const bundle = commandBundleForRuntimeStage(targetRuntimeStage);
807
- const stages = [...COMMAND_BUNDLES[bundle]];
808
- const autoAdvanceTo = options.autoAdvanceTo ?? null;
809
- const canAutoAdvanceWithinBundle = options.canAutoAdvanceWithinBundle ?? Boolean(autoAdvanceTo && stages.includes(autoAdvanceTo));
810
- const displayCommand = options.displayCommand ?? commandBundleDisplayCommand(bundle, targetRuntimeStage, canonicalCommand);
811
- const stopReasons = options.stopReasons ?? [];
812
- const evidenceSurface = options.evidenceSurface ?? evidenceSurfaceForRuntimeStage(targetRuntimeStage);
813
- const resumeMode = options.resumeMode ?? defaultResumeMode(intent, targetRuntimeStage);
814
- const commandBundle: CommandBundlePlan = {
815
- contract: 'sdd-command-bundle-plan-v1',
816
- branch: branchFromCommand(canonicalCommand),
817
- bundle,
818
- stages,
819
- targetRuntimeStage,
820
- resumeMode,
821
- canonicalCommand,
822
- displayCommand,
823
- canAutoAdvanceWithinBundle,
824
- autoAdvanceTo,
825
- stopReasons,
826
- evidenceSurface
827
- };
828
- return {
829
- stage: bundle,
830
- bundle,
831
- targetRuntimeStage,
832
- resumeMode,
833
- intent,
834
- canonicalCommand,
835
- displayCommand,
836
- commandSemantics: commandSemanticsForTarget(bundle, targetRuntimeStage, canonicalCommand),
837
- evidenceRequirement,
838
- blockingReason,
839
- canAutoAdvanceWithinBundle,
840
- autoAdvanceTo,
841
- stopReasons,
842
- evidenceSurface,
843
- commandBundle,
844
- hostProjections: hostCommandProjections(commandBundle)
845
- };
846
- }
847
-
848
- export function commandBundleForRuntimeStage(stage: SddStage): SddCommandBundle {
849
- if (stage === 'verifies') {
850
- return 'tasks';
851
- }
852
- if (stage === 'goal-verify') {
853
- return 'test';
854
- }
855
- return stage;
856
- }
857
-
858
- function runtimeStageForCommand(canonicalCommand: string, fallbackBundle: SddCommandBundle): SddStage {
859
- const command = canonicalCommand.replace(/^sdd\s+/, '').split(/\s+/)[0];
860
- return isSddStage(command) ? command : COMMAND_BUNDLES[fallbackBundle][0];
861
- }
862
-
863
- function isSddStage(value: string): value is SddStage {
864
- return value === 'spec' || value === 'plan' || value === 'tasks' || value === 'verifies' || value === 'do' || value === 'test' || value === 'goal-verify' || value === 'ship';
865
- }
866
-
867
- function defaultResumeMode(intent: WorkflowNextIntentKind, targetRuntimeStage: SddStage): BundleResumeMode {
868
- if (intent === 'repair_failure') {
869
- return 'repair';
870
- }
871
- if (intent === 'run_goal_verify' || targetRuntimeStage === 'verifies' || targetRuntimeStage === 'goal-verify') {
872
- return 'resume';
873
- }
874
- return 'start';
875
- }
876
-
877
- function commandSemanticsForTarget(bundle: SddCommandBundle, targetRuntimeStage: SddStage, canonicalCommand: string): WorkflowCommandSemantics {
878
- if (/^sdd\s+status\b/.test(canonicalCommand)) {
879
- return 'inspection_navigation';
880
- }
881
- return bundle === 'do' || bundle === 'test' || bundle === 'ship' || /\sclose\b/.test(canonicalCommand) || targetRuntimeStage === 'verifies' || targetRuntimeStage === 'goal-verify'
882
- ? 'gate_execution'
883
- : 'inspection_navigation';
884
- }
885
-
886
- function evidenceSurfaceForRuntimeStage(stage: SddStage): string[] {
887
- const surfaces: Partial<Record<SddStage, string[]>> = {
888
- spec: ['specs/<branch>/spec.md', '.sdd/runs/<branch>/spec/*.md'],
889
- plan: ['specs/<branch>/plan.md', '.sdd/runs/<branch>/plan/*.md'],
890
- tasks: ['specs/<branch>/tasks.md', '.sdd/runs/<branch>/tasks/*.md'],
891
- verifies: ['specs/<branch>/verify.md', '.sdd/runs/<branch>/verifies/*.md'],
892
- do: ['.sdd/runs/<branch>/do/*.md'],
893
- test: ['.sdd/runs/<branch>/test/*.md'],
894
- 'goal-verify': ['.sdd/runs/<branch>/goal-verify/*.md', 'truthAlignment projection'],
895
- ship: ['.sdd/runs/<branch>/ship/*.md', 'truthAlignment projection']
896
- };
897
- return surfaces[stage] ?? [`.sdd/runs/<branch>/${stage}/*.md`];
898
- }
899
-
900
- function branchFromCommand(canonicalCommand: string): string {
901
- const tokens = canonicalCommand.split(/\s+/);
902
- const branchIndex = tokens.indexOf('--branch');
903
- return branchIndex >= 0 ? tokens[branchIndex + 1] ?? '<branch>' : '<branch>';
904
- }
905
-
906
- function commandBundleDisplayCommand(bundle: SddCommandBundle, targetRuntimeStage: SddStage, canonicalCommand: string): string {
907
- return claudeCodeSlashEntry({ bundle, targetRuntimeStage, canonicalCommand });
908
- }
909
-
910
- function hostCommandProjections(commandBundle: CommandBundlePlan): WorkflowHostCommandProjection[] {
911
- return [
912
- {
913
- host: 'claude_code',
914
- status: 'active',
915
- entry: claudeCodeSlashEntry(commandBundle),
916
- projectionSurfaces: ['slash command', 'skill', 'settings/hooks/statusline metadata'],
917
- permissionProjection: 'Claude Code permission mode/tool prompts remain host enforcement, not SDD lifecycle truth.',
918
- reason: 'Claude Code supports slash/skill/statusline projections; the canonical CLI command remains the portable source of workflow intent.'
919
- },
920
- {
921
- host: 'codex',
922
- status: 'future',
923
- entry: null,
924
- projectionSurfaces: ['config.toml profile', 'AGENTS.md instruction surface', 'approval_policy', 'sandbox_mode'],
925
- permissionProjection: 'Codex approval and sandbox controls can project execution policy; custom command/skill projection is not marked active without stronger evidence.',
926
- reason: 'Codex exposes approval, sandbox, AGENTS.md, and built-in slash surfaces, but project custom workflow command semantics stay future until validated.'
927
- },
928
- {
929
- host: 'opencode',
930
- status: 'active',
931
- entry: opencodeCommandEntry(commandBundle),
932
- projectionSurfaces: ['opencode.json/jsonc', '.opencode/commands', '.opencode/agents', '.opencode/skills', 'permissions'],
933
- permissionProjection: 'OpenCode allow/ask/deny permissions can project SDD tool policy; SDD artifacts remain authoritative evidence.',
934
- reason: 'OpenCode documents project commands, agents, skills, and permissions suitable for host-specific projection.'
935
- }
936
- ];
937
- }
938
-
939
- function claudeCodeSlashEntry(commandBundle: Pick<CommandBundlePlan, 'bundle' | 'targetRuntimeStage' | 'canonicalCommand'>): string {
940
- return projectedCommandEntry('/sdd:', commandBundle, ':');
941
- }
942
-
943
- function opencodeCommandEntry(commandBundle: Pick<CommandBundlePlan, 'bundle' | 'targetRuntimeStage' | 'canonicalCommand'>): string {
944
- return projectedCommandEntry('/sdd ', commandBundle, ' ');
945
- }
946
-
947
- function projectedCommandEntry(prefix: string, commandBundle: Pick<CommandBundlePlan, 'bundle' | 'targetRuntimeStage' | 'canonicalCommand'>, separator: ':' | ' '): string {
948
- const tokens = commandBundle.canonicalCommand.replace(/^sdd\s+/, '').split(/\s+/).filter(Boolean);
949
- const [command, ...rest] = tokens;
950
- if (!command || !isSddStage(command)) {
951
- return `/sdd ${tokens.join(' ')}`;
952
- }
953
- const target = commandBundle.targetRuntimeStage === commandBundle.bundle ? '' : ` target=${commandBundle.targetRuntimeStage}`;
954
- const tailTokens = stripTargetOption(rest);
955
- const head = separator === ':' ? `${prefix}${commandBundle.bundle}` : `${prefix}${commandBundle.bundle}`;
956
- return `${head}${target}${tailTokens.length > 0 ? ` ${tailTokens.join(' ')}` : ''}`;
957
- }
958
-
959
- function stripTargetOption(tokens: string[]): string[] {
960
- const result: string[] = [];
961
- for (let index = 0; index < tokens.length; index += 1) {
962
- if (tokens[index] === '--target') {
963
- index += 1;
964
- continue;
965
- }
966
- result.push(tokens[index]);
967
- }
968
- return result;
969
- }
970
-
971
- function projectWorkflowStateProjection(resolution: WorkflowStateResolution): unknown {
972
- return {
973
- contract: resolution.contract,
974
- generatedAt: resolution.generatedAt,
975
- branch: resolution.branch,
976
- workflowStatus: resolution.workflowStatus,
977
- documents: resolution.documents,
978
- taskCounts: resolution.taskCounts,
979
- latestRun: resolution.latestRun,
980
- latestRunsByTask: resolution.latestRunsByTask,
981
- latestEligibleRunsByTask: resolution.latestEligibleRunsByTask,
982
- affectedFileConflicts: resolution.affectedFileConflicts,
983
- dependencyBlockers: resolution.dependencyBlockers,
984
- openRepairs: resolution.openRepairs,
985
- blockingReasons: resolution.blockingReasons,
986
- workflowReadiness: resolution.workflowReadiness,
987
- whyNotShip: resolution.whyNotShip,
988
- nextIntent: resolution.nextIntent,
989
- truthReconciliation: resolution.truthReconciliation,
990
- recommendedNextCommand: resolution.recommendedNextCommand
991
- };
992
- }
1
+ import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { WORKFLOW_STATE_RESOLVER_CONTRACT_VERSION, type RuntimeProjectionEnvelope, type RuntimeRef, type SddStage } from '../contracts.js';
4
+ import { listRuntimeProjections, listRuntimeRepairs, recordRuntimeProjection, type RuntimeRepairRecord } from '../storage/runtime-store.js';
5
+ import type { RunState, RunStateTaskRuntime, RunSummary } from '../run-state/model.js';
6
+ import { affectedFileConflictsForSelectedRun, type WorkflowAffectedFileConflict } from './affected-file-conflicts.js';
7
+ import { readAllRunStates, summarizeRunState } from '../run-state/run-state.js';
8
+ import { resolveSddContext, type ContextBranchSource, type ContextResolverContract } from '../sdd-docs/context.js';
9
+ import { parseSddBranch, type SddTask, type SddTaskGap, type SddTaskModel } from '../sdd-docs/task-parser.js';
10
+ import { dependencyBlockingReasonsForTask, workflowDependencyBlockers, type WorkflowDependencyBlocker } from './dependencies.js';
11
+ import { selectLatestEligibleRunsByTask, type DocumentCompatibilityClass, type LatestEligibleRunSelection } from './latest-eligible-run.js';
12
+ import {
13
+ EXECUTE_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
14
+ PLAN_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
15
+ readTruthAlignmentProjection,
16
+ SHIP_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
17
+ SPEC_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
18
+ TASKS_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
19
+ type TruthAlignmentProjection
20
+ } from '../stage-collaboration.js';
21
+ import { buildTruthReconciliationDecision, minimalReworkFrontier, recordTruthReconciliationDecision, truthDriftClassForAlignment, truthReconciliationOwnerStage, type TruthReconciliationDecision } from '../truth-reconciliation.js';
22
+ import { normalizePortablePath } from '../path-safety.js';
23
+ import { hashDocumentContent } from '../sdd-docs/document-hashes.js';
24
+ import { recordWorkflowRuntimeProjections } from './runtime-projections.js';
25
+
26
+ export interface WorkflowTaskCounts {
27
+ total: number;
28
+ pending: number;
29
+ inProgress: number;
30
+ completed: number;
31
+ blocked: number;
32
+ deferred: number;
33
+ unknown: number;
34
+ gaps: number;
35
+ }
36
+
37
+ export interface WorkflowLatestTaskRun {
38
+ partition: string;
39
+ gitBranch: string | null;
40
+ taskId: string;
41
+ runId: string;
42
+ runStatus: RunState['status'];
43
+ validationStatus: RunState['validation']['status'];
44
+ affectedFiles: string[];
45
+ updatedAt: string;
46
+ compatibility: DocumentCompatibilityClass;
47
+ eligibleForDefaultApply: boolean;
48
+ reasons: string[];
49
+ }
50
+
51
+ export type WorkflowCommandSemantics = 'inspection_navigation' | 'gate_execution';
52
+ export type WorkflowHostProjectionStatus = 'active' | 'future' | 'unsupported';
53
+ export type SddCommandBundle = 'spec' | 'plan' | 'tasks' | 'execute' | 'ship';
54
+ export type BundleResumeMode = 'start' | 'resume' | 'repair' | 'reconcile';
55
+ export type WorkflowNextStage = SddCommandBundle;
56
+ export type WorkflowNextIntentKind = 'start_spec' | 'resolve_task_gaps' | 'inspect_dependency' | 'workflow_complete' | 'ship_readiness' | 'inspect_task' | 'list_tasks' | 'continue_execute' | 'run_task_validation' | 'run_batch_validation' | 'run_wave_validation' | 'repair_failure' | 'reconcile_truth';
57
+
58
+ export const COMMAND_BUNDLES: Record<SddCommandBundle, readonly SddStage[]> = {
59
+ spec: ['spec'],
60
+ plan: ['plan'],
61
+ tasks: ['tasks'],
62
+ execute: ['execute'],
63
+ ship: ['ship']
64
+ };
65
+
66
+ export interface CommandBundlePlan {
67
+ contract: 'sdd-command-bundle-plan-v1';
68
+ branch: string;
69
+ bundle: SddCommandBundle;
70
+ stages: SddStage[];
71
+ targetRuntimeStage: SddStage;
72
+ resumeMode: BundleResumeMode;
73
+ canonicalCommand: string;
74
+ displayCommand: string;
75
+ canAutoAdvanceWithinBundle: boolean;
76
+ autoAdvanceTo: SddStage | null;
77
+ stopReasons: string[];
78
+ evidenceSurface: string[];
79
+ }
80
+
81
+ export interface WorkflowReadinessSummary {
82
+ requiredTaskIds: string[];
83
+ acceptedTaskIds: string[];
84
+ missingTaskIds: string[];
85
+ readyForShip: boolean;
86
+ whyNotShip: string[];
87
+ }
88
+
89
+ export interface WorkflowHostCommandProjection {
90
+ host: 'claude_code' | 'codex' | 'opencode';
91
+ status: WorkflowHostProjectionStatus;
92
+ entry: string | null;
93
+ projectionSurfaces: string[];
94
+ permissionProjection: string;
95
+ reason: string;
96
+ }
97
+
98
+ export interface WorkflowNextIntent {
99
+ stage: WorkflowNextStage;
100
+ bundle: SddCommandBundle;
101
+ targetRuntimeStage: SddStage;
102
+ resumeMode: BundleResumeMode;
103
+ intent: WorkflowNextIntentKind;
104
+ canonicalCommand: string;
105
+ displayCommand: string;
106
+ commandSemantics: WorkflowCommandSemantics;
107
+ evidenceRequirement: string;
108
+ blockingReason: string | null;
109
+ canAutoAdvanceWithinBundle: boolean;
110
+ autoAdvanceTo: SddStage | null;
111
+ stopReasons: string[];
112
+ evidenceSurface: string[];
113
+ commandBundle: CommandBundlePlan;
114
+ hostProjections: WorkflowHostCommandProjection[];
115
+ }
116
+
117
+
118
+ export interface WorkflowStateResolution {
119
+ contract: typeof WORKFLOW_STATE_RESOLVER_CONTRACT_VERSION;
120
+ generatedAt: string;
121
+ branch: string;
122
+ workflowStatus: 'active' | 'not_started';
123
+ context: ContextResolverContract;
124
+ documents: SddTaskModel['documents'];
125
+ model: SddTaskModel;
126
+ taskCounts: WorkflowTaskCounts;
127
+ visibleGaps: SddTaskGap[];
128
+ latestRun: RunSummary | null;
129
+ latestRunState: RunState | null;
130
+ latestRunsByTask: WorkflowLatestTaskRun[];
131
+ latestEligibleRunsByTask: LatestEligibleRunSelection[];
132
+ affectedFileConflicts: WorkflowAffectedFileConflict[];
133
+ blockingReasons: string[];
134
+ dependencyBlockers: WorkflowDependencyBlocker[];
135
+ openRepairs: RuntimeRepairRecord[];
136
+ workflowReadiness: WorkflowReadinessSummary;
137
+ whyNotShip: string[];
138
+ recommendedNextCommand: string;
139
+ nextIntent: WorkflowNextIntent;
140
+ truthReconciliation: TruthReconciliationDecision | null;
141
+ }
142
+
143
+ export async function resolveWorkflowState(projectRoot: string, options: { branch?: string | null; branchSource?: ContextBranchSource; taskId?: string | null } = {}): Promise<WorkflowStateResolution> {
144
+ const context = await resolveSddContext(projectRoot, options);
145
+ const branch = context.partition;
146
+ const [model, states, openRepairs, truthAlignmentEnvelope] = await Promise.all([parseSddBranch(projectRoot, branch), readAllRunStates(projectRoot), listRuntimeRepairs(projectRoot, { branchSlug: branch, status: 'open' }), readTruthAlignmentProjection(projectRoot, { branch })]);
147
+ const visibleGaps = workflowIsActive(model) ? model.gaps : [];
148
+ const latestEligibleRunsByTask = selectLatestEligibleRunsByTask({ states, model, partition: branch, currentGitBranch: context.currentGitBranch });
149
+ const latestRunsByTask = selectedLatestTaskRuns(latestEligibleRunsByTask);
150
+ const selectedTaskRun = options.taskId
151
+ ? latestRunsByTask.find((entry) => entry.taskId === options.taskId) ?? null
152
+ : latestRunsByTask.slice().sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt))[0] ?? null;
153
+ const latestRunState = selectedTaskRun ? states.find((state) => state.runId === selectedTaskRun.runId) ?? null : null;
154
+ const affectedFileConflicts = latestRunState ? affectedFileConflictsForSelectedRun(states, latestRunState) : [];
155
+ const runtimeByTask = latestRuntimeTaskStates(latestEligibleRunsByTask, states);
156
+ const dependencyBlockers = workflowDependencyBlockers(model, { runtimeByTask });
157
+ const readiness = workflowReadinessSummary(model, latestRunsByTask);
158
+ const generatedAt = new Date().toISOString();
159
+ const blockingReasons = [...blockingWorkflowReasons(visibleGaps, affectedFileConflicts, dependencyBlockers), ...openRepairs.map(formatOpenRepairReason)];
160
+ const truthReconciliation = await resolveTruthReconciliationDecision(projectRoot, branch, truthAlignmentEnvelope?.payload ?? null, generatedAt, { states, model });
161
+ const resolution: WorkflowStateResolution = {
162
+ contract: WORKFLOW_STATE_RESOLVER_CONTRACT_VERSION,
163
+ generatedAt,
164
+ branch,
165
+ workflowStatus: workflowIsActive(model) ? 'active' : 'not_started',
166
+ context,
167
+ documents: model.documents,
168
+ model,
169
+ taskCounts: taskCounts(model, visibleGaps),
170
+ visibleGaps,
171
+ latestRun: latestRunState ? summarizeRunState(latestRunState) : null,
172
+ latestRunState,
173
+ latestRunsByTask,
174
+ latestEligibleRunsByTask,
175
+ affectedFileConflicts,
176
+ dependencyBlockers,
177
+ openRepairs,
178
+ blockingReasons,
179
+ workflowReadiness: readiness,
180
+ whyNotShip: readiness.whyNotShip,
181
+ nextIntent: recommendedWorkflowNextIntent(context, model, latestRunsByTask, visibleGaps, dependencyBlockers, runtimeByTask, readiness, openRepairs, truthReconciliation),
182
+ truthReconciliation,
183
+ recommendedNextCommand: ''
184
+ };
185
+ resolution.recommendedNextCommand = resolution.nextIntent.canonicalCommand;
186
+ try {
187
+ await recordRuntimeProjection(projectRoot, 'workflow_state', branch, projectWorkflowStateProjection(resolution));
188
+ await recordWorkflowRuntimeProjections(projectRoot, resolution);
189
+ } catch {
190
+ // Projection writes are rebuildable and must not block workflow resolution.
191
+ }
192
+ return resolution;
193
+ }
194
+
195
+ function workflowIsActive(model: SddTaskModel): boolean {
196
+ return model.documents.specExists || model.documents.planExists || model.documents.tasksExists;
197
+ }
198
+
199
+ function taskCounts(model: SddTaskModel, gaps: SddTaskGap[]): WorkflowTaskCounts {
200
+ return {
201
+ total: model.tasks.length,
202
+ pending: model.tasks.filter((task) => task.status === 'pending').length,
203
+ inProgress: model.tasks.filter((task) => task.status === 'in_progress').length,
204
+ completed: model.tasks.filter((task) => task.status === 'completed').length,
205
+ blocked: model.tasks.filter((task) => task.status === 'blocked').length,
206
+ deferred: model.tasks.filter((task) => task.status === 'deferred').length,
207
+ unknown: model.tasks.filter((task) => task.status === 'unknown').length,
208
+ gaps: gaps.length
209
+ };
210
+ }
211
+
212
+ function selectedLatestTaskRuns(selections: LatestEligibleRunSelection[]): WorkflowLatestTaskRun[] {
213
+ return selections
214
+ .flatMap((selection) => selection.selected ? [selection.selected] : [])
215
+ .map((candidate) => ({
216
+ partition: candidate.partition,
217
+ gitBranch: candidate.gitBranch,
218
+ taskId: candidate.taskId,
219
+ runId: candidate.runId,
220
+ runStatus: candidate.runStatus,
221
+ validationStatus: candidate.validationStatus,
222
+ affectedFiles: candidate.affectedFiles,
223
+ updatedAt: candidate.updatedAt,
224
+ compatibility: candidate.compatibility,
225
+ eligibleForDefaultApply: candidate.eligibleForDefaultApply,
226
+ reasons: candidate.reasons
227
+ }))
228
+ .sort((left, right) => left.taskId.localeCompare(right.taskId));
229
+ }
230
+
231
+
232
+ function blockingWorkflowReasons(gaps: SddTaskGap[], conflicts: WorkflowAffectedFileConflict[], dependencyBlockers: WorkflowDependencyBlocker[]): string[] {
233
+ const reasons = gaps.filter((gap) => gap.severity === 'blocking').map((gap) => `${gap.field}: ${gap.message}`);
234
+ for (const conflict of conflicts) {
235
+ reasons.push(`Affected file ${conflict.file} is active in run ${conflict.runId} for ${conflict.partition}/${conflict.taskId}.`);
236
+ }
237
+ for (const blocker of dependencyBlockers) {
238
+ reasons.push(blocker.reason);
239
+ }
240
+ return reasons;
241
+ }
242
+
243
+ async function resolveTruthReconciliationDecision(projectRoot: string, branch: string, truthAlignment: TruthAlignmentProjection | null, generatedAt: string, progress: { states: RunState[]; model: SddTaskModel }): Promise<TruthReconciliationDecision | null> {
244
+ if (!truthAlignment) {
245
+ return null;
246
+ }
247
+ const freshness = await refreshAlignedTruthAlignmentFreshness(projectRoot, branch, truthAlignment);
248
+ if (freshness.truthAlignment.status === 'aligned') {
249
+ return null;
250
+ }
251
+ const changeKind = truthDriftClassForAlignment(freshness.truthAlignment);
252
+ const ownerStage = truthReconciliationOwnerStage(changeKind, freshness.truthAlignment.ownerStage);
253
+ const minimalFrontier = minimalReworkFrontier({ ownerStage, semanticImpact: freshness.truthAlignment.semanticImpact, invalidatesStages: freshness.truthAlignment.invalidatesStages });
254
+ const targetStage = await activeTruthReconciliationStage(projectRoot, minimalFrontier, freshness.truthAlignment, progress);
255
+ const nextIntent = truthReconciliationNextIntent(branch, targetStage, freshness.truthAlignment.reasons);
256
+ const decision = buildTruthReconciliationDecision({
257
+ truthAlignment: freshness.truthAlignment,
258
+ nextIntent,
259
+ changeKind,
260
+ changedRef: freshness.changedRef,
261
+ oldHash: freshness.oldHash,
262
+ newHash: freshness.newHash
263
+ });
264
+ await recordTruthReconciliationDecision(projectRoot, decision, generatedAt);
265
+ return decision;
266
+ }
267
+
268
+ interface TruthAlignmentFreshness {
269
+ truthAlignment: TruthAlignmentProjection;
270
+ changedRef?: RuntimeRef;
271
+ oldHash?: string;
272
+ newHash?: string;
273
+ }
274
+
275
+ async function refreshAlignedTruthAlignmentFreshness(projectRoot: string, branch: string, truthAlignment: TruthAlignmentProjection): Promise<TruthAlignmentFreshness> {
276
+ if (truthAlignment.status !== 'aligned') {
277
+ return { truthAlignment };
278
+ }
279
+ const staleRefs: Array<{ ref: RuntimeRef; currentHash: string }> = [];
280
+ for (const ref of [...truthAlignment.declaredTruthRefs, ...truthAlignment.acceptedRealityRefs]) {
281
+ if (!ref.hash || ref.kind === 'projection' || ref.kind === 'run') {
282
+ continue;
283
+ }
284
+ const currentHash = await currentTruthRefHash(projectRoot, ref);
285
+ if (currentHash !== ref.hash) {
286
+ staleRefs.push({ ref, currentHash });
287
+ }
288
+ }
289
+ const unresolvedStaleRefs = await unresolvedStaleTruthRefs(projectRoot, branch, truthAlignment, staleRefs);
290
+ const firstStaleRef = unresolvedStaleRefs[0];
291
+ if (!firstStaleRef) {
292
+ return { truthAlignment };
293
+ }
294
+ const ownerStage = ownerStageForTruthRef(branch, firstStaleRef.ref) ?? truthAlignment.ownerStage ?? 'ship';
295
+ const semanticImpact = semanticImpactForTruthRef(branch, firstStaleRef.ref);
296
+ const reasons = [
297
+ ...truthAlignment.reasons,
298
+ ...unresolvedStaleRefs.map((entry) => `TruthAlignment ref hash is stale for ${entry.ref.ref}: expected ${entry.ref.hash ?? 'unknown'}, actual ${entry.currentHash}.`)
299
+ ];
300
+ return {
301
+ truthAlignment: {
302
+ ...truthAlignment,
303
+ status: 'update_required',
304
+ ownerStage,
305
+ semanticImpact,
306
+ staleRefs: uniqueRuntimeRefs([...truthAlignment.staleRefs, ...unresolvedStaleRefs.map((entry) => entry.ref)]),
307
+ invalidatesStages: uniqueStages([...truthAlignment.invalidatesStages, ownerStage]),
308
+ reasons: uniqueStrings(reasons)
309
+ },
310
+ changedRef: firstStaleRef.ref,
311
+ oldHash: firstStaleRef.ref.hash,
312
+ newHash: firstStaleRef.currentHash
313
+ };
314
+ }
315
+
316
+ async function unresolvedStaleTruthRefs(projectRoot: string, branch: string, truthAlignment: TruthAlignmentProjection, staleRefs: Array<{ ref: RuntimeRef; currentHash: string }>): Promise<Array<{ ref: RuntimeRef; currentHash: string }>> {
317
+ const unresolved: Array<{ ref: RuntimeRef; currentHash: string }> = [];
318
+ for (const entry of staleRefs) {
319
+ if (!await staleTruthRefReconciledAfterAlignment(projectRoot, branch, truthAlignment, entry)) {
320
+ unresolved.push(entry);
321
+ }
322
+ }
323
+ return unresolved;
324
+ }
325
+
326
+ async function staleTruthRefReconciledAfterAlignment(projectRoot: string, branch: string, truthAlignment: TruthAlignmentProjection, entry: { ref: RuntimeRef; currentHash: string }): Promise<boolean> {
327
+ const stage = ownerStageForTruthRef(branch, entry.ref);
328
+ return stage ? await stageCloseAcceptedTruthRefAfterTruthAlignment(projectRoot, truthAlignment, stage, entry.ref, entry.currentHash) : false;
329
+ }
330
+
331
+ async function activeTruthReconciliationStage(projectRoot: string, frontier: SddStage[], truthAlignment: TruthAlignmentProjection, progress: { states: RunState[]; model: SddTaskModel }): Promise<SddStage> {
332
+ for (const stage of frontier) {
333
+ if (!await truthReconciliationStageCompleted(projectRoot, stage, truthAlignment, progress)) {
334
+ return stage;
335
+ }
336
+ }
337
+ return frontier[frontier.length - 1] ?? truthAlignment.ownerStage ?? 'ship';
338
+ }
339
+
340
+ async function truthReconciliationStageCompleted(projectRoot: string, stage: SddStage, truthAlignment: TruthAlignmentProjection, progress: { states: RunState[]; model: SddTaskModel }): Promise<boolean> {
341
+ if (await stageCloseCompletedAfterTruthAlignment(projectRoot, truthAlignment, stage)) {
342
+ return true;
343
+ }
344
+ const taskIds = reconciliationTaskIds(truthAlignment, progress);
345
+ if (stage === 'execute') {
346
+ return taskIds.every((taskId) => progress.states.some((state) => stateAfterTruthAlignment(state, truthAlignment) && stateTaskImplemented(state.tasks[taskId]) && stateTaskValidationPassed(state.tasks[taskId], state)));
347
+ }
348
+ return false;
349
+ }
350
+
351
+ function reconciliationTaskIds(truthAlignment: TruthAlignmentProjection, progress: { states: RunState[]; model: SddTaskModel }): string[] {
352
+ const requiredIds = requiredTaskIds(progress.model);
353
+ const requiredIdSet = new Set(requiredIds);
354
+ const targetRefs = new Set([...truthAlignment.staleRefs, ...truthAlignment.acceptedRealityRefs].map((ref) => normalizePortablePath(ref.ref)).filter(Boolean));
355
+ const taskIds = new Set<string>();
356
+ for (const state of progress.states) {
357
+ if (state.partition && state.partition !== truthAlignment.branch) {
358
+ continue;
359
+ }
360
+ if (!stateReferencesAnyRef(state, targetRefs)) {
361
+ continue;
362
+ }
363
+ for (const taskId of stateTaskIds(state)) {
364
+ if (requiredIdSet.has(taskId)) {
365
+ taskIds.add(taskId);
366
+ }
367
+ }
368
+ }
369
+ const scopedTaskIds = [...taskIds].sort();
370
+ return scopedTaskIds.length > 0 ? scopedTaskIds : requiredIds;
371
+ }
372
+
373
+ function stateReferencesAnyRef(state: RunState, targetRefs: Set<string>): boolean {
374
+ if (targetRefs.size === 0) {
375
+ return false;
376
+ }
377
+ const refs = [
378
+ ...state.artifacts.map((artifact) => artifact.path),
379
+ ...Object.values(state.tasks).flatMap((runtime) => [...(runtime.artifacts ?? []), ...(runtime.evidence ?? [])])
380
+ ];
381
+ return refs.some((ref) => refMatchesTarget(ref, targetRefs));
382
+ }
383
+
384
+ function refMatchesTarget(ref: string, targetRefs: Set<string>): boolean {
385
+ const normalized = normalizePortablePath(ref);
386
+ return Boolean(normalized && [...targetRefs].some((target) => normalized === target || normalized.endsWith(`/${target}`) || target.endsWith(`/${normalized}`)));
387
+ }
388
+
389
+ function stateTaskIds(state: RunState): string[] {
390
+ return [...new Set([state.taskId, state.currentTask, ...Object.keys(state.tasks)].filter((taskId): taskId is string => typeof taskId === 'string' && taskId.length > 0))];
391
+ }
392
+
393
+ async function stageCloseCompletedAfterTruthAlignment(projectRoot: string, truthAlignment: TruthAlignmentProjection, stage: SddStage): Promise<boolean> {
394
+ const projectionType = stageAdjudicationProjectionType(stage);
395
+ if (!projectionType) {
396
+ return false;
397
+ }
398
+ const projections = await listRuntimeProjections(projectRoot, [projectionType]);
399
+ return projections
400
+ .map((projection) => projection.payload as RuntimeProjectionEnvelope<StageCloseAdjudicationProjection>)
401
+ .some((envelope) => stageAdjudicationCompletedAfterTruthAlignment(envelope, truthAlignment, stage));
402
+ }
403
+
404
+ interface StageCloseAdjudicationProjection {
405
+ stage?: SddStage;
406
+ scope?: { branch?: string };
407
+ health?: string | null;
408
+ stageDecision?: { status?: string | null; health?: string | null; acceptedDecisionRefs?: RuntimeRef[] };
409
+ closureRefs?: Record<string, unknown>;
410
+ }
411
+
412
+ function stageAdjudicationProjectionType(stage: SddStage): string | null {
413
+ const projectionTypes: Record<SddStage, string> = {
414
+ spec: SPEC_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
415
+ plan: PLAN_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
416
+ tasks: TASKS_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
417
+ execute: EXECUTE_COLLABORATION_ADJUDICATION_PROJECTION_TYPE,
418
+ ship: SHIP_COLLABORATION_ADJUDICATION_PROJECTION_TYPE
419
+ };
420
+ return projectionTypes[stage] ?? null;
421
+ }
422
+
423
+ async function stageCloseAcceptedTruthRefAfterTruthAlignment(projectRoot: string, truthAlignment: TruthAlignmentProjection, stage: SddStage, staleRef: RuntimeRef, currentHash: string): Promise<boolean> {
424
+ const projectionType = stageAdjudicationProjectionType(stage);
425
+ if (!projectionType) {
426
+ return false;
427
+ }
428
+ const projections = await listRuntimeProjections(projectRoot, [projectionType]);
429
+ return projections
430
+ .map((projection) => projection.payload as RuntimeProjectionEnvelope<StageCloseAdjudicationProjection>)
431
+ .some((envelope) => stageAdjudicationCompletedAfterTruthAlignment(envelope, truthAlignment, stage)
432
+ && acceptedStageRefs(envelope.payload).some((acceptedRef) => acceptedTruthRefMatchesCurrent(acceptedRef, staleRef, currentHash)));
433
+ }
434
+
435
+ function acceptedTruthRefMatchesCurrent(acceptedRef: RuntimeRef, staleRef: RuntimeRef, currentHash: string): boolean {
436
+ return acceptedRef.kind === staleRef.kind
437
+ && normalizePortablePath(acceptedRef.ref) === normalizePortablePath(staleRef.ref)
438
+ && acceptedRef.hash === currentHash;
439
+ }
440
+
441
+ function stageAdjudicationCompletedAfterTruthAlignment(envelope: RuntimeProjectionEnvelope<StageCloseAdjudicationProjection>, truthAlignment: TruthAlignmentProjection, stage: SddStage): boolean {
442
+ const expectedHealth = expectedStageCloseHealth(stage);
443
+ return envelope.payload?.scope?.branch === truthAlignment.branch
444
+ && envelope.payload.stage === stage
445
+ && Date.parse(envelope.generatedAt) > Date.parse(truthAlignment.createdAt)
446
+ && envelope.payload.stageDecision?.status === 'completed'
447
+ && (envelope.payload.health === expectedHealth || envelope.payload.stageDecision?.health === expectedHealth)
448
+ && acceptedStageRefs(envelope.payload).some((ref) => ownerStageForTruthRef(truthAlignment.branch, ref) === stage);
449
+ }
450
+
451
+ function expectedStageCloseHealth(stage: SddStage): string {
452
+ const expectedHealth: Record<SddStage, string> = {
453
+ spec: 'ready_for_plan',
454
+ plan: 'ready_for_tasks',
455
+ tasks: 'ready_for_execute',
456
+ execute: 'ready_for_ship',
457
+ ship: 'ship_ready'
458
+ };
459
+ return expectedHealth[stage];
460
+ }
461
+
462
+ function acceptedStageRefs(adjudication: StageCloseAdjudicationProjection): RuntimeRef[] {
463
+ const refs = Array.isArray(adjudication.stageDecision?.acceptedDecisionRefs) ? adjudication.stageDecision.acceptedDecisionRefs : [];
464
+ const closureRefs = adjudication.closureRefs ?? {};
465
+ const closureRefKeys = [
466
+ 'acceptedSpecRef',
467
+ 'acceptedPlanRef',
468
+ 'acceptedTasksRef',
469
+ 'acceptedVerifyRef',
470
+ 'acceptedImplementationRef',
471
+ 'acceptedTestEvidenceRef',
472
+ 'acceptedEvidenceJudgmentRef',
473
+ 'acceptedShipReadinessRef'
474
+ ];
475
+ return [
476
+ ...refs,
477
+ ...closureRefKeys.map((key) => runtimeRefFromUnknown(closureRefs[key]))
478
+ ].filter((ref): ref is RuntimeRef => ref !== null);
479
+ }
480
+
481
+ function runtimeRefFromUnknown(value: unknown): RuntimeRef | null {
482
+ if (!value || typeof value !== 'object') {
483
+ return null;
484
+ }
485
+ const candidate = value as Partial<RuntimeRef>;
486
+ if (typeof candidate.kind !== 'string' || typeof candidate.ref !== 'string') {
487
+ return null;
488
+ }
489
+ return {
490
+ kind: candidate.kind as RuntimeRef['kind'],
491
+ ref: candidate.ref,
492
+ hash: typeof candidate.hash === 'string' ? candidate.hash : undefined
493
+ };
494
+ }
495
+
496
+ function requiredTaskIds(model: SddTaskModel): string[] {
497
+ return model.tasks.filter((task) => task.status !== 'deferred').map((task) => task.id);
498
+ }
499
+
500
+ function stateAfterTruthAlignment(state: RunState, truthAlignment: TruthAlignmentProjection): boolean {
501
+ return Date.parse(state.updatedAt) > Date.parse(truthAlignment.createdAt);
502
+ }
503
+
504
+ function stateTaskImplemented(runtime: RunStateTaskRuntime | undefined): boolean {
505
+ return runtimeTaskImplemented(runtime);
506
+ }
507
+
508
+ function stateTaskValidationPassed(runtime: RunStateTaskRuntime | undefined, state: RunState): boolean {
509
+ return runtime?.verificationStatus === 'pass' || runtime?.status === 'implemented_verified' || state.validation.status === 'pass';
510
+ }
511
+
512
+ async function currentTruthRefHash(projectRoot: string, ref: RuntimeRef): Promise<string> {
513
+ const normalized = normalizePortablePath(ref.ref);
514
+ if (!normalized || normalized === '.' || normalized === '..' || normalized.includes('..') || path.isAbsolute(ref.ref)) {
515
+ return 'unsafe-ref';
516
+ }
517
+ const projectPath = path.resolve(projectRoot);
518
+ const filePath = path.resolve(projectPath, normalized);
519
+ if (!filePath.startsWith(`${projectPath}${path.sep}`)) {
520
+ return 'escaped-ref';
521
+ }
522
+ try {
523
+ return hashDocumentContent(await readFile(filePath, 'utf8'));
524
+ } catch {
525
+ return 'missing-ref';
526
+ }
527
+ }
528
+
529
+ function ownerStageForTruthRef(branch: string, ref: RuntimeRef): SddStage | null {
530
+ const normalized = normalizePortablePath(ref.ref);
531
+ if (!normalized) {
532
+ return null;
533
+ }
534
+ if (normalized === `specs/${branch}/spec.md`) {
535
+ return 'spec';
536
+ }
537
+ if (normalized === `specs/${branch}/plan.md`) {
538
+ return 'plan';
539
+ }
540
+ if (normalized === `specs/${branch}/tasks.md`) {
541
+ return 'tasks';
542
+ }
543
+ if (normalized === `specs/${branch}/verify.md`) {
544
+ return 'tasks';
545
+ }
546
+ if (normalized === `specs/${branch}/release.md`) {
547
+ return 'ship';
548
+ }
549
+ const runStage = normalized.match(new RegExp(`^\\.sdd/runs/${escapeRegExp(branch)}/([^/]+)/`))?.[1];
550
+ return runStage && isSddStage(runStage) ? runStage : null;
551
+ }
552
+
553
+ function semanticImpactForTruthRef(branch: string, ref: RuntimeRef): TruthAlignmentProjection['semanticImpact'] {
554
+ const ownerStage = ownerStageForTruthRef(branch, ref);
555
+ return ref.kind === 'document' || ownerStage === 'spec' || ownerStage === 'plan' || ownerStage === 'tasks' ? 'none' : 'material';
556
+ }
557
+
558
+ function uniqueRuntimeRefs(refs: RuntimeRef[]): RuntimeRef[] {
559
+ const seen = new Set<string>();
560
+ const result: RuntimeRef[] = [];
561
+ for (const ref of refs) {
562
+ const key = `${ref.kind}:${ref.ref}:${ref.hash ?? ''}`;
563
+ if (!seen.has(key)) {
564
+ seen.add(key);
565
+ result.push(ref);
566
+ }
567
+ }
568
+ return result;
569
+ }
570
+
571
+ function uniqueStages(stages: SddStage[]): SddStage[] {
572
+ return ['spec', 'plan', 'tasks', 'execute', 'ship'].filter((stage): stage is SddStage => stages.includes(stage as SddStage));
573
+ }
574
+
575
+ function uniqueStrings(values: string[]): string[] {
576
+ return [...new Set(values)];
577
+ }
578
+
579
+ function escapeRegExp(value: string): string {
580
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
581
+ }
582
+
583
+ function truthReconciliationNextIntent(branch: string, ownerStage: SddStage, reasons: string[]): WorkflowNextIntent {
584
+ const bundle = commandBundleForRuntimeStage(ownerStage);
585
+ return workflowNextIntent(bundle, 'reconcile_truth', truthReconciliationCommand(branch, ownerStage), `Reconcile truth drift in ${ownerStage}-manager before downstream ship readiness.`, reasons.join('; ') || 'truthAlignment requires reconciliation', {
586
+ targetRuntimeStage: ownerStage,
587
+ resumeMode: 'reconcile',
588
+ canAutoAdvanceWithinBundle: ownerStage === 'execute',
589
+ evidenceSurface: [...evidenceSurfaceForRuntimeStage(ownerStage), 'truthReconciliation projection']
590
+ });
591
+ }
592
+
593
+ function truthReconciliationCommand(branch: string, ownerStage: SddStage): string {
594
+ return stageCloseCommandForRuntimeStage(branch, ownerStage);
595
+ }
596
+
597
+ function stageCloseCommandForRuntimeStage(branch: string, stage: SddStage): string {
598
+ if (stage === 'execute') {
599
+ return `sdd execute close --branch ${branch} --compact-json`;
600
+ }
601
+ return `sdd ${stage} close --branch ${branch} --compact-json`;
602
+ }
603
+
604
+ function formatOpenRepairReason(repair: RuntimeRepairRecord): string {
605
+ return `Open ${repair.repairType} ${repair.repairId}: ${repair.blockers.join('; ')}`;
606
+ }
607
+
608
+ function recommendedWorkflowNextIntent(
609
+ context: ContextResolverContract,
610
+ model: SddTaskModel,
611
+ latestRunsByTask: WorkflowLatestTaskRun[],
612
+ gaps: SddTaskGap[],
613
+ dependencyBlockers: WorkflowDependencyBlocker[],
614
+ runtimeByTask: Map<string, RunStateTaskRuntime>,
615
+ readiness: WorkflowReadinessSummary,
616
+ openRepairs: RuntimeRepairRecord[],
617
+ truthReconciliation: TruthReconciliationDecision | null
618
+ ): WorkflowNextIntent {
619
+ if (!workflowIsActive(model)) {
620
+ return workflowNextIntent('spec', 'start_spec', `sdd spec --branch ${context.partition}`, 'Start the spec stage before planning or task execution.', null);
621
+ }
622
+ const blockingGap = gaps.find((gap) => gap.severity === 'blocking');
623
+ if (blockingGap) {
624
+ return workflowNextIntent('tasks', 'resolve_task_gaps', `sdd tasks gaps --branch ${context.partition}`, 'Resolve blocking task document gaps before execution evidence can be trusted.', `${blockingGap.field}: ${blockingGap.message}`);
625
+ }
626
+ const openRepair = openRepairs[0];
627
+ if (openRepair) {
628
+ return workflowNextIntent('execute', 'repair_failure', openRepair.recommendedCommands[0] ?? `sdd doctor --branch ${context.partition} --latest-only`, openRepair.requiredEvidence.join('; ') || 'Resolve the open repair with new accepted evidence or a fresh gate PASS.', formatOpenRepairReason(openRepair));
629
+ }
630
+
631
+ if (truthReconciliation) {
632
+ return truthReconciliation.nextIntent;
633
+ }
634
+
635
+ const strictTask = model.tasks.find((task) => needsTaskValidation(task, runtimeByTask.get(task.id)));
636
+ if (strictTask) {
637
+ return workflowNextIntent('execute', 'run_task_validation', validationUnitCommand(context.partition, validationUnitIdForTask(strictTask)), 'Validate this task before more implementation proceeds.', null);
638
+ }
639
+
640
+ const readyBoundary = readyValidationBoundary(model, runtimeByTask);
641
+ if (readyBoundary?.kind === 'batch') {
642
+ return workflowNextIntent('execute', 'run_batch_validation', validationUnitCommand(context.partition, readyBoundary.id), `Validate accumulated implementation evidence for validation unit ${readyBoundary.id}.`, null);
643
+ }
644
+ if (readyBoundary?.kind === 'wave') {
645
+ return workflowNextIntent('execute', 'run_wave_validation', validationUnitCommand(context.partition, readyBoundary.id), `Validate accumulated implementation evidence for validation unit ${readyBoundary.id}.`, null);
646
+ }
647
+
648
+ if (readiness.readyForShip) {
649
+ if (evidenceJudgmentPassedForShip(model, runtimeByTask)) {
650
+ return workflowNextIntent('ship', 'ship_readiness', `sdd ship close --branch ${context.partition} --compact-json`, 'Execute evidence judgment passed; close ship readiness with ship-stage evidence.', null);
651
+ }
652
+ return workflowNextIntent('execute', 'continue_execute', stageCloseCommandForRuntimeStage(context.partition, 'execute'), 'Close execute with evidence-judgment material before ship readiness can run.', null, {
653
+ targetRuntimeStage: 'execute',
654
+ resumeMode: 'resume',
655
+ canAutoAdvanceWithinBundle: true,
656
+ evidenceSurface: ['.sdd/runs/<branch>/execute/*.md', 'truthAlignment projection']
657
+ });
658
+ }
659
+
660
+ const nextTask = model.tasks.find((task) => task.status === 'pending' && !runtimeTaskImplemented(runtimeByTask.get(task.id)) && dependencyBlockingReasonsForTask(model, task.id, { runtimeByTask }).length === 0);
661
+ if (nextTask) {
662
+ return workflowNextIntent('execute', 'continue_execute', `sdd execute --branch ${context.partition}`, `Continue public execute stage for ready task ${nextTask.id}.`, null);
663
+ }
664
+
665
+ const dependencyBlocker = dependencyBlockers[0];
666
+ if (dependencyBlocker) {
667
+ return workflowNextIntent('tasks', 'inspect_dependency', `sdd tasks inspect ${dependencyBlocker.dependencyId} --branch ${context.partition}`, 'Inspect the dependency task before continuing this workflow.', dependencyBlocker.reason);
668
+ }
669
+
670
+ const pendingTask = model.tasks.find((task) => task.status === 'pending');
671
+ return pendingTask
672
+ ? workflowNextIntent('tasks', 'inspect_task', `sdd tasks inspect ${pendingTask.id} --branch ${context.partition}`, 'Inspect task boundary, acceptance, validation, and capability needs before execute.', null)
673
+ : workflowNextIntent('tasks', 'list_tasks', `sdd tasks list --branch ${context.partition}`, 'Inspect task state and decide whether to continue or ship.', null);
674
+ }
675
+
676
+ export function latestRuntimeTaskStates(selections: LatestEligibleRunSelection[], states: RunState[]): Map<string, RunStateTaskRuntime> {
677
+ const stateByRunId = new Map(states.map((state) => [state.runId, state]));
678
+ const result = new Map<string, RunStateTaskRuntime>();
679
+ for (const selection of selections) {
680
+ const selected = selection.selected;
681
+ if (!selected) {
682
+ continue;
683
+ }
684
+ const taskState = stateByRunId.get(selected.runId)?.tasks[selected.taskId];
685
+ if (taskState) {
686
+ result.set(selected.taskId, taskState);
687
+ }
688
+ }
689
+ return result;
690
+ }
691
+
692
+ function needsTaskValidation(task: SddTask, runtime: RunStateTaskRuntime | undefined): boolean {
693
+ return Boolean(runtimeTaskImplemented(runtime) && runtime?.verificationStatus !== 'pass' && (task.requiresVerifyBeforeNext || task.validationTiming === 'task_end'));
694
+ }
695
+
696
+ function validationUnitIdForTask(task: SddTask): string {
697
+ return task.validationBatch ?? `task-${task.id}`;
698
+ }
699
+
700
+
701
+ function readyValidationBoundary(model: SddTaskModel, runtimeByTask: Map<string, RunStateTaskRuntime>): { kind: 'batch'; id: string } | { kind: 'wave'; id: string } | null {
702
+ const batchGroups = new Map<string, SddTask[]>();
703
+ const waveGroups = new Map<string, SddTask[]>();
704
+ for (const task of model.tasks) {
705
+ if (task.validationTiming === 'batch_end' && task.validationBatch) {
706
+ batchGroups.set(task.validationBatch, [...(batchGroups.get(task.validationBatch) ?? []), task]);
707
+ }
708
+ if (task.validationTiming === 'wave_end') {
709
+ const id = validationUnitIdForTask(task);
710
+ waveGroups.set(id, [...(waveGroups.get(id) ?? []), task]);
711
+ }
712
+ }
713
+ for (const [id, tasks] of batchGroups) {
714
+ if (validationBoundaryReady(tasks, runtimeByTask)) {
715
+ return { kind: 'batch', id };
716
+ }
717
+ }
718
+ for (const [id, tasks] of waveGroups) {
719
+ if (validationBoundaryReady(tasks, runtimeByTask)) {
720
+ return { kind: 'wave', id };
721
+ }
722
+ }
723
+ return null;
724
+ }
725
+
726
+ function validationBoundaryReady(tasks: SddTask[], runtimeByTask: Map<string, RunStateTaskRuntime>): boolean {
727
+ return tasks.every((task) => runtimeTaskImplemented(runtimeByTask.get(task.id)))
728
+ && tasks.some((task) => runtimeByTask.get(task.id)?.verificationStatus !== 'pass');
729
+ }
730
+
731
+ function runtimeTaskImplemented(runtime: RunStateTaskRuntime | undefined): boolean {
732
+ return runtime?.implementationStatus === 'implemented' || runtime?.status === 'implemented_pending_validation' || runtime?.status === 'implemented_verified';
733
+ }
734
+
735
+ function latestEligibleRunReadyForShip(run: WorkflowLatestTaskRun): boolean {
736
+ return run.runStatus === 'completed' && run.validationStatus === 'pass';
737
+ }
738
+
739
+ function evidenceJudgmentPassedForShip(model: SddTaskModel, runtimeByTask: Map<string, RunStateTaskRuntime>): boolean {
740
+ const requiredTasks = model.tasks.filter((task) => task.status !== 'deferred');
741
+ return requiredTasks.length > 0 && requiredTasks.every((task) => {
742
+ const runtime = runtimeByTask.get(task.id);
743
+ return runtime?.verifyStatus === 'PASS' || runtime?.status === 'implemented_verified';
744
+ });
745
+ }
746
+
747
+ function workflowReadinessSummary(model: SddTaskModel, latestRunsByTask: WorkflowLatestTaskRun[]): WorkflowReadinessSummary {
748
+ const requiredTaskIds = model.tasks.filter((task) => task.status !== 'deferred').map((task) => task.id).sort();
749
+ const acceptedTaskIds = requiredTaskIds.filter((taskId) => latestRunsByTask.some((run) => run.taskId === taskId && latestEligibleRunReadyForShip(run))).sort();
750
+ const missingTaskIds = requiredTaskIds.filter((taskId) => !acceptedTaskIds.includes(taskId));
751
+ return {
752
+ requiredTaskIds,
753
+ acceptedTaskIds,
754
+ missingTaskIds,
755
+ readyForShip: requiredTaskIds.length > 0 && missingTaskIds.length === 0,
756
+ whyNotShip: missingTaskIds.length === 0 ? [] : missingTaskIds.map((taskId) => `Task ${taskId} has no accepted validation PASS evidence.`)
757
+ };
758
+ }
759
+
760
+ function validationUnitCommand(branch: string, validationUnitId: string): string {
761
+ return `sdd execute --branch ${branch} --json`;
762
+ }
763
+
764
+
765
+ export interface WorkflowNextIntentOptions {
766
+ targetRuntimeStage?: SddStage;
767
+ resumeMode?: BundleResumeMode;
768
+ displayCommand?: string;
769
+ canAutoAdvanceWithinBundle?: boolean;
770
+ autoAdvanceTo?: SddStage | null;
771
+ stopReasons?: string[];
772
+ evidenceSurface?: string[];
773
+ }
774
+
775
+ export function workflowNextIntent(
776
+ stage: WorkflowNextStage,
777
+ intent: WorkflowNextIntentKind,
778
+ canonicalCommand: string,
779
+ evidenceRequirement: string,
780
+ blockingReason: string | null,
781
+ options: WorkflowNextIntentOptions = {}
782
+ ): WorkflowNextIntent {
783
+ const targetRuntimeStage = options.targetRuntimeStage ?? runtimeStageForCommand(canonicalCommand, stage);
784
+ const bundle = commandBundleForRuntimeStage(targetRuntimeStage);
785
+ const stages = [...COMMAND_BUNDLES[bundle]];
786
+ const autoAdvanceTo = options.autoAdvanceTo ?? null;
787
+ const canAutoAdvanceWithinBundle = options.canAutoAdvanceWithinBundle ?? Boolean(autoAdvanceTo && stages.includes(autoAdvanceTo));
788
+ const displayCommand = options.displayCommand ?? commandBundleDisplayCommand(bundle, targetRuntimeStage, canonicalCommand);
789
+ const stopReasons = options.stopReasons ?? [];
790
+ const evidenceSurface = options.evidenceSurface ?? evidenceSurfaceForRuntimeStage(targetRuntimeStage);
791
+ const resumeMode = options.resumeMode ?? defaultResumeMode(intent, targetRuntimeStage);
792
+ const commandBundle: CommandBundlePlan = {
793
+ contract: 'sdd-command-bundle-plan-v1',
794
+ branch: branchFromCommand(canonicalCommand),
795
+ bundle,
796
+ stages,
797
+ targetRuntimeStage,
798
+ resumeMode,
799
+ canonicalCommand,
800
+ displayCommand,
801
+ canAutoAdvanceWithinBundle,
802
+ autoAdvanceTo,
803
+ stopReasons,
804
+ evidenceSurface
805
+ };
806
+ return {
807
+ stage: bundle,
808
+ bundle,
809
+ targetRuntimeStage,
810
+ resumeMode,
811
+ intent,
812
+ canonicalCommand,
813
+ displayCommand,
814
+ commandSemantics: commandSemanticsForTarget(bundle, targetRuntimeStage, canonicalCommand),
815
+ evidenceRequirement,
816
+ blockingReason,
817
+ canAutoAdvanceWithinBundle,
818
+ autoAdvanceTo,
819
+ stopReasons,
820
+ evidenceSurface,
821
+ commandBundle,
822
+ hostProjections: hostCommandProjections(commandBundle)
823
+ };
824
+ }
825
+
826
+ export function commandBundleForRuntimeStage(stage: SddStage): SddCommandBundle {
827
+ return stage;
828
+ }
829
+
830
+ function runtimeStageForCommand(canonicalCommand: string, fallbackBundle: SddCommandBundle): SddStage {
831
+ const command = canonicalCommand.replace(/^sdd\s+/, '').split(/\s+/)[0];
832
+ return isSddStage(command) ? command : COMMAND_BUNDLES[fallbackBundle][0];
833
+ }
834
+
835
+ function isSddStage(value: string): value is SddStage {
836
+ return value === 'spec' || value === 'plan' || value === 'tasks' || value === 'execute' || value === 'ship';
837
+ }
838
+
839
+ function defaultResumeMode(intent: WorkflowNextIntentKind, targetRuntimeStage: SddStage): BundleResumeMode {
840
+ if (intent === 'repair_failure') {
841
+ return 'repair';
842
+ }
843
+ if (targetRuntimeStage === 'execute') {
844
+ return 'resume';
845
+ }
846
+ return 'start';
847
+ }
848
+
849
+ function commandSemanticsForTarget(bundle: SddCommandBundle, targetRuntimeStage: SddStage, canonicalCommand: string): WorkflowCommandSemantics {
850
+ if (/^sdd\s+status\b/.test(canonicalCommand)) {
851
+ return 'inspection_navigation';
852
+ }
853
+ return bundle === 'execute' || bundle === 'ship' || /\sclose\b/.test(canonicalCommand) || targetRuntimeStage === 'execute' ? 'gate_execution' : 'inspection_navigation';
854
+ }
855
+
856
+ function evidenceSurfaceForRuntimeStage(stage: SddStage): string[] {
857
+ const surfaces: Partial<Record<SddStage, string[]>> = {
858
+ spec: ['specs/<branch>/spec.md', '.sdd/runs/<branch>/spec/*.md'],
859
+ plan: ['specs/<branch>/plan.md', '.sdd/runs/<branch>/plan/*.md'],
860
+ tasks: ['specs/<branch>/tasks.md', 'specs/<branch>/verify.md', '.sdd/runs/<branch>/tasks/*.md'],
861
+ execute: ['.sdd/runs/<branch>/execute/*.md', 'truthAlignment projection'],
862
+ ship: ['.sdd/runs/<branch>/ship/*.md', 'truthAlignment projection']
863
+ };
864
+ return surfaces[stage] ?? [`.sdd/runs/<branch>/${stage}/*.md`];
865
+ }
866
+
867
+ function branchFromCommand(canonicalCommand: string): string {
868
+ const tokens = canonicalCommand.split(/\s+/);
869
+ const branchIndex = tokens.indexOf('--branch');
870
+ return branchIndex >= 0 ? tokens[branchIndex + 1] ?? '<branch>' : '<branch>';
871
+ }
872
+
873
+ function commandBundleDisplayCommand(bundle: SddCommandBundle, targetRuntimeStage: SddStage, canonicalCommand: string): string {
874
+ return claudeCodeSlashEntry({ bundle, targetRuntimeStage, canonicalCommand });
875
+ }
876
+
877
+ function hostCommandProjections(commandBundle: CommandBundlePlan): WorkflowHostCommandProjection[] {
878
+ return [
879
+ {
880
+ host: 'claude_code',
881
+ status: 'active',
882
+ entry: claudeCodeSlashEntry(commandBundle),
883
+ projectionSurfaces: ['slash command', 'skill', 'settings/hooks/statusline metadata'],
884
+ permissionProjection: 'Claude Code permission mode/tool prompts remain host enforcement, not SDD lifecycle truth.',
885
+ reason: 'Claude Code supports slash/skill/statusline projections; the canonical CLI command remains the portable source of workflow intent.'
886
+ },
887
+ {
888
+ host: 'codex',
889
+ status: 'future',
890
+ entry: null,
891
+ projectionSurfaces: ['config.toml profile', 'AGENTS.md instruction surface', 'approval_policy', 'sandbox_mode'],
892
+ permissionProjection: 'Codex approval and sandbox controls can project execution policy; custom command/skill projection is not marked active without stronger evidence.',
893
+ reason: 'Codex exposes approval, sandbox, AGENTS.md, and built-in slash surfaces, but project custom workflow command semantics stay future until validated.'
894
+ },
895
+ {
896
+ host: 'opencode',
897
+ status: 'active',
898
+ entry: opencodeCommandEntry(commandBundle),
899
+ projectionSurfaces: ['opencode.json/jsonc', '.opencode/commands', '.opencode/agents', '.opencode/skills', 'permissions'],
900
+ permissionProjection: 'OpenCode allow/ask/deny permissions can project SDD tool policy; SDD artifacts remain authoritative evidence.',
901
+ reason: 'OpenCode documents project commands, agents, skills, and permissions suitable for host-specific projection.'
902
+ }
903
+ ];
904
+ }
905
+
906
+ function claudeCodeSlashEntry(commandBundle: Pick<CommandBundlePlan, 'bundle' | 'targetRuntimeStage' | 'canonicalCommand'>): string {
907
+ return projectedCommandEntry('/sdd:', commandBundle, ':');
908
+ }
909
+
910
+ function opencodeCommandEntry(commandBundle: Pick<CommandBundlePlan, 'bundle' | 'targetRuntimeStage' | 'canonicalCommand'>): string {
911
+ return projectedCommandEntry('/sdd ', commandBundle, ' ');
912
+ }
913
+
914
+ function projectedCommandEntry(prefix: string, commandBundle: Pick<CommandBundlePlan, 'bundle' | 'targetRuntimeStage' | 'canonicalCommand'>, separator: ':' | ' '): string {
915
+ const tokens = commandBundle.canonicalCommand.replace(/^sdd\s+/, '').split(/\s+/).filter(Boolean);
916
+ const [command, ...rest] = tokens;
917
+ if (!command) {
918
+ return `/sdd ${tokens.join(' ')}`;
919
+ }
920
+ if (command === 'execute') {
921
+ const head = separator === ':' ? `${prefix}execute` : `${prefix}execute`;
922
+ return `${head}${rest.length > 0 ? ` ${rest.join(' ')}` : ''}`;
923
+ }
924
+ if (!isSddStage(command)) {
925
+ return `/sdd ${tokens.join(' ')}`;
926
+ }
927
+ const tailTokens = stripTargetOption(rest);
928
+ const publicClose = command === commandBundle.bundle && tailTokens[0] === 'close';
929
+ const target = publicClose || commandBundle.targetRuntimeStage === commandBundle.bundle ? '' : ` target=${commandBundle.targetRuntimeStage}`;
930
+ const head = separator === ':' ? `${prefix}${commandBundle.bundle}` : `${prefix}${commandBundle.bundle}`;
931
+ return `${head}${target}${tailTokens.length > 0 ? ` ${tailTokens.join(' ')}` : ''}`;
932
+ }
933
+
934
+ function stripTargetOption(tokens: string[]): string[] {
935
+ const result: string[] = [];
936
+ for (let index = 0; index < tokens.length; index += 1) {
937
+ if (tokens[index] === '--target') {
938
+ index += 1;
939
+ continue;
940
+ }
941
+ result.push(tokens[index]);
942
+ }
943
+ return result;
944
+ }
945
+
946
+ function projectWorkflowStateProjection(resolution: WorkflowStateResolution): unknown {
947
+ return {
948
+ contract: resolution.contract,
949
+ generatedAt: resolution.generatedAt,
950
+ branch: resolution.branch,
951
+ workflowStatus: resolution.workflowStatus,
952
+ documents: resolution.documents,
953
+ taskCounts: resolution.taskCounts,
954
+ latestRun: resolution.latestRun,
955
+ latestRunsByTask: resolution.latestRunsByTask,
956
+ latestEligibleRunsByTask: resolution.latestEligibleRunsByTask,
957
+ affectedFileConflicts: resolution.affectedFileConflicts,
958
+ dependencyBlockers: resolution.dependencyBlockers,
959
+ openRepairs: resolution.openRepairs,
960
+ blockingReasons: resolution.blockingReasons,
961
+ workflowReadiness: resolution.workflowReadiness,
962
+ whyNotShip: resolution.whyNotShip,
963
+ nextIntent: resolution.nextIntent,
964
+ truthReconciliation: resolution.truthReconciliation,
965
+ recommendedNextCommand: resolution.recommendedNextCommand
966
+ };
967
+ }