sdd-agent-platform 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (826) hide show
  1. package/README.md +33 -39
  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 -0
  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 +7 -13
  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/project.js +8 -8
  37. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/project.js.map +1 -1
  38. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/registries.js +1 -0
  39. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/registries.js.map +1 -1
  40. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js +4 -4
  41. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js.map +1 -1
  42. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-trust.js +24 -0
  43. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-trust.js.map +1 -1
  44. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/runtime-contracts.js +1 -1
  45. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/runtime-contracts.js.map +1 -1
  46. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js +43 -180
  47. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js.map +1 -1
  48. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.d.ts +1 -1
  49. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js +7 -14
  50. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js.map +1 -1
  51. package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/coordination.js +110 -0
  52. package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/coordination.js.map +1 -0
  53. package/node_modules/@sdd-agent-platform/core/dist/execution/background-executor.js +4 -4
  54. package/node_modules/@sdd-agent-platform/core/dist/execution/background-executor.js.map +1 -1
  55. package/node_modules/@sdd-agent-platform/core/dist/execution/foreground-subagents.js +3 -3
  56. package/node_modules/@sdd-agent-platform/core/dist/execution/foreground-subagents.js.map +1 -1
  57. package/node_modules/@sdd-agent-platform/core/dist/execution/host-invocation.js +85 -86
  58. package/node_modules/@sdd-agent-platform/core/dist/execution/host-invocation.js.map +1 -1
  59. package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js +2 -3
  60. package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js.map +1 -1
  61. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js +2 -2
  62. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js.map +1 -1
  63. package/node_modules/@sdd-agent-platform/core/dist/governance/policy.d.ts +1 -1
  64. package/node_modules/@sdd-agent-platform/core/dist/governance/policy.js +1 -1
  65. package/node_modules/@sdd-agent-platform/core/dist/governance/policy.js.map +1 -1
  66. package/node_modules/@sdd-agent-platform/core/dist/instructions.d.ts +1 -1
  67. package/node_modules/@sdd-agent-platform/core/dist/instructions.js +31 -67
  68. package/node_modules/@sdd-agent-platform/core/dist/instructions.js.map +1 -1
  69. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/decision-gate.js +1 -1
  70. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/decision-gate.js.map +1 -1
  71. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.d.ts +0 -1
  72. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js +59 -85
  73. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js.map +1 -1
  74. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/contracts.d.ts +159 -0
  75. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/contracts.js +7 -0
  76. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/contracts.js.map +1 -0
  77. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/kernel.d.ts +16 -0
  78. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/kernel.js +461 -0
  79. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/kernel.js.map +1 -0
  80. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph.d.ts +2 -0
  81. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph.js +3 -0
  82. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph.js.map +1 -0
  83. package/node_modules/@sdd-agent-platform/core/dist/orchestration/contracts.d.ts +1 -1
  84. package/node_modules/@sdd-agent-platform/core/dist/orchestration/runtime.d.ts +2 -12
  85. package/node_modules/@sdd-agent-platform/core/dist/orchestration/runtime.js +32 -80
  86. package/node_modules/@sdd-agent-platform/core/dist/orchestration/runtime.js.map +1 -1
  87. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.d.ts +2 -5
  88. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js +27 -69
  89. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js.map +1 -1
  90. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js +118 -34
  91. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js.map +1 -1
  92. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js +1 -1
  93. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js.map +1 -1
  94. package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.js +1 -1
  95. package/node_modules/@sdd-agent-platform/core/dist/registries/command-team-runtime.d.ts +1 -1
  96. package/node_modules/@sdd-agent-platform/core/dist/registries/command-team-runtime.js +8 -15
  97. package/node_modules/@sdd-agent-platform/core/dist/registries/command-team-runtime.js.map +1 -1
  98. package/node_modules/@sdd-agent-platform/core/dist/registries/eval-learning-context.js +4 -4
  99. package/node_modules/@sdd-agent-platform/core/dist/registries/eval-learning-context.js.map +1 -1
  100. package/node_modules/@sdd-agent-platform/core/dist/registries/plan-scout-domains.d.ts +13 -0
  101. package/node_modules/@sdd-agent-platform/core/dist/registries/plan-scout-domains.js +76 -0
  102. package/node_modules/@sdd-agent-platform/core/dist/registries/plan-scout-domains.js.map +1 -0
  103. package/node_modules/@sdd-agent-platform/core/dist/registries/query-status.js +2 -2
  104. package/node_modules/@sdd-agent-platform/core/dist/registries/query-status.js.map +1 -1
  105. package/node_modules/@sdd-agent-platform/core/dist/registries/skill-capabilities.js +7 -7
  106. package/node_modules/@sdd-agent-platform/core/dist/registries/skill-capabilities.js.map +1 -1
  107. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-capabilities.js +4 -4
  108. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-capabilities.js.map +1 -1
  109. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-plugins.js +2 -2
  110. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-plugins.js.map +1 -1
  111. package/node_modules/@sdd-agent-platform/core/dist/registries/worker-adapters.js +11 -11
  112. package/node_modules/@sdd-agent-platform/core/dist/registries/worker-adapters.js.map +1 -1
  113. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.d.ts +1 -1
  114. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js +21 -21
  115. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js.map +1 -1
  116. package/node_modules/@sdd-agent-platform/core/dist/risk/consumer-diagnostics.js +2 -1
  117. package/node_modules/@sdd-agent-platform/core/dist/risk/consumer-diagnostics.js.map +1 -1
  118. package/node_modules/@sdd-agent-platform/core/dist/risk/kernel.js +6 -6
  119. package/node_modules/@sdd-agent-platform/core/dist/risk/kernel.js.map +1 -1
  120. package/node_modules/@sdd-agent-platform/core/dist/risk/legacy-adapters.js +11 -23
  121. package/node_modules/@sdd-agent-platform/core/dist/risk/legacy-adapters.js.map +1 -1
  122. package/node_modules/@sdd-agent-platform/core/dist/risk/workflow-gates.d.ts +2 -2
  123. package/node_modules/@sdd-agent-platform/core/dist/risk/workflow-gates.js +18 -20
  124. package/node_modules/@sdd-agent-platform/core/dist/risk/workflow-gates.js.map +1 -1
  125. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime.d.ts +0 -2
  126. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js +1 -1
  127. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js.map +1 -1
  128. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js +16 -48
  129. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js.map +1 -1
  130. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-import.js +11 -1
  131. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-import.js.map +1 -1
  132. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js +2 -2
  133. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js.map +1 -1
  134. package/node_modules/@sdd-agent-platform/core/dist/router/stage-route-binding.d.ts +2 -2
  135. package/node_modules/@sdd-agent-platform/core/dist/router/stage-route-binding.js +20 -28
  136. package/node_modules/@sdd-agent-platform/core/dist/router/stage-route-binding.js.map +1 -1
  137. package/node_modules/@sdd-agent-platform/core/dist/router.d.ts +0 -1
  138. package/node_modules/@sdd-agent-platform/core/dist/router.js +0 -1
  139. package/node_modules/@sdd-agent-platform/core/dist/router.js.map +1 -1
  140. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.d.ts +6 -6
  141. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js +13 -124
  142. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js.map +1 -1
  143. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.d.ts +2 -0
  144. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js +5 -7
  145. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js.map +1 -1
  146. package/node_modules/@sdd-agent-platform/core/dist/run-state/model.d.ts +28 -28
  147. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-index.d.ts +2 -0
  148. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-index.js +3 -1
  149. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-index.js.map +1 -1
  150. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js +26 -36
  151. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js.map +1 -1
  152. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.d.ts +0 -4
  153. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js +5 -51
  154. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js.map +1 -1
  155. package/node_modules/@sdd-agent-platform/core/dist/run-state.d.ts +0 -1
  156. package/node_modules/@sdd-agent-platform/core/dist/run-state.js +0 -1
  157. package/node_modules/@sdd-agent-platform/core/dist/run-state.js.map +1 -1
  158. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/build.js +1 -1
  159. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/build.js.map +1 -1
  160. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/findings.js +5 -5
  161. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/findings.js.map +1 -1
  162. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js +1 -1
  163. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js.map +1 -1
  164. package/node_modules/@sdd-agent-platform/core/dist/runtime-projection-p0.d.ts +2 -2
  165. package/node_modules/@sdd-agent-platform/core/dist/runtime-projection-p0.js +11 -0
  166. package/node_modules/@sdd-agent-platform/core/dist/runtime-projection-p0.js.map +1 -1
  167. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/artifact-depth.d.ts +14 -0
  168. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/artifact-depth.js +179 -0
  169. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/artifact-depth.js.map +1 -0
  170. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.d.ts +0 -2
  171. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js +10 -97
  172. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js.map +1 -1
  173. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.d.ts +1 -1
  174. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js +6 -8
  175. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js.map +1 -1
  176. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.d.ts +5 -2
  177. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js +85 -68
  178. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js.map +1 -1
  179. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-rendering.js +2 -2
  180. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-rendering.js.map +1 -1
  181. package/node_modules/@sdd-agent-platform/core/dist/spec-entry.js +40 -0
  182. package/node_modules/@sdd-agent-platform/core/dist/spec-entry.js.map +1 -0
  183. package/node_modules/@sdd-agent-platform/core/dist/spec-manager-contracts.d.ts +12 -0
  184. package/node_modules/@sdd-agent-platform/core/dist/spec-manager-contracts.js +2 -0
  185. package/node_modules/@sdd-agent-platform/core/dist/spec-manager-contracts.js.map +1 -0
  186. package/node_modules/@sdd-agent-platform/core/dist/stage-artifacts.d.ts +2 -2
  187. package/node_modules/@sdd-agent-platform/core/dist/stage-artifacts.js +19 -26
  188. package/node_modules/@sdd-agent-platform/core/dist/stage-artifacts.js.map +1 -1
  189. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration-contracts.d.ts +1 -1
  190. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration-contracts.js +3 -6
  191. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration-contracts.js.map +1 -1
  192. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration.d.ts +111 -263
  193. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration.js +1272 -1124
  194. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration.js.map +1 -1
  195. package/node_modules/@sdd-agent-platform/core/dist/stage-runtime/runtime.js +5 -5
  196. package/node_modules/@sdd-agent-platform/core/dist/stage-runtime/runtime.js.map +1 -1
  197. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.d.ts +1 -44
  198. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js +47 -170
  199. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js.map +1 -1
  200. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js +73 -73
  201. package/node_modules/@sdd-agent-platform/core/dist/subagents/contracts.d.ts +1 -1
  202. package/node_modules/@sdd-agent-platform/core/dist/subagents/runtime.js +7 -7
  203. package/node_modules/@sdd-agent-platform/core/dist/subagents/runtime.js.map +1 -1
  204. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.d.ts +1 -0
  205. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js +2 -0
  206. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js.map +1 -0
  207. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.d.ts +1 -0
  208. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js +2 -0
  209. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js.map +1 -0
  210. package/node_modules/@sdd-agent-platform/core/dist/sync-back.d.ts +1 -0
  211. package/node_modules/@sdd-agent-platform/core/dist/sync-back.js +2 -0
  212. package/node_modules/@sdd-agent-platform/core/dist/sync-back.js.map +1 -0
  213. package/node_modules/@sdd-agent-platform/core/dist/task-execution-contract.d.ts +167 -0
  214. package/node_modules/@sdd-agent-platform/core/dist/task-execution-contract.js +377 -0
  215. package/node_modules/@sdd-agent-platform/core/dist/task-execution-contract.js.map +1 -0
  216. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js +329 -314
  217. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js.map +1 -1
  218. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.d.ts +1 -0
  219. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js +53 -7
  220. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js.map +1 -1
  221. package/node_modules/@sdd-agent-platform/core/dist/truth-reconciliation.js +9 -12
  222. package/node_modules/@sdd-agent-platform/core/dist/truth-reconciliation.js.map +1 -1
  223. package/node_modules/@sdd-agent-platform/core/dist/tsconfig.tsbuildinfo +1 -1
  224. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.d.ts +0 -48
  225. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js +1 -520
  226. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js.map +1 -1
  227. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.d.ts +5 -5
  228. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js +14 -14
  229. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js.map +1 -1
  230. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.d.ts +1 -0
  231. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js +111 -159
  232. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js.map +1 -1
  233. package/node_modules/@sdd-agent-platform/core/dist/verification/task-evidence-judgment.d.ts +49 -0
  234. package/node_modules/@sdd-agent-platform/core/dist/verification/task-evidence-judgment.js +521 -0
  235. package/node_modules/@sdd-agent-platform/core/dist/verification/task-evidence-judgment.js.map +1 -0
  236. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js +21 -21
  237. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js.map +1 -1
  238. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.d.ts +0 -18
  239. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js +5 -27
  240. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js.map +1 -1
  241. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js +45 -45
  242. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js.map +1 -1
  243. package/node_modules/@sdd-agent-platform/core/dist/verification.d.ts +3 -3
  244. package/node_modules/@sdd-agent-platform/core/dist/verification.js +2 -2
  245. package/node_modules/@sdd-agent-platform/core/dist/verification.js.map +1 -1
  246. package/node_modules/@sdd-agent-platform/core/dist/work-units/contracts.d.ts +1 -1
  247. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js +9 -227
  248. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js.map +1 -1
  249. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js +9 -50
  250. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js.map +1 -1
  251. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js +4 -42
  252. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js.map +1 -1
  253. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.d.ts +2 -3
  254. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
  255. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js +2 -1
  256. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
  257. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.js +1 -1
  258. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.d.ts +1 -0
  259. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js +23 -63
  260. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js.map +1 -1
  261. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.d.ts +2 -2
  262. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js +43 -65
  263. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js.map +1 -1
  264. package/node_modules/@sdd-agent-platform/core/package.json +5 -2
  265. package/node_modules/@sdd-agent-platform/core/src/ai-tools.test.ts +238 -185
  266. package/node_modules/@sdd-agent-platform/core/src/ai-tools.ts +56 -73
  267. package/node_modules/@sdd-agent-platform/core/src/artifacts/ingestion.test.ts +189 -227
  268. package/node_modules/@sdd-agent-platform/core/src/artifacts/ingestion.ts +222 -278
  269. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-evidence.test.ts +28 -28
  270. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-evidence.ts +302 -301
  271. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-result.test.ts +181 -181
  272. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-result.ts +231 -240
  273. package/node_modules/@sdd-agent-platform/core/src/artifacts/templates.ts +99 -99
  274. package/node_modules/@sdd-agent-platform/core/src/artifacts.ts +4 -4
  275. package/node_modules/@sdd-agent-platform/core/src/coding-facts/contracts.ts +79 -79
  276. package/node_modules/@sdd-agent-platform/core/src/coding-facts.ts +1 -1
  277. package/node_modules/@sdd-agent-platform/core/src/config/init-project.test.ts +314 -318
  278. package/node_modules/@sdd-agent-platform/core/src/config/init-project.ts +128 -123
  279. package/node_modules/@sdd-agent-platform/core/src/config/project-config.ts +265 -265
  280. package/node_modules/@sdd-agent-platform/core/src/config/project-detection.ts +147 -147
  281. package/node_modules/@sdd-agent-platform/core/src/config/starter-documents.ts +400 -432
  282. package/node_modules/@sdd-agent-platform/core/src/context/budget.ts +30 -30
  283. package/node_modules/@sdd-agent-platform/core/src/context/build-package.ts +305 -311
  284. package/node_modules/@sdd-agent-platform/core/src/context/command-summary.ts +45 -45
  285. package/node_modules/@sdd-agent-platform/core/src/context/context-build.test.ts +188 -189
  286. package/node_modules/@sdd-agent-platform/core/src/context/evidence-summary.ts +144 -163
  287. package/node_modules/@sdd-agent-platform/core/src/context/log-worker.ts +48 -48
  288. package/node_modules/@sdd-agent-platform/core/src/context/source-refs.ts +41 -41
  289. package/node_modules/@sdd-agent-platform/core/src/context-offload/contracts.ts +47 -47
  290. package/node_modules/@sdd-agent-platform/core/src/context-offload/runtime.test.ts +71 -71
  291. package/node_modules/@sdd-agent-platform/core/src/context-offload/runtime.ts +178 -178
  292. package/node_modules/@sdd-agent-platform/core/src/context-offload.ts +2 -2
  293. package/node_modules/@sdd-agent-platform/core/src/context.ts +6 -6
  294. package/node_modules/@sdd-agent-platform/core/src/contracts/issues.ts +13 -13
  295. package/node_modules/@sdd-agent-platform/core/src/contracts.test.ts +9 -9
  296. package/node_modules/@sdd-agent-platform/core/src/contracts.ts +121 -116
  297. package/node_modules/@sdd-agent-platform/core/src/delegation/delegation.test.ts +183 -183
  298. package/node_modules/@sdd-agent-platform/core/src/delegation/model.ts +23 -26
  299. package/node_modules/@sdd-agent-platform/core/src/delegation/queue.ts +58 -58
  300. package/node_modules/@sdd-agent-platform/core/src/delegation/run-state.ts +14 -14
  301. package/node_modules/@sdd-agent-platform/core/src/delegation/state-machine.ts +90 -90
  302. package/node_modules/@sdd-agent-platform/core/src/delegation/validation.ts +124 -127
  303. package/node_modules/@sdd-agent-platform/core/src/delegation.ts +26 -26
  304. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/ai-entries.ts +28 -28
  305. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/document-chain.ts +104 -112
  306. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/local-run-index.ts +27 -27
  307. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/project.ts +84 -84
  308. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/registries.ts +252 -251
  309. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-evidence.ts +330 -330
  310. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-records.ts +79 -79
  311. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-trust.ts +128 -107
  312. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/runtime-contracts.ts +300 -300
  313. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.test.ts +627 -755
  314. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.ts +301 -453
  315. package/node_modules/@sdd-agent-platform/core/src/doctor/model.ts +13 -13
  316. package/node_modules/@sdd-agent-platform/core/src/doctor/summary.ts +11 -11
  317. package/node_modules/@sdd-agent-platform/core/src/doctor.ts +2 -2
  318. package/node_modules/@sdd-agent-platform/core/src/evidence/lookup.ts +80 -88
  319. package/node_modules/@sdd-agent-platform/core/src/evidence-runtime/contracts.ts +48 -48
  320. package/node_modules/@sdd-agent-platform/core/src/evidence-runtime.ts +1 -1
  321. package/node_modules/@sdd-agent-platform/core/src/execution/agent-execution-records.ts +195 -195
  322. package/node_modules/@sdd-agent-platform/core/src/execution/background-executor.test.ts +187 -235
  323. package/node_modules/@sdd-agent-platform/core/src/execution/background-executor.ts +305 -305
  324. package/node_modules/@sdd-agent-platform/core/src/execution/foreground-subagents.test.ts +97 -106
  325. package/node_modules/@sdd-agent-platform/core/src/execution/foreground-subagents.ts +453 -453
  326. package/node_modules/@sdd-agent-platform/core/src/execution/host-invocation.ts +225 -226
  327. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.test.ts +132 -143
  328. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.ts +436 -437
  329. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.test.ts +102 -102
  330. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.ts +271 -271
  331. package/node_modules/@sdd-agent-platform/core/src/execution/wave-executor.test.ts +111 -121
  332. package/node_modules/@sdd-agent-platform/core/src/execution/wave-executor.ts +231 -231
  333. package/node_modules/@sdd-agent-platform/core/src/execution.ts +5 -5
  334. package/node_modules/@sdd-agent-platform/core/src/governance/policy.test.ts +57 -65
  335. package/node_modules/@sdd-agent-platform/core/src/governance/policy.ts +175 -175
  336. package/node_modules/@sdd-agent-platform/core/src/governance.ts +1 -1
  337. package/node_modules/@sdd-agent-platform/core/src/instructions.test.ts +80 -64
  338. package/node_modules/@sdd-agent-platform/core/src/instructions.ts +32 -68
  339. package/node_modules/@sdd-agent-platform/core/src/lifecycle/decision-gate.test.ts +174 -174
  340. package/node_modules/@sdd-agent-platform/core/src/lifecycle/decision-gate.ts +373 -373
  341. package/node_modules/@sdd-agent-platform/core/src/lifecycle/rendering.ts +29 -29
  342. package/node_modules/@sdd-agent-platform/core/src/lifecycle/risk-signals.ts +146 -146
  343. package/node_modules/@sdd-agent-platform/core/src/lifecycle/ship.test.ts +47 -47
  344. package/node_modules/@sdd-agent-platform/core/src/lifecycle/ship.ts +255 -280
  345. package/node_modules/@sdd-agent-platform/core/src/lifecycle-graph/contracts.ts +179 -0
  346. package/node_modules/@sdd-agent-platform/core/src/lifecycle-graph/kernel.ts +522 -0
  347. package/node_modules/@sdd-agent-platform/core/src/lifecycle-graph.ts +2 -0
  348. package/node_modules/@sdd-agent-platform/core/src/lifecycle.ts +4 -4
  349. package/node_modules/@sdd-agent-platform/core/src/orchestration/contracts.ts +50 -50
  350. package/node_modules/@sdd-agent-platform/core/src/orchestration/index.ts +2 -2
  351. package/node_modules/@sdd-agent-platform/core/src/orchestration/runtime.ts +331 -394
  352. package/node_modules/@sdd-agent-platform/core/src/path-safety.test.ts +22 -22
  353. package/node_modules/@sdd-agent-platform/core/src/phase8-contracts.test.ts +243 -242
  354. package/node_modules/@sdd-agent-platform/core/src/phase8-projection-compat.test.ts +152 -153
  355. package/node_modules/@sdd-agent-platform/core/src/phase8-risk-kernel.test.ts +277 -277
  356. package/node_modules/@sdd-agent-platform/core/src/phase9-lifecycle-graph.test.ts +103 -0
  357. package/node_modules/@sdd-agent-platform/core/src/planning/task-graph.test.ts +88 -88
  358. package/node_modules/@sdd-agent-platform/core/src/planning/task-graph.ts +222 -222
  359. package/node_modules/@sdd-agent-platform/core/src/planning/wave-plan.test.ts +79 -79
  360. package/node_modules/@sdd-agent-platform/core/src/planning/wave-plan.ts +160 -160
  361. package/node_modules/@sdd-agent-platform/core/src/planning.ts +2 -2
  362. package/node_modules/@sdd-agent-platform/core/src/registries/agent-capability-catalog.ts +426 -473
  363. package/node_modules/@sdd-agent-platform/core/src/registries/agent-registry.ts +230 -146
  364. package/node_modules/@sdd-agent-platform/core/src/registries/agent-runtime-static.ts +142 -142
  365. package/node_modules/@sdd-agent-platform/core/src/registries/capability-sources.ts +253 -253
  366. package/node_modules/@sdd-agent-platform/core/src/registries/command-team-runtime.ts +302 -309
  367. package/node_modules/@sdd-agent-platform/core/src/registries/eval-learning-context.ts +246 -246
  368. package/node_modules/@sdd-agent-platform/core/src/registries/plan-scout-domains.ts +89 -0
  369. package/node_modules/@sdd-agent-platform/core/src/registries/query-status.ts +119 -119
  370. package/node_modules/@sdd-agent-platform/core/src/registries/registries.test.ts +454 -445
  371. package/node_modules/@sdd-agent-platform/core/src/registries/skill-capabilities.ts +37 -37
  372. package/node_modules/@sdd-agent-platform/core/src/registries/tool-capabilities.ts +135 -135
  373. package/node_modules/@sdd-agent-platform/core/src/registries/tool-plugins.ts +132 -132
  374. package/node_modules/@sdd-agent-platform/core/src/registries/worker-adapters.ts +144 -144
  375. package/node_modules/@sdd-agent-platform/core/src/registries/workflow-gates.ts +111 -111
  376. package/node_modules/@sdd-agent-platform/core/src/registries.ts +42 -42
  377. package/node_modules/@sdd-agent-platform/core/src/risk/consumer-diagnostics.ts +98 -97
  378. package/node_modules/@sdd-agent-platform/core/src/risk/contracts.ts +63 -63
  379. package/node_modules/@sdd-agent-platform/core/src/risk/kernel.ts +233 -233
  380. package/node_modules/@sdd-agent-platform/core/src/risk/legacy-adapters.ts +251 -263
  381. package/node_modules/@sdd-agent-platform/core/src/risk/workflow-gates.ts +203 -205
  382. package/node_modules/@sdd-agent-platform/core/src/risk.ts +5 -5
  383. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime-config.ts +327 -327
  384. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime.ts +388 -390
  385. package/node_modules/@sdd-agent-platform/core/src/router/profile-resolution.ts +154 -154
  386. package/node_modules/@sdd-agent-platform/core/src/router/risk-policy.ts +33 -33
  387. package/node_modules/@sdd-agent-platform/core/src/router/route-cache.ts +100 -100
  388. package/node_modules/@sdd-agent-platform/core/src/router/route-projection.ts +356 -356
  389. package/node_modules/@sdd-agent-platform/core/src/router/route-sdd-task.test.ts +428 -665
  390. package/node_modules/@sdd-agent-platform/core/src/router/route-sdd-task.ts +2 -2
  391. package/node_modules/@sdd-agent-platform/core/src/router/routing-rules.ts +73 -73
  392. package/node_modules/@sdd-agent-platform/core/src/router/routing.ts +189 -223
  393. package/node_modules/@sdd-agent-platform/core/src/router/runtime-import.ts +464 -453
  394. package/node_modules/@sdd-agent-platform/core/src/router/runtime-inspection.ts +124 -124
  395. package/node_modules/@sdd-agent-platform/core/src/router/runtime-registry.ts +123 -123
  396. package/node_modules/@sdd-agent-platform/core/src/router/runtime-validation.ts +277 -277
  397. package/node_modules/@sdd-agent-platform/core/src/router/stage-route-binding.ts +273 -279
  398. package/node_modules/@sdd-agent-platform/core/src/router/team-mode.ts +170 -170
  399. package/node_modules/@sdd-agent-platform/core/src/router.ts +5 -6
  400. package/node_modules/@sdd-agent-platform/core/src/run-state/artifacts.ts +126 -240
  401. package/node_modules/@sdd-agent-platform/core/src/run-state/events.ts +27 -27
  402. package/node_modules/@sdd-agent-platform/core/src/run-state/inspect-run.ts +172 -172
  403. package/node_modules/@sdd-agent-platform/core/src/run-state/invocation-ledger.ts +109 -109
  404. package/node_modules/@sdd-agent-platform/core/src/run-state/model.ts +252 -253
  405. package/node_modules/@sdd-agent-platform/core/src/run-state/run-index.test.ts +52 -52
  406. package/node_modules/@sdd-agent-platform/core/src/run-state/run-index.ts +356 -352
  407. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.test.ts +70 -118
  408. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.ts +406 -416
  409. package/node_modules/@sdd-agent-platform/core/src/run-state/task-evidence.ts +198 -252
  410. package/node_modules/@sdd-agent-platform/core/src/run-state/timing.ts +146 -146
  411. package/node_modules/@sdd-agent-platform/core/src/run-state.ts +8 -9
  412. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis/build.ts +60 -60
  413. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis/findings.ts +257 -256
  414. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis/model.ts +140 -140
  415. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis.test.ts +66 -66
  416. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis.ts +2 -2
  417. package/node_modules/@sdd-agent-platform/core/src/runtime-paths.ts +253 -253
  418. package/node_modules/@sdd-agent-platform/core/src/runtime-projection-p0.test.ts +101 -96
  419. package/node_modules/@sdd-agent-platform/core/src/runtime-projection-p0.ts +314 -292
  420. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/artifact-depth.test.ts +380 -0
  421. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/artifact-depth.ts +207 -0
  422. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/context.ts +111 -111
  423. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/document-hashes.ts +207 -306
  424. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/run-binding.ts +95 -97
  425. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-inspection.ts +39 -39
  426. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.test.ts +467 -523
  427. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.ts +738 -709
  428. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-rendering.ts +81 -81
  429. package/node_modules/@sdd-agent-platform/core/src/sdd-docs.ts +5 -5
  430. package/node_modules/@sdd-agent-platform/core/src/spec-manager-contracts.ts +13 -0
  431. package/node_modules/@sdd-agent-platform/core/src/stage-artifacts.ts +435 -450
  432. package/node_modules/@sdd-agent-platform/core/src/stage-collaboration-contracts.ts +316 -322
  433. package/node_modules/@sdd-agent-platform/core/src/stage-collaboration.test.ts +2963 -2902
  434. package/node_modules/@sdd-agent-platform/core/src/stage-collaboration.ts +5856 -5831
  435. package/node_modules/@sdd-agent-platform/core/src/stage-runtime/contracts.ts +40 -40
  436. package/node_modules/@sdd-agent-platform/core/src/stage-runtime/runtime.test.ts +209 -209
  437. package/node_modules/@sdd-agent-platform/core/src/stage-runtime/runtime.ts +360 -360
  438. package/node_modules/@sdd-agent-platform/core/src/stage-runtime.ts +2 -2
  439. package/node_modules/@sdd-agent-platform/core/src/status/project-status.test.ts +288 -511
  440. package/node_modules/@sdd-agent-platform/core/src/status/project-status.ts +651 -851
  441. package/node_modules/@sdd-agent-platform/core/src/status.ts +2 -2
  442. package/node_modules/@sdd-agent-platform/core/src/storage/json-io.ts +10 -10
  443. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.test.ts +489 -681
  444. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.ts +1981 -1981
  445. package/node_modules/@sdd-agent-platform/core/src/subagents/contracts.ts +45 -45
  446. package/node_modules/@sdd-agent-platform/core/src/subagents/runtime.test.ts +232 -232
  447. package/node_modules/@sdd-agent-platform/core/src/subagents/runtime.ts +307 -307
  448. package/node_modules/@sdd-agent-platform/core/src/subagents.ts +2 -2
  449. package/node_modules/@sdd-agent-platform/core/src/task-execution-contract.test.ts +141 -0
  450. package/node_modules/@sdd-agent-platform/core/src/task-execution-contract.ts +566 -0
  451. package/node_modules/@sdd-agent-platform/core/src/task-risk-profile.ts +193 -193
  452. package/node_modules/@sdd-agent-platform/core/src/test-support/fixtures.ts +413 -398
  453. package/node_modules/@sdd-agent-platform/core/src/test-support/run-state.ts +102 -56
  454. package/node_modules/@sdd-agent-platform/core/src/test-support.ts +2 -2
  455. package/node_modules/@sdd-agent-platform/core/src/truth-reconciliation.test.ts +72 -72
  456. package/node_modules/@sdd-agent-platform/core/src/truth-reconciliation.ts +9 -12
  457. package/node_modules/@sdd-agent-platform/core/src/verification/rendering.ts +137 -137
  458. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.test.ts +77 -84
  459. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.ts +77 -77
  460. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.ts +455 -506
  461. package/node_modules/@sdd-agent-platform/core/src/verification/{goal-verify.test.ts → task-evidence-judgment.test.ts} +261 -261
  462. package/node_modules/@sdd-agent-platform/core/src/verification/{goal-verify.ts → task-evidence-judgment.ts} +619 -619
  463. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.ts +1190 -1190
  464. package/node_modules/@sdd-agent-platform/core/src/verification/validation-cache.ts +106 -106
  465. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.ts +513 -556
  466. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.ts +334 -334
  467. package/node_modules/@sdd-agent-platform/core/src/verification.ts +8 -8
  468. package/node_modules/@sdd-agent-platform/core/src/work-units/contracts.ts +26 -26
  469. package/node_modules/@sdd-agent-platform/core/src/work-units/runtime.test.ts +88 -88
  470. package/node_modules/@sdd-agent-platform/core/src/work-units/runtime.ts +112 -112
  471. package/node_modules/@sdd-agent-platform/core/src/work-units.ts +2 -2
  472. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/evidence-packet.ts +190 -425
  473. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.test.ts +169 -507
  474. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.ts +136 -182
  475. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.test.ts +135 -174
  476. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.ts +153 -194
  477. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/types.ts +111 -115
  478. package/node_modules/@sdd-agent-platform/core/src/workflow-state/affected-file-conflicts.ts +95 -93
  479. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.test.ts +32 -32
  480. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.ts +114 -114
  481. package/node_modules/@sdd-agent-platform/core/src/workflow-state/latest-eligible-run.ts +184 -224
  482. package/node_modules/@sdd-agent-platform/core/src/workflow-state/migration-recovery.ts +158 -158
  483. package/node_modules/@sdd-agent-platform/core/src/workflow-state/repair-contract.ts +77 -77
  484. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve-task-run.ts +114 -114
  485. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.test.ts +969 -956
  486. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.ts +967 -992
  487. package/node_modules/@sdd-agent-platform/core/src/workflow-state/runtime-projections.ts +712 -712
  488. package/node_modules/@sdd-agent-platform/core/src/workflow-state.ts +2 -2
  489. package/node_modules/@sdd-agent-platform/core/src/worktree/isolation.ts +130 -130
  490. package/node_modules/@sdd-agent-platform/core/src/worktree/lifecycle.ts +269 -269
  491. package/node_modules/@sdd-agent-platform/core/src/worktree/worktree.test.ts +150 -150
  492. package/node_modules/@sdd-agent-platform/core/src/worktree.ts +2 -2
  493. package/node_modules/@sdd-agent-platform/core/tsconfig.json +15 -15
  494. package/package.json +2 -2
  495. package/packages/cli/dist/args.js +2 -2
  496. package/packages/cli/dist/args.js.map +1 -1
  497. package/packages/cli/dist/commands/ai-tools.js +2 -13
  498. package/packages/cli/dist/commands/ai-tools.js.map +1 -1
  499. package/packages/cli/dist/commands/{verifies.d.ts → artifact.d.ts} +1 -1
  500. package/packages/cli/dist/commands/artifact.js +168 -0
  501. package/packages/cli/dist/commands/artifact.js.map +1 -0
  502. package/packages/cli/dist/commands/context.js +1 -1
  503. package/packages/cli/dist/commands/context.js.map +1 -1
  504. package/packages/cli/dist/commands/evidence.js.map +1 -0
  505. package/packages/cli/dist/commands/execution.js +127 -49
  506. package/packages/cli/dist/commands/execution.js.map +1 -1
  507. package/packages/cli/dist/commands/governance.js +1 -1
  508. package/packages/cli/dist/commands/governance.js.map +1 -1
  509. package/packages/cli/dist/commands/init.js +1 -6
  510. package/packages/cli/dist/commands/init.js.map +1 -1
  511. package/packages/cli/dist/commands/instructions.d.ts +1 -1
  512. package/packages/cli/dist/commands/instructions.js +15 -1
  513. package/packages/cli/dist/commands/instructions.js.map +1 -1
  514. package/packages/cli/dist/commands/registry/runtime.js +63 -40
  515. package/packages/cli/dist/commands/registry/runtime.js.map +1 -1
  516. package/packages/cli/dist/commands/run.js +13 -52
  517. package/packages/cli/dist/commands/run.js.map +1 -1
  518. package/packages/cli/dist/commands/stage-close.d.ts +60 -0
  519. package/packages/cli/dist/commands/stage-close.js +270 -41
  520. package/packages/cli/dist/commands/stage-close.js.map +1 -1
  521. package/packages/cli/dist/commands/status.js +9 -68
  522. package/packages/cli/dist/commands/status.js.map +1 -1
  523. package/packages/cli/dist/commands/tasks.js.map +1 -1
  524. package/packages/cli/dist/dispatch.js +6 -26
  525. package/packages/cli/dist/dispatch.js.map +1 -1
  526. package/packages/cli/dist/help.js +153 -159
  527. package/packages/cli/dist/help.js.map +1 -1
  528. package/packages/cli/dist/renderers/artifacts.d.ts +5 -0
  529. package/packages/cli/dist/renderers/artifacts.js +43 -0
  530. package/packages/cli/dist/renderers/artifacts.js.map +1 -0
  531. package/packages/cli/dist/renderers/doctor.js +1 -1
  532. package/packages/cli/dist/renderers/doctor.js.map +1 -1
  533. package/packages/cli/dist/renderers/execution.js +1 -1
  534. package/packages/cli/dist/renderers/execution.js.map +1 -1
  535. package/packages/cli/dist/renderers/json.d.ts +0 -1
  536. package/packages/cli/dist/renderers/json.js +0 -3
  537. package/packages/cli/dist/renderers/json.js.map +1 -1
  538. package/packages/cli/dist/renderers/registry-runtime.d.ts +1 -2
  539. package/packages/cli/dist/renderers/registry-runtime.js +0 -20
  540. package/packages/cli/dist/renderers/registry-runtime.js.map +1 -1
  541. package/packages/cli/dist/renderers/router.js +1 -1
  542. package/packages/cli/dist/renderers/router.js.map +1 -1
  543. package/packages/cli/dist/renderers/workflow.d.ts +53 -0
  544. package/packages/cli/dist/renderers/workflow.js +89 -30
  545. package/packages/cli/dist/renderers/workflow.js.map +1 -1
  546. package/packages/cli/dist/tsconfig.tsbuildinfo +1 -1
  547. package/packages/cli/package.json +2 -2
  548. package/packages/core/dist/ai-tools.js +56 -73
  549. package/packages/core/dist/ai-tools.js.map +1 -1
  550. package/packages/core/dist/artifacts/ingestion.js +9 -64
  551. package/packages/core/dist/artifacts/ingestion.js.map +1 -1
  552. package/packages/core/dist/artifacts/sdd-evidence.js +1 -0
  553. package/packages/core/dist/artifacts/sdd-evidence.js.map +1 -1
  554. package/packages/core/dist/artifacts/sdd-result.js +17 -26
  555. package/packages/core/dist/artifacts/sdd-result.js.map +1 -1
  556. package/packages/core/dist/config/init-project.d.ts +8 -7
  557. package/packages/core/dist/config/init-project.js +8 -12
  558. package/packages/core/dist/config/init-project.js.map +1 -1
  559. package/packages/core/dist/config/project-config.d.ts +1 -1
  560. package/packages/core/dist/config/project-config.js +1 -1
  561. package/packages/core/dist/config/project-config.js.map +1 -1
  562. package/packages/core/dist/config/starter-documents.d.ts +3 -4
  563. package/packages/core/dist/config/starter-documents.js +377 -411
  564. package/packages/core/dist/config/starter-documents.js.map +1 -1
  565. package/packages/core/dist/context/build-package.d.ts +1 -1
  566. package/packages/core/dist/context/build-package.js +7 -13
  567. package/packages/core/dist/context/build-package.js.map +1 -1
  568. package/packages/core/dist/context/evidence-summary.js +8 -26
  569. package/packages/core/dist/context/evidence-summary.js.map +1 -1
  570. package/packages/core/dist/context/log-worker.js +2 -2
  571. package/packages/core/dist/context/log-worker.js.map +1 -1
  572. package/packages/core/dist/context-offload/contracts.d.ts +1 -1
  573. package/packages/core/dist/contracts.d.ts +6 -1
  574. package/packages/core/dist/contracts.js +5 -0
  575. package/packages/core/dist/contracts.js.map +1 -1
  576. package/packages/core/dist/delegation/model.d.ts +0 -3
  577. package/packages/core/dist/delegation/validation.d.ts +0 -3
  578. package/packages/core/dist/delegation/validation.js +4 -7
  579. package/packages/core/dist/delegation/validation.js.map +1 -1
  580. package/packages/core/dist/doctor/checks/document-chain.js +3 -13
  581. package/packages/core/dist/doctor/checks/document-chain.js.map +1 -1
  582. package/packages/core/dist/doctor/checks/project.js +8 -8
  583. package/packages/core/dist/doctor/checks/project.js.map +1 -1
  584. package/packages/core/dist/doctor/checks/registries.js +1 -0
  585. package/packages/core/dist/doctor/checks/registries.js.map +1 -1
  586. package/packages/core/dist/doctor/checks/run-evidence.js +4 -4
  587. package/packages/core/dist/doctor/checks/run-evidence.js.map +1 -1
  588. package/packages/core/dist/doctor/checks/run-trust.js +24 -0
  589. package/packages/core/dist/doctor/checks/run-trust.js.map +1 -1
  590. package/packages/core/dist/doctor/checks/runtime-contracts.js +1 -1
  591. package/packages/core/dist/doctor/checks/runtime-contracts.js.map +1 -1
  592. package/packages/core/dist/doctor/doctor.js +43 -180
  593. package/packages/core/dist/doctor/doctor.js.map +1 -1
  594. package/packages/core/dist/evidence/lookup.d.ts +1 -1
  595. package/packages/core/dist/evidence/lookup.js +7 -14
  596. package/packages/core/dist/evidence/lookup.js.map +1 -1
  597. package/packages/core/dist/evidence-runtime/coordination.js +110 -0
  598. package/packages/core/dist/evidence-runtime/coordination.js.map +1 -0
  599. package/packages/core/dist/execution/background-executor.js +4 -4
  600. package/packages/core/dist/execution/background-executor.js.map +1 -1
  601. package/packages/core/dist/execution/foreground-subagents.js +3 -3
  602. package/packages/core/dist/execution/foreground-subagents.js.map +1 -1
  603. package/packages/core/dist/execution/host-invocation.js +85 -86
  604. package/packages/core/dist/execution/host-invocation.js.map +1 -1
  605. package/packages/core/dist/execution/resident-worker.js +2 -3
  606. package/packages/core/dist/execution/resident-worker.js.map +1 -1
  607. package/packages/core/dist/execution/stage-team-runtime.js +2 -2
  608. package/packages/core/dist/execution/stage-team-runtime.js.map +1 -1
  609. package/packages/core/dist/governance/policy.d.ts +1 -1
  610. package/packages/core/dist/governance/policy.js +1 -1
  611. package/packages/core/dist/governance/policy.js.map +1 -1
  612. package/packages/core/dist/instructions.d.ts +1 -1
  613. package/packages/core/dist/instructions.js +31 -67
  614. package/packages/core/dist/instructions.js.map +1 -1
  615. package/packages/core/dist/lifecycle/decision-gate.js +1 -1
  616. package/packages/core/dist/lifecycle/decision-gate.js.map +1 -1
  617. package/packages/core/dist/lifecycle/ship.d.ts +0 -1
  618. package/packages/core/dist/lifecycle/ship.js +59 -85
  619. package/packages/core/dist/lifecycle/ship.js.map +1 -1
  620. package/packages/core/dist/lifecycle-graph/contracts.d.ts +159 -0
  621. package/packages/core/dist/lifecycle-graph/contracts.js +7 -0
  622. package/packages/core/dist/lifecycle-graph/contracts.js.map +1 -0
  623. package/packages/core/dist/lifecycle-graph/kernel.d.ts +16 -0
  624. package/packages/core/dist/lifecycle-graph/kernel.js +461 -0
  625. package/packages/core/dist/lifecycle-graph/kernel.js.map +1 -0
  626. package/packages/core/dist/lifecycle-graph.d.ts +2 -0
  627. package/packages/core/dist/lifecycle-graph.js +3 -0
  628. package/packages/core/dist/lifecycle-graph.js.map +1 -0
  629. package/packages/core/dist/orchestration/contracts.d.ts +1 -1
  630. package/packages/core/dist/orchestration/runtime.d.ts +2 -12
  631. package/packages/core/dist/orchestration/runtime.js +32 -80
  632. package/packages/core/dist/orchestration/runtime.js.map +1 -1
  633. package/packages/core/dist/registries/agent-capability-catalog.d.ts +2 -5
  634. package/packages/core/dist/registries/agent-capability-catalog.js +27 -69
  635. package/packages/core/dist/registries/agent-capability-catalog.js.map +1 -1
  636. package/packages/core/dist/registries/agent-registry.js +118 -34
  637. package/packages/core/dist/registries/agent-registry.js.map +1 -1
  638. package/packages/core/dist/registries/agent-runtime-static.js +1 -1
  639. package/packages/core/dist/registries/agent-runtime-static.js.map +1 -1
  640. package/packages/core/dist/registries/capability-sources.js +1 -1
  641. package/packages/core/dist/registries/command-team-runtime.d.ts +1 -1
  642. package/packages/core/dist/registries/command-team-runtime.js +8 -15
  643. package/packages/core/dist/registries/command-team-runtime.js.map +1 -1
  644. package/packages/core/dist/registries/eval-learning-context.js +4 -4
  645. package/packages/core/dist/registries/eval-learning-context.js.map +1 -1
  646. package/packages/core/dist/registries/plan-scout-domains.d.ts +13 -0
  647. package/packages/core/dist/registries/plan-scout-domains.js +76 -0
  648. package/packages/core/dist/registries/plan-scout-domains.js.map +1 -0
  649. package/packages/core/dist/registries/query-status.js +2 -2
  650. package/packages/core/dist/registries/query-status.js.map +1 -1
  651. package/packages/core/dist/registries/skill-capabilities.js +7 -7
  652. package/packages/core/dist/registries/skill-capabilities.js.map +1 -1
  653. package/packages/core/dist/registries/tool-capabilities.js +4 -4
  654. package/packages/core/dist/registries/tool-capabilities.js.map +1 -1
  655. package/packages/core/dist/registries/tool-plugins.js +2 -2
  656. package/packages/core/dist/registries/tool-plugins.js.map +1 -1
  657. package/packages/core/dist/registries/worker-adapters.js +11 -11
  658. package/packages/core/dist/registries/worker-adapters.js.map +1 -1
  659. package/packages/core/dist/registries/workflow-gates.d.ts +1 -1
  660. package/packages/core/dist/registries/workflow-gates.js +21 -21
  661. package/packages/core/dist/registries/workflow-gates.js.map +1 -1
  662. package/packages/core/dist/risk/consumer-diagnostics.js +2 -1
  663. package/packages/core/dist/risk/consumer-diagnostics.js.map +1 -1
  664. package/packages/core/dist/risk/kernel.js +6 -6
  665. package/packages/core/dist/risk/kernel.js.map +1 -1
  666. package/packages/core/dist/risk/legacy-adapters.js +11 -23
  667. package/packages/core/dist/risk/legacy-adapters.js.map +1 -1
  668. package/packages/core/dist/risk/workflow-gates.d.ts +2 -2
  669. package/packages/core/dist/risk/workflow-gates.js +18 -20
  670. package/packages/core/dist/risk/workflow-gates.js.map +1 -1
  671. package/packages/core/dist/router/agent-runtime.d.ts +0 -2
  672. package/packages/core/dist/router/route-projection.js +1 -1
  673. package/packages/core/dist/router/route-projection.js.map +1 -1
  674. package/packages/core/dist/router/routing.js +16 -48
  675. package/packages/core/dist/router/routing.js.map +1 -1
  676. package/packages/core/dist/router/runtime-import.js +11 -1
  677. package/packages/core/dist/router/runtime-import.js.map +1 -1
  678. package/packages/core/dist/router/runtime-validation.js +2 -2
  679. package/packages/core/dist/router/runtime-validation.js.map +1 -1
  680. package/packages/core/dist/router/stage-route-binding.d.ts +2 -2
  681. package/packages/core/dist/router/stage-route-binding.js +20 -28
  682. package/packages/core/dist/router/stage-route-binding.js.map +1 -1
  683. package/packages/core/dist/router.d.ts +0 -1
  684. package/packages/core/dist/router.js +0 -1
  685. package/packages/core/dist/router.js.map +1 -1
  686. package/packages/core/dist/run-state/artifacts.d.ts +6 -6
  687. package/packages/core/dist/run-state/artifacts.js +13 -124
  688. package/packages/core/dist/run-state/artifacts.js.map +1 -1
  689. package/packages/core/dist/run-state/inspect-run.d.ts +2 -0
  690. package/packages/core/dist/run-state/inspect-run.js +5 -7
  691. package/packages/core/dist/run-state/inspect-run.js.map +1 -1
  692. package/packages/core/dist/run-state/model.d.ts +28 -28
  693. package/packages/core/dist/run-state/run-index.d.ts +2 -0
  694. package/packages/core/dist/run-state/run-index.js +3 -1
  695. package/packages/core/dist/run-state/run-index.js.map +1 -1
  696. package/packages/core/dist/run-state/run-state.js +26 -36
  697. package/packages/core/dist/run-state/run-state.js.map +1 -1
  698. package/packages/core/dist/run-state/task-evidence.d.ts +0 -4
  699. package/packages/core/dist/run-state/task-evidence.js +5 -51
  700. package/packages/core/dist/run-state/task-evidence.js.map +1 -1
  701. package/packages/core/dist/run-state.d.ts +0 -1
  702. package/packages/core/dist/run-state.js +0 -1
  703. package/packages/core/dist/run-state.js.map +1 -1
  704. package/packages/core/dist/runtime-analysis/build.js +1 -1
  705. package/packages/core/dist/runtime-analysis/build.js.map +1 -1
  706. package/packages/core/dist/runtime-analysis/findings.js +5 -5
  707. package/packages/core/dist/runtime-analysis/findings.js.map +1 -1
  708. package/packages/core/dist/runtime-paths.js +1 -1
  709. package/packages/core/dist/runtime-paths.js.map +1 -1
  710. package/packages/core/dist/runtime-projection-p0.d.ts +2 -2
  711. package/packages/core/dist/runtime-projection-p0.js +11 -0
  712. package/packages/core/dist/runtime-projection-p0.js.map +1 -1
  713. package/packages/core/dist/sdd-docs/artifact-depth.d.ts +14 -0
  714. package/packages/core/dist/sdd-docs/artifact-depth.js +179 -0
  715. package/packages/core/dist/sdd-docs/artifact-depth.js.map +1 -0
  716. package/packages/core/dist/sdd-docs/document-hashes.d.ts +0 -2
  717. package/packages/core/dist/sdd-docs/document-hashes.js +10 -97
  718. package/packages/core/dist/sdd-docs/document-hashes.js.map +1 -1
  719. package/packages/core/dist/sdd-docs/run-binding.d.ts +1 -1
  720. package/packages/core/dist/sdd-docs/run-binding.js +6 -8
  721. package/packages/core/dist/sdd-docs/run-binding.js.map +1 -1
  722. package/packages/core/dist/sdd-docs/task-parser.d.ts +5 -2
  723. package/packages/core/dist/sdd-docs/task-parser.js +85 -68
  724. package/packages/core/dist/sdd-docs/task-parser.js.map +1 -1
  725. package/packages/core/dist/sdd-docs/task-rendering.js +2 -2
  726. package/packages/core/dist/sdd-docs/task-rendering.js.map +1 -1
  727. package/packages/core/dist/spec-entry.js +40 -0
  728. package/packages/core/dist/spec-entry.js.map +1 -0
  729. package/packages/core/dist/spec-manager-contracts.d.ts +12 -0
  730. package/packages/core/dist/spec-manager-contracts.js +2 -0
  731. package/packages/core/dist/spec-manager-contracts.js.map +1 -0
  732. package/packages/core/dist/stage-artifacts.d.ts +2 -2
  733. package/packages/core/dist/stage-artifacts.js +19 -26
  734. package/packages/core/dist/stage-artifacts.js.map +1 -1
  735. package/packages/core/dist/stage-collaboration-contracts.d.ts +1 -1
  736. package/packages/core/dist/stage-collaboration-contracts.js +3 -6
  737. package/packages/core/dist/stage-collaboration-contracts.js.map +1 -1
  738. package/packages/core/dist/stage-collaboration.d.ts +111 -263
  739. package/packages/core/dist/stage-collaboration.js +1272 -1124
  740. package/packages/core/dist/stage-collaboration.js.map +1 -1
  741. package/packages/core/dist/stage-runtime/runtime.js +5 -5
  742. package/packages/core/dist/stage-runtime/runtime.js.map +1 -1
  743. package/packages/core/dist/status/project-status.d.ts +1 -44
  744. package/packages/core/dist/status/project-status.js +47 -170
  745. package/packages/core/dist/status/project-status.js.map +1 -1
  746. package/packages/core/dist/storage/runtime-store.js +73 -73
  747. package/packages/core/dist/subagents/contracts.d.ts +1 -1
  748. package/packages/core/dist/subagents/runtime.js +7 -7
  749. package/packages/core/dist/subagents/runtime.js.map +1 -1
  750. package/packages/core/dist/sync-back/apply.d.ts +1 -0
  751. package/packages/core/dist/sync-back/apply.js +2 -0
  752. package/packages/core/dist/sync-back/apply.js.map +1 -0
  753. package/packages/core/dist/sync-back/inspect.d.ts +1 -0
  754. package/packages/core/dist/sync-back/inspect.js +2 -0
  755. package/packages/core/dist/sync-back/inspect.js.map +1 -0
  756. package/packages/core/dist/sync-back.d.ts +1 -0
  757. package/packages/core/dist/sync-back.js +2 -0
  758. package/packages/core/dist/sync-back.js.map +1 -0
  759. package/packages/core/dist/task-execution-contract.d.ts +167 -0
  760. package/packages/core/dist/task-execution-contract.js +377 -0
  761. package/packages/core/dist/task-execution-contract.js.map +1 -0
  762. package/packages/core/dist/test-support/fixtures.js +329 -314
  763. package/packages/core/dist/test-support/fixtures.js.map +1 -1
  764. package/packages/core/dist/test-support/run-state.d.ts +1 -0
  765. package/packages/core/dist/test-support/run-state.js +53 -7
  766. package/packages/core/dist/test-support/run-state.js.map +1 -1
  767. package/packages/core/dist/truth-reconciliation.js +9 -12
  768. package/packages/core/dist/truth-reconciliation.js.map +1 -1
  769. package/packages/core/dist/tsconfig.tsbuildinfo +1 -1
  770. package/packages/core/dist/verification/goal-verify.d.ts +0 -48
  771. package/packages/core/dist/verification/goal-verify.js +1 -520
  772. package/packages/core/dist/verification/goal-verify.js.map +1 -1
  773. package/packages/core/dist/verification/rendering.d.ts +5 -5
  774. package/packages/core/dist/verification/rendering.js +14 -14
  775. package/packages/core/dist/verification/rendering.js.map +1 -1
  776. package/packages/core/dist/verification/single-task-loop.d.ts +1 -0
  777. package/packages/core/dist/verification/single-task-loop.js +111 -159
  778. package/packages/core/dist/verification/single-task-loop.js.map +1 -1
  779. package/packages/core/dist/verification/task-evidence-judgment.d.ts +49 -0
  780. package/packages/core/dist/verification/task-evidence-judgment.js +521 -0
  781. package/packages/core/dist/verification/task-evidence-judgment.js.map +1 -0
  782. package/packages/core/dist/verification/test-runtime.js +21 -21
  783. package/packages/core/dist/verification/test-runtime.js.map +1 -1
  784. package/packages/core/dist/verification/validation-wave.d.ts +0 -18
  785. package/packages/core/dist/verification/validation-wave.js +5 -27
  786. package/packages/core/dist/verification/validation-wave.js.map +1 -1
  787. package/packages/core/dist/verification/verify-contract.js +45 -45
  788. package/packages/core/dist/verification/verify-contract.js.map +1 -1
  789. package/packages/core/dist/verification.d.ts +3 -3
  790. package/packages/core/dist/verification.js +2 -2
  791. package/packages/core/dist/verification.js.map +1 -1
  792. package/packages/core/dist/work-units/contracts.d.ts +1 -1
  793. package/packages/core/dist/workflow-gate/evidence-packet.js +9 -227
  794. package/packages/core/dist/workflow-gate/evidence-packet.js.map +1 -1
  795. package/packages/core/dist/workflow-gate/hard-checks.js +9 -50
  796. package/packages/core/dist/workflow-gate/hard-checks.js.map +1 -1
  797. package/packages/core/dist/workflow-gate/policy.js +4 -42
  798. package/packages/core/dist/workflow-gate/policy.js.map +1 -1
  799. package/packages/core/dist/workflow-gate/types.d.ts +2 -3
  800. package/packages/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
  801. package/packages/core/dist/workflow-state/affected-file-conflicts.js +2 -1
  802. package/packages/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
  803. package/packages/core/dist/workflow-state/dependencies.js +1 -1
  804. package/packages/core/dist/workflow-state/latest-eligible-run.d.ts +1 -0
  805. package/packages/core/dist/workflow-state/latest-eligible-run.js +23 -63
  806. package/packages/core/dist/workflow-state/latest-eligible-run.js.map +1 -1
  807. package/packages/core/dist/workflow-state/resolve.d.ts +2 -2
  808. package/packages/core/dist/workflow-state/resolve.js +43 -65
  809. package/packages/core/dist/workflow-state/resolve.js.map +1 -1
  810. package/packages/core/package.json +5 -2
  811. package/tsconfig.build.json +6 -7
  812. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.test.ts +0 -269
  813. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.test.ts +0 -492
  814. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.test.ts +0 -383
  815. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.test.ts +0 -188
  816. package/packages/cli/dist/commands/lifecycle.d.ts +0 -6
  817. package/packages/cli/dist/commands/lifecycle.js +0 -125
  818. package/packages/cli/dist/commands/lifecycle.js.map +0 -1
  819. package/packages/cli/dist/commands/test.d.ts +0 -6
  820. package/packages/cli/dist/commands/test.js +0 -373
  821. package/packages/cli/dist/commands/test.js.map +0 -1
  822. package/packages/cli/dist/commands/verifies.js +0 -87
  823. package/packages/cli/dist/commands/verifies.js.map +0 -1
  824. package/packages/cli/dist/commands/verify.d.ts +0 -6
  825. package/packages/cli/dist/commands/verify.js +0 -330
  826. 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
+ }