sdd-agent-platform 0.4.1 → 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 (698) hide show
  1. package/README.md +24 -28
  2. package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js +84 -103
  3. package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js.map +1 -1
  4. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.d.ts +10 -6
  5. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js +7 -8
  6. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js.map +1 -1
  7. package/node_modules/@sdd-agent-platform/core/dist/config/project-config.d.ts +3 -1
  8. package/node_modules/@sdd-agent-platform/core/dist/config/project-config.js +7 -3
  9. package/node_modules/@sdd-agent-platform/core/dist/config/project-config.js.map +1 -1
  10. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.d.ts +0 -1
  11. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js +374 -421
  12. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js.map +1 -1
  13. package/node_modules/@sdd-agent-platform/core/dist/context/build-package.d.ts +1 -1
  14. package/node_modules/@sdd-agent-platform/core/dist/context/build-package.js +7 -19
  15. package/node_modules/@sdd-agent-platform/core/dist/context/build-package.js.map +1 -1
  16. package/node_modules/@sdd-agent-platform/core/dist/contracts.d.ts +7 -1
  17. package/node_modules/@sdd-agent-platform/core/dist/contracts.js +6 -0
  18. package/node_modules/@sdd-agent-platform/core/dist/contracts.js.map +1 -1
  19. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/document-chain.js +2 -12
  20. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/document-chain.js.map +1 -1
  21. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js +1 -18
  22. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js.map +1 -1
  23. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.d.ts +1 -1
  24. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js +1 -1
  25. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js.map +1 -1
  26. package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/contracts.d.ts +0 -1
  27. package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/coordination.js +110 -0
  28. package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/coordination.js.map +1 -0
  29. package/node_modules/@sdd-agent-platform/core/dist/execution/host-invocation.js +83 -83
  30. package/node_modules/@sdd-agent-platform/core/dist/instructions.d.ts +1 -1
  31. package/node_modules/@sdd-agent-platform/core/dist/instructions.js +37 -80
  32. package/node_modules/@sdd-agent-platform/core/dist/instructions.js.map +1 -1
  33. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js +58 -68
  34. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js.map +1 -1
  35. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/contracts.d.ts +159 -0
  36. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/contracts.js +7 -0
  37. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/contracts.js.map +1 -0
  38. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/kernel.d.ts +16 -0
  39. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/kernel.js +461 -0
  40. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph/kernel.js.map +1 -0
  41. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph.d.ts +2 -0
  42. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph.js +3 -0
  43. package/node_modules/@sdd-agent-platform/core/dist/lifecycle-graph.js.map +1 -0
  44. package/node_modules/@sdd-agent-platform/core/dist/orchestration/contracts.d.ts +1 -1
  45. package/node_modules/@sdd-agent-platform/core/dist/orchestration/runtime.js +21 -28
  46. package/node_modules/@sdd-agent-platform/core/dist/orchestration/runtime.js.map +1 -1
  47. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js +124 -40
  48. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js.map +1 -1
  49. package/node_modules/@sdd-agent-platform/core/dist/registries/command-team-runtime.d.ts +1 -1
  50. package/node_modules/@sdd-agent-platform/core/dist/registries/command-team-runtime.js +6 -13
  51. package/node_modules/@sdd-agent-platform/core/dist/registries/command-team-runtime.js.map +1 -1
  52. package/node_modules/@sdd-agent-platform/core/dist/registries/plan-scout-domains.d.ts +13 -0
  53. package/node_modules/@sdd-agent-platform/core/dist/registries/plan-scout-domains.js +76 -0
  54. package/node_modules/@sdd-agent-platform/core/dist/registries/plan-scout-domains.js.map +1 -0
  55. package/node_modules/@sdd-agent-platform/core/dist/registries/skill-capabilities.js +7 -7
  56. package/node_modules/@sdd-agent-platform/core/dist/registries/skill-capabilities.js.map +1 -1
  57. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-capabilities.js +6 -6
  58. package/node_modules/@sdd-agent-platform/core/dist/registries/tool-capabilities.js.map +1 -1
  59. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.d.ts +1 -1
  60. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js +18 -18
  61. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js.map +1 -1
  62. package/node_modules/@sdd-agent-platform/core/dist/risk/consumer-diagnostics.js +2 -1
  63. package/node_modules/@sdd-agent-platform/core/dist/risk/consumer-diagnostics.js.map +1 -1
  64. package/node_modules/@sdd-agent-platform/core/dist/risk/contracts.d.ts +2 -2
  65. package/node_modules/@sdd-agent-platform/core/dist/risk/kernel.js +7 -7
  66. package/node_modules/@sdd-agent-platform/core/dist/risk/kernel.js.map +1 -1
  67. package/node_modules/@sdd-agent-platform/core/dist/risk/legacy-adapters.js +12 -27
  68. package/node_modules/@sdd-agent-platform/core/dist/risk/legacy-adapters.js.map +1 -1
  69. package/node_modules/@sdd-agent-platform/core/dist/risk/workflow-gates.js +6 -6
  70. package/node_modules/@sdd-agent-platform/core/dist/risk/workflow-gates.js.map +1 -1
  71. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime-config.js +1 -1
  72. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime-config.js.map +1 -1
  73. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js +2 -4
  74. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js.map +1 -1
  75. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-import.d.ts +28 -0
  76. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-import.js +383 -0
  77. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-import.js.map +1 -0
  78. package/node_modules/@sdd-agent-platform/core/dist/router/stage-route-binding.d.ts +37 -0
  79. package/node_modules/@sdd-agent-platform/core/dist/router/stage-route-binding.js +227 -0
  80. package/node_modules/@sdd-agent-platform/core/dist/router/stage-route-binding.js.map +1 -0
  81. package/node_modules/@sdd-agent-platform/core/dist/router.d.ts +1 -0
  82. package/node_modules/@sdd-agent-platform/core/dist/router.js +1 -0
  83. package/node_modules/@sdd-agent-platform/core/dist/router.js.map +1 -1
  84. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.d.ts +16 -0
  85. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js +6 -0
  86. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js.map +1 -1
  87. package/node_modules/@sdd-agent-platform/core/dist/run-state/model.d.ts +20 -0
  88. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js +7 -7
  89. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js.map +1 -1
  90. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.d.ts +1 -2
  91. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js +2 -9
  92. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js.map +1 -1
  93. package/node_modules/@sdd-agent-platform/core/dist/run-state/timing.d.ts +8 -0
  94. package/node_modules/@sdd-agent-platform/core/dist/run-state/timing.js +131 -0
  95. package/node_modules/@sdd-agent-platform/core/dist/run-state/timing.js.map +1 -0
  96. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/build.js +1 -4
  97. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/build.js.map +1 -1
  98. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/findings.js +0 -39
  99. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/findings.js.map +1 -1
  100. package/node_modules/@sdd-agent-platform/core/dist/runtime-analysis/model.d.ts +1 -17
  101. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.d.ts +10 -0
  102. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js +65 -0
  103. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js.map +1 -1
  104. package/node_modules/@sdd-agent-platform/core/dist/runtime-projection-p0.d.ts +64 -0
  105. package/node_modules/@sdd-agent-platform/core/dist/runtime-projection-p0.js +211 -0
  106. package/node_modules/@sdd-agent-platform/core/dist/runtime-projection-p0.js.map +1 -0
  107. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/artifact-depth.d.ts +14 -0
  108. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/artifact-depth.js +179 -0
  109. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/artifact-depth.js.map +1 -0
  110. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.d.ts +5 -1
  111. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js +60 -22
  112. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js.map +1 -1
  113. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-rendering.js +2 -2
  114. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-rendering.js.map +1 -1
  115. package/node_modules/@sdd-agent-platform/core/dist/spec-entry.js +40 -0
  116. package/node_modules/@sdd-agent-platform/core/dist/spec-entry.js.map +1 -0
  117. package/node_modules/@sdd-agent-platform/core/dist/spec-manager-contracts.d.ts +12 -0
  118. package/node_modules/@sdd-agent-platform/core/dist/spec-manager-contracts.js +2 -0
  119. package/node_modules/@sdd-agent-platform/core/dist/spec-manager-contracts.js.map +1 -0
  120. package/node_modules/@sdd-agent-platform/core/dist/stage-artifacts.d.ts +55 -0
  121. package/node_modules/@sdd-agent-platform/core/dist/stage-artifacts.js +315 -0
  122. package/node_modules/@sdd-agent-platform/core/dist/stage-artifacts.js.map +1 -0
  123. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration-contracts.d.ts +55 -0
  124. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration-contracts.js +238 -0
  125. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration-contracts.js.map +1 -0
  126. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration.d.ts +736 -0
  127. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration.js +4018 -0
  128. package/node_modules/@sdd-agent-platform/core/dist/stage-collaboration.js.map +1 -0
  129. package/node_modules/@sdd-agent-platform/core/dist/stage-runtime/runtime.js +8 -1
  130. package/node_modules/@sdd-agent-platform/core/dist/stage-runtime/runtime.js.map +1 -1
  131. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js +25 -1
  132. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js.map +1 -1
  133. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.d.ts +170 -18
  134. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js +597 -85
  135. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js.map +1 -1
  136. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.d.ts +1 -17
  137. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js +1 -242
  138. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js.map +1 -1
  139. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.d.ts +1 -110
  140. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js +1 -496
  141. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js.map +1 -1
  142. package/node_modules/@sdd-agent-platform/core/dist/sync-back.d.ts +1 -2
  143. package/node_modules/@sdd-agent-platform/core/dist/sync-back.js +1 -2
  144. package/node_modules/@sdd-agent-platform/core/dist/sync-back.js.map +1 -1
  145. package/node_modules/@sdd-agent-platform/core/dist/task-execution-contract.d.ts +167 -0
  146. package/node_modules/@sdd-agent-platform/core/dist/task-execution-contract.js +377 -0
  147. package/node_modules/@sdd-agent-platform/core/dist/task-execution-contract.js.map +1 -0
  148. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js +329 -314
  149. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js.map +1 -1
  150. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.d.ts +1 -0
  151. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js +31 -0
  152. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js.map +1 -1
  153. package/node_modules/@sdd-agent-platform/core/dist/truth-reconciliation.d.ts +44 -0
  154. package/node_modules/@sdd-agent-platform/core/dist/truth-reconciliation.js +135 -0
  155. package/node_modules/@sdd-agent-platform/core/dist/truth-reconciliation.js.map +1 -0
  156. package/node_modules/@sdd-agent-platform/core/dist/tsconfig.tsbuildinfo +1 -1
  157. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.d.ts +0 -49
  158. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js +1 -545
  159. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js.map +1 -1
  160. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.d.ts +5 -7
  161. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js +15 -55
  162. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js.map +1 -1
  163. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js +1 -40
  164. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js.map +1 -1
  165. package/node_modules/@sdd-agent-platform/core/dist/verification/task-evidence-judgment.d.ts +49 -0
  166. package/node_modules/@sdd-agent-platform/core/dist/verification/task-evidence-judgment.js +521 -0
  167. package/node_modules/@sdd-agent-platform/core/dist/verification/task-evidence-judgment.js.map +1 -0
  168. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.d.ts +12 -2
  169. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js +247 -112
  170. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js.map +1 -1
  171. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-cache.d.ts +26 -0
  172. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-cache.js +73 -0
  173. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-cache.js.map +1 -0
  174. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.d.ts +1 -1
  175. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js +49 -72
  176. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js.map +1 -1
  177. package/node_modules/@sdd-agent-platform/core/dist/verification.d.ts +3 -3
  178. package/node_modules/@sdd-agent-platform/core/dist/verification.js +2 -2
  179. package/node_modules/@sdd-agent-platform/core/dist/verification.js.map +1 -1
  180. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js +2 -7
  181. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js.map +1 -1
  182. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js +0 -7
  183. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js.map +1 -1
  184. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js +2 -4
  185. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js.map +1 -1
  186. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.d.ts +3 -5
  187. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js +30 -4
  188. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js.map +1 -1
  189. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/migration-recovery.d.ts +40 -0
  190. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/migration-recovery.js +110 -0
  191. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/migration-recovery.js.map +1 -0
  192. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/repair-contract.d.ts +12 -0
  193. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/repair-contract.js +63 -0
  194. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/repair-contract.js.map +1 -0
  195. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve-task-run.d.ts +21 -0
  196. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve-task-run.js +95 -0
  197. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve-task-run.js.map +1 -0
  198. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.d.ts +55 -5
  199. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js +518 -36
  200. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js.map +1 -1
  201. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/runtime-projections.d.ts +228 -0
  202. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/runtime-projections.js +452 -0
  203. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/runtime-projections.js.map +1 -0
  204. package/node_modules/@sdd-agent-platform/core/package.json +6 -3
  205. package/node_modules/@sdd-agent-platform/core/src/ai-tools.test.ts +238 -137
  206. package/node_modules/@sdd-agent-platform/core/src/ai-tools.ts +84 -103
  207. package/node_modules/@sdd-agent-platform/core/src/artifacts/ingestion.test.ts +189 -189
  208. package/node_modules/@sdd-agent-platform/core/src/artifacts/ingestion.ts +222 -222
  209. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-evidence.test.ts +28 -28
  210. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-evidence.ts +302 -302
  211. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-result.test.ts +181 -181
  212. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-result.ts +231 -231
  213. package/node_modules/@sdd-agent-platform/core/src/artifacts/templates.ts +99 -99
  214. package/node_modules/@sdd-agent-platform/core/src/artifacts.ts +4 -4
  215. package/node_modules/@sdd-agent-platform/core/src/coding-facts/contracts.ts +79 -79
  216. package/node_modules/@sdd-agent-platform/core/src/coding-facts.ts +1 -1
  217. package/node_modules/@sdd-agent-platform/core/src/config/init-project.test.ts +314 -306
  218. package/node_modules/@sdd-agent-platform/core/src/config/init-project.ts +128 -120
  219. package/node_modules/@sdd-agent-platform/core/src/config/project-config.ts +265 -259
  220. package/node_modules/@sdd-agent-platform/core/src/config/project-detection.ts +147 -147
  221. package/node_modules/@sdd-agent-platform/core/src/config/starter-documents.ts +400 -445
  222. package/node_modules/@sdd-agent-platform/core/src/context/budget.ts +30 -30
  223. package/node_modules/@sdd-agent-platform/core/src/context/build-package.ts +305 -317
  224. package/node_modules/@sdd-agent-platform/core/src/context/command-summary.ts +45 -45
  225. package/node_modules/@sdd-agent-platform/core/src/context/context-build.test.ts +188 -188
  226. package/node_modules/@sdd-agent-platform/core/src/context/evidence-summary.ts +144 -144
  227. package/node_modules/@sdd-agent-platform/core/src/context/log-worker.ts +48 -48
  228. package/node_modules/@sdd-agent-platform/core/src/context/source-refs.ts +41 -41
  229. package/node_modules/@sdd-agent-platform/core/src/context-offload/contracts.ts +47 -47
  230. package/node_modules/@sdd-agent-platform/core/src/context-offload/runtime.test.ts +71 -71
  231. package/node_modules/@sdd-agent-platform/core/src/context-offload/runtime.ts +178 -178
  232. package/node_modules/@sdd-agent-platform/core/src/context-offload.ts +2 -2
  233. package/node_modules/@sdd-agent-platform/core/src/context.ts +6 -6
  234. package/node_modules/@sdd-agent-platform/core/src/contracts/issues.ts +13 -13
  235. package/node_modules/@sdd-agent-platform/core/src/contracts.test.ts +9 -9
  236. package/node_modules/@sdd-agent-platform/core/src/contracts.ts +121 -115
  237. package/node_modules/@sdd-agent-platform/core/src/delegation/delegation.test.ts +183 -183
  238. package/node_modules/@sdd-agent-platform/core/src/delegation/model.ts +23 -23
  239. package/node_modules/@sdd-agent-platform/core/src/delegation/queue.ts +58 -58
  240. package/node_modules/@sdd-agent-platform/core/src/delegation/run-state.ts +14 -14
  241. package/node_modules/@sdd-agent-platform/core/src/delegation/state-machine.ts +90 -90
  242. package/node_modules/@sdd-agent-platform/core/src/delegation/validation.ts +124 -124
  243. package/node_modules/@sdd-agent-platform/core/src/delegation.ts +26 -26
  244. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/ai-entries.ts +28 -28
  245. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/document-chain.ts +104 -112
  246. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/local-run-index.ts +27 -27
  247. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/project.ts +84 -84
  248. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/registries.ts +252 -252
  249. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-evidence.ts +330 -330
  250. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-records.ts +79 -79
  251. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-trust.ts +128 -128
  252. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/runtime-contracts.ts +300 -300
  253. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.test.ts +627 -657
  254. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.ts +301 -318
  255. package/node_modules/@sdd-agent-platform/core/src/doctor/model.ts +13 -13
  256. package/node_modules/@sdd-agent-platform/core/src/doctor/summary.ts +11 -11
  257. package/node_modules/@sdd-agent-platform/core/src/doctor.ts +2 -2
  258. package/node_modules/@sdd-agent-platform/core/src/evidence/lookup.ts +80 -80
  259. package/node_modules/@sdd-agent-platform/core/src/evidence-runtime/contracts.ts +48 -49
  260. package/node_modules/@sdd-agent-platform/core/src/evidence-runtime.ts +1 -1
  261. package/node_modules/@sdd-agent-platform/core/src/execution/agent-execution-records.ts +195 -195
  262. package/node_modules/@sdd-agent-platform/core/src/execution/background-executor.test.ts +187 -187
  263. package/node_modules/@sdd-agent-platform/core/src/execution/background-executor.ts +305 -305
  264. package/node_modules/@sdd-agent-platform/core/src/execution/foreground-subagents.test.ts +97 -97
  265. package/node_modules/@sdd-agent-platform/core/src/execution/foreground-subagents.ts +453 -453
  266. package/node_modules/@sdd-agent-platform/core/src/execution/host-invocation.ts +225 -225
  267. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.test.ts +132 -132
  268. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.ts +436 -436
  269. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.test.ts +102 -102
  270. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.ts +271 -271
  271. package/node_modules/@sdd-agent-platform/core/src/execution/wave-executor.test.ts +111 -111
  272. package/node_modules/@sdd-agent-platform/core/src/execution/wave-executor.ts +231 -231
  273. package/node_modules/@sdd-agent-platform/core/src/execution.ts +5 -5
  274. package/node_modules/@sdd-agent-platform/core/src/governance/policy.test.ts +57 -57
  275. package/node_modules/@sdd-agent-platform/core/src/governance/policy.ts +175 -175
  276. package/node_modules/@sdd-agent-platform/core/src/governance.ts +1 -1
  277. package/node_modules/@sdd-agent-platform/core/src/instructions.test.ts +80 -49
  278. package/node_modules/@sdd-agent-platform/core/src/instructions.ts +38 -81
  279. package/node_modules/@sdd-agent-platform/core/src/lifecycle/decision-gate.test.ts +174 -174
  280. package/node_modules/@sdd-agent-platform/core/src/lifecycle/decision-gate.ts +373 -373
  281. package/node_modules/@sdd-agent-platform/core/src/lifecycle/rendering.ts +29 -29
  282. package/node_modules/@sdd-agent-platform/core/src/lifecycle/risk-signals.ts +146 -146
  283. package/node_modules/@sdd-agent-platform/core/src/lifecycle/ship.test.ts +47 -0
  284. package/node_modules/@sdd-agent-platform/core/src/lifecycle/ship.ts +255 -263
  285. package/node_modules/@sdd-agent-platform/core/src/lifecycle-graph/contracts.ts +179 -0
  286. package/node_modules/@sdd-agent-platform/core/src/lifecycle-graph/kernel.ts +522 -0
  287. package/node_modules/@sdd-agent-platform/core/src/lifecycle-graph.ts +2 -0
  288. package/node_modules/@sdd-agent-platform/core/src/lifecycle.ts +4 -4
  289. package/node_modules/@sdd-agent-platform/core/src/orchestration/contracts.ts +50 -50
  290. package/node_modules/@sdd-agent-platform/core/src/orchestration/index.ts +2 -2
  291. package/node_modules/@sdd-agent-platform/core/src/orchestration/runtime.ts +331 -342
  292. package/node_modules/@sdd-agent-platform/core/src/path-safety.test.ts +22 -22
  293. package/node_modules/@sdd-agent-platform/core/src/phase8-contracts.test.ts +243 -243
  294. package/node_modules/@sdd-agent-platform/core/src/phase8-projection-compat.test.ts +152 -153
  295. package/node_modules/@sdd-agent-platform/core/src/phase8-risk-kernel.test.ts +277 -277
  296. package/node_modules/@sdd-agent-platform/core/src/phase9-lifecycle-graph.test.ts +103 -0
  297. package/node_modules/@sdd-agent-platform/core/src/planning/task-graph.test.ts +88 -88
  298. package/node_modules/@sdd-agent-platform/core/src/planning/task-graph.ts +222 -222
  299. package/node_modules/@sdd-agent-platform/core/src/planning/wave-plan.test.ts +79 -79
  300. package/node_modules/@sdd-agent-platform/core/src/planning/wave-plan.ts +160 -160
  301. package/node_modules/@sdd-agent-platform/core/src/planning.ts +2 -2
  302. package/node_modules/@sdd-agent-platform/core/src/registries/agent-capability-catalog.ts +426 -426
  303. package/node_modules/@sdd-agent-platform/core/src/registries/agent-registry.ts +230 -146
  304. package/node_modules/@sdd-agent-platform/core/src/registries/agent-runtime-static.ts +142 -142
  305. package/node_modules/@sdd-agent-platform/core/src/registries/capability-sources.ts +253 -253
  306. package/node_modules/@sdd-agent-platform/core/src/registries/command-team-runtime.ts +302 -309
  307. package/node_modules/@sdd-agent-platform/core/src/registries/eval-learning-context.ts +246 -246
  308. package/node_modules/@sdd-agent-platform/core/src/registries/plan-scout-domains.ts +89 -0
  309. package/node_modules/@sdd-agent-platform/core/src/registries/query-status.ts +119 -119
  310. package/node_modules/@sdd-agent-platform/core/src/registries/registries.test.ts +454 -429
  311. package/node_modules/@sdd-agent-platform/core/src/registries/skill-capabilities.ts +37 -37
  312. package/node_modules/@sdd-agent-platform/core/src/registries/tool-capabilities.ts +135 -135
  313. package/node_modules/@sdd-agent-platform/core/src/registries/tool-plugins.ts +132 -132
  314. package/node_modules/@sdd-agent-platform/core/src/registries/worker-adapters.ts +144 -144
  315. package/node_modules/@sdd-agent-platform/core/src/registries/workflow-gates.ts +111 -111
  316. package/node_modules/@sdd-agent-platform/core/src/registries.ts +42 -42
  317. package/node_modules/@sdd-agent-platform/core/src/risk/consumer-diagnostics.ts +98 -97
  318. package/node_modules/@sdd-agent-platform/core/src/risk/contracts.ts +63 -63
  319. package/node_modules/@sdd-agent-platform/core/src/risk/kernel.ts +233 -233
  320. package/node_modules/@sdd-agent-platform/core/src/risk/legacy-adapters.ts +251 -266
  321. package/node_modules/@sdd-agent-platform/core/src/risk/workflow-gates.ts +203 -203
  322. package/node_modules/@sdd-agent-platform/core/src/risk.ts +5 -5
  323. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime-config.ts +327 -327
  324. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime.ts +388 -388
  325. package/node_modules/@sdd-agent-platform/core/src/router/profile-resolution.ts +154 -154
  326. package/node_modules/@sdd-agent-platform/core/src/router/risk-policy.ts +33 -33
  327. package/node_modules/@sdd-agent-platform/core/src/router/route-cache.ts +100 -100
  328. package/node_modules/@sdd-agent-platform/core/src/router/route-projection.ts +356 -356
  329. package/node_modules/@sdd-agent-platform/core/src/router/route-sdd-task.test.ts +428 -428
  330. package/node_modules/@sdd-agent-platform/core/src/router/route-sdd-task.ts +2 -2
  331. package/node_modules/@sdd-agent-platform/core/src/router/routing-rules.ts +73 -73
  332. package/node_modules/@sdd-agent-platform/core/src/router/routing.ts +189 -191
  333. package/node_modules/@sdd-agent-platform/core/src/router/runtime-import.ts +464 -0
  334. package/node_modules/@sdd-agent-platform/core/src/router/runtime-inspection.ts +124 -124
  335. package/node_modules/@sdd-agent-platform/core/src/router/runtime-registry.ts +123 -123
  336. package/node_modules/@sdd-agent-platform/core/src/router/runtime-validation.ts +277 -277
  337. package/node_modules/@sdd-agent-platform/core/src/router/stage-route-binding.ts +273 -0
  338. package/node_modules/@sdd-agent-platform/core/src/router/team-mode.ts +170 -170
  339. package/node_modules/@sdd-agent-platform/core/src/router.ts +5 -4
  340. package/node_modules/@sdd-agent-platform/core/src/run-state/artifacts.ts +126 -118
  341. package/node_modules/@sdd-agent-platform/core/src/run-state/events.ts +27 -27
  342. package/node_modules/@sdd-agent-platform/core/src/run-state/inspect-run.ts +172 -172
  343. package/node_modules/@sdd-agent-platform/core/src/run-state/invocation-ledger.ts +109 -109
  344. package/node_modules/@sdd-agent-platform/core/src/run-state/model.ts +252 -230
  345. package/node_modules/@sdd-agent-platform/core/src/run-state/run-index.test.ts +52 -52
  346. package/node_modules/@sdd-agent-platform/core/src/run-state/run-index.ts +356 -356
  347. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.test.ts +70 -70
  348. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.ts +406 -406
  349. package/node_modules/@sdd-agent-platform/core/src/run-state/task-evidence.ts +198 -206
  350. package/node_modules/@sdd-agent-platform/core/src/run-state/timing.ts +146 -0
  351. package/node_modules/@sdd-agent-platform/core/src/run-state.ts +8 -8
  352. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis/build.ts +60 -63
  353. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis/findings.ts +257 -296
  354. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis/model.ts +140 -152
  355. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis.test.ts +66 -68
  356. package/node_modules/@sdd-agent-platform/core/src/runtime-analysis.ts +2 -2
  357. package/node_modules/@sdd-agent-platform/core/src/runtime-paths.ts +253 -176
  358. package/node_modules/@sdd-agent-platform/core/src/runtime-projection-p0.test.ts +101 -0
  359. package/node_modules/@sdd-agent-platform/core/src/runtime-projection-p0.ts +314 -0
  360. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/artifact-depth.test.ts +380 -0
  361. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/artifact-depth.ts +207 -0
  362. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/context.ts +111 -111
  363. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/document-hashes.ts +207 -207
  364. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/run-binding.ts +95 -95
  365. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-inspection.ts +39 -39
  366. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.test.ts +467 -401
  367. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.ts +738 -694
  368. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-rendering.ts +81 -81
  369. package/node_modules/@sdd-agent-platform/core/src/sdd-docs.ts +5 -5
  370. package/node_modules/@sdd-agent-platform/core/src/spec-manager-contracts.ts +13 -0
  371. package/node_modules/@sdd-agent-platform/core/src/stage-artifacts.ts +435 -0
  372. package/node_modules/@sdd-agent-platform/core/src/stage-collaboration-contracts.ts +316 -0
  373. package/node_modules/@sdd-agent-platform/core/src/stage-collaboration.test.ts +2964 -0
  374. package/node_modules/@sdd-agent-platform/core/src/stage-collaboration.ts +5856 -0
  375. package/node_modules/@sdd-agent-platform/core/src/stage-runtime/contracts.ts +40 -40
  376. package/node_modules/@sdd-agent-platform/core/src/stage-runtime/runtime.test.ts +209 -209
  377. package/node_modules/@sdd-agent-platform/core/src/stage-runtime/runtime.ts +360 -352
  378. package/node_modules/@sdd-agent-platform/core/src/stage-runtime.ts +2 -2
  379. package/node_modules/@sdd-agent-platform/core/src/status/project-status.test.ts +288 -288
  380. package/node_modules/@sdd-agent-platform/core/src/status/project-status.ts +651 -625
  381. package/node_modules/@sdd-agent-platform/core/src/status.ts +2 -2
  382. package/node_modules/@sdd-agent-platform/core/src/storage/json-io.ts +10 -10
  383. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.test.ts +489 -489
  384. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.ts +1981 -1175
  385. package/node_modules/@sdd-agent-platform/core/src/subagents/contracts.ts +45 -45
  386. package/node_modules/@sdd-agent-platform/core/src/subagents/runtime.test.ts +232 -232
  387. package/node_modules/@sdd-agent-platform/core/src/subagents/runtime.ts +307 -307
  388. package/node_modules/@sdd-agent-platform/core/src/subagents.ts +2 -2
  389. package/node_modules/@sdd-agent-platform/core/src/task-execution-contract.test.ts +141 -0
  390. package/node_modules/@sdd-agent-platform/core/src/task-execution-contract.ts +566 -0
  391. package/node_modules/@sdd-agent-platform/core/src/task-risk-profile.ts +193 -193
  392. package/node_modules/@sdd-agent-platform/core/src/test-support/fixtures.ts +413 -398
  393. package/node_modules/@sdd-agent-platform/core/src/test-support/run-state.ts +102 -70
  394. package/node_modules/@sdd-agent-platform/core/src/test-support.ts +2 -2
  395. package/node_modules/@sdd-agent-platform/core/src/truth-reconciliation.test.ts +72 -0
  396. package/node_modules/@sdd-agent-platform/core/src/truth-reconciliation.ts +174 -0
  397. package/node_modules/@sdd-agent-platform/core/src/verification/rendering.ts +137 -181
  398. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.test.ts +77 -77
  399. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.ts +77 -77
  400. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.ts +455 -494
  401. package/node_modules/@sdd-agent-platform/core/src/verification/{goal-verify.test.ts → task-evidence-judgment.test.ts} +261 -335
  402. package/node_modules/@sdd-agent-platform/core/src/verification/{goal-verify.ts → task-evidence-judgment.ts} +619 -648
  403. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.ts +1190 -1032
  404. package/node_modules/@sdd-agent-platform/core/src/verification/validation-cache.ts +106 -0
  405. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.ts +513 -513
  406. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.ts +334 -358
  407. package/node_modules/@sdd-agent-platform/core/src/verification.ts +8 -8
  408. package/node_modules/@sdd-agent-platform/core/src/work-units/contracts.ts +26 -26
  409. package/node_modules/@sdd-agent-platform/core/src/work-units/runtime.test.ts +88 -88
  410. package/node_modules/@sdd-agent-platform/core/src/work-units/runtime.ts +112 -112
  411. package/node_modules/@sdd-agent-platform/core/src/work-units.ts +2 -2
  412. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/evidence-packet.ts +190 -196
  413. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.test.ts +169 -171
  414. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.ts +136 -143
  415. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.test.ts +135 -137
  416. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.ts +153 -155
  417. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/types.ts +111 -114
  418. package/node_modules/@sdd-agent-platform/core/src/workflow-state/affected-file-conflicts.ts +95 -95
  419. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.test.ts +32 -32
  420. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.ts +114 -114
  421. package/node_modules/@sdd-agent-platform/core/src/workflow-state/latest-eligible-run.ts +184 -156
  422. package/node_modules/@sdd-agent-platform/core/src/workflow-state/migration-recovery.ts +158 -0
  423. package/node_modules/@sdd-agent-platform/core/src/workflow-state/repair-contract.ts +77 -0
  424. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve-task-run.ts +114 -0
  425. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.test.ts +970 -464
  426. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.ts +967 -363
  427. package/node_modules/@sdd-agent-platform/core/src/workflow-state/runtime-projections.ts +712 -0
  428. package/node_modules/@sdd-agent-platform/core/src/workflow-state.ts +2 -2
  429. package/node_modules/@sdd-agent-platform/core/src/worktree/isolation.ts +130 -130
  430. package/node_modules/@sdd-agent-platform/core/src/worktree/lifecycle.ts +269 -269
  431. package/node_modules/@sdd-agent-platform/core/src/worktree/worktree.test.ts +150 -150
  432. package/node_modules/@sdd-agent-platform/core/src/worktree.ts +2 -2
  433. package/node_modules/@sdd-agent-platform/core/tsconfig.json +15 -15
  434. package/package.json +2 -2
  435. package/packages/cli/dist/args.js +1 -1
  436. package/packages/cli/dist/args.js.map +1 -1
  437. package/packages/cli/dist/commands/context.js +1 -1
  438. package/packages/cli/dist/commands/context.js.map +1 -1
  439. package/packages/cli/dist/commands/evidence.js.map +1 -0
  440. package/packages/cli/dist/commands/execution.js +126 -0
  441. package/packages/cli/dist/commands/execution.js.map +1 -1
  442. package/packages/cli/dist/commands/instructions.d.ts +1 -1
  443. package/packages/cli/dist/commands/instructions.js +15 -1
  444. package/packages/cli/dist/commands/instructions.js.map +1 -1
  445. package/packages/cli/dist/commands/registry/runtime.js +70 -1
  446. package/packages/cli/dist/commands/registry/runtime.js.map +1 -1
  447. package/packages/cli/dist/commands/run.js +12 -1
  448. package/packages/cli/dist/commands/run.js.map +1 -1
  449. package/packages/cli/dist/commands/stage-close.d.ts +66 -0
  450. package/packages/cli/dist/commands/stage-close.js +524 -0
  451. package/packages/cli/dist/commands/stage-close.js.map +1 -0
  452. package/packages/cli/dist/commands/status.js +8 -1
  453. package/packages/cli/dist/commands/status.js.map +1 -1
  454. package/packages/cli/dist/commands/tasks.js.map +1 -1
  455. package/packages/cli/dist/dispatch.js +6 -31
  456. package/packages/cli/dist/dispatch.js.map +1 -1
  457. package/packages/cli/dist/help.js +153 -158
  458. package/packages/cli/dist/help.js.map +1 -1
  459. package/packages/cli/dist/renderers/workflow.d.ts +51 -2
  460. package/packages/cli/dist/renderers/workflow.js.map +1 -1
  461. package/packages/cli/dist/skill-import-args.d.ts +10 -0
  462. package/packages/cli/dist/skill-import-args.js +47 -0
  463. package/packages/cli/dist/skill-import-args.js.map +1 -0
  464. package/packages/cli/dist/tsconfig.tsbuildinfo +1 -1
  465. package/packages/cli/package.json +2 -2
  466. package/packages/core/dist/ai-tools.js +84 -103
  467. package/packages/core/dist/ai-tools.js.map +1 -1
  468. package/packages/core/dist/config/init-project.d.ts +10 -6
  469. package/packages/core/dist/config/init-project.js +7 -8
  470. package/packages/core/dist/config/init-project.js.map +1 -1
  471. package/packages/core/dist/config/project-config.d.ts +3 -1
  472. package/packages/core/dist/config/project-config.js +7 -3
  473. package/packages/core/dist/config/project-config.js.map +1 -1
  474. package/packages/core/dist/config/starter-documents.d.ts +0 -1
  475. package/packages/core/dist/config/starter-documents.js +374 -421
  476. package/packages/core/dist/config/starter-documents.js.map +1 -1
  477. package/packages/core/dist/context/build-package.d.ts +1 -1
  478. package/packages/core/dist/context/build-package.js +7 -19
  479. package/packages/core/dist/context/build-package.js.map +1 -1
  480. package/packages/core/dist/contracts.d.ts +7 -1
  481. package/packages/core/dist/contracts.js +6 -0
  482. package/packages/core/dist/contracts.js.map +1 -1
  483. package/packages/core/dist/doctor/checks/document-chain.js +2 -12
  484. package/packages/core/dist/doctor/checks/document-chain.js.map +1 -1
  485. package/packages/core/dist/doctor/doctor.js +1 -18
  486. package/packages/core/dist/doctor/doctor.js.map +1 -1
  487. package/packages/core/dist/evidence/lookup.d.ts +1 -1
  488. package/packages/core/dist/evidence/lookup.js +1 -1
  489. package/packages/core/dist/evidence/lookup.js.map +1 -1
  490. package/packages/core/dist/evidence-runtime/contracts.d.ts +0 -1
  491. package/packages/core/dist/evidence-runtime/coordination.js +110 -0
  492. package/packages/core/dist/evidence-runtime/coordination.js.map +1 -0
  493. package/packages/core/dist/execution/host-invocation.js +83 -83
  494. package/packages/core/dist/instructions.d.ts +1 -1
  495. package/packages/core/dist/instructions.js +37 -80
  496. package/packages/core/dist/instructions.js.map +1 -1
  497. package/packages/core/dist/lifecycle/ship.js +58 -68
  498. package/packages/core/dist/lifecycle/ship.js.map +1 -1
  499. package/packages/core/dist/lifecycle-graph/contracts.d.ts +159 -0
  500. package/packages/core/dist/lifecycle-graph/contracts.js +7 -0
  501. package/packages/core/dist/lifecycle-graph/contracts.js.map +1 -0
  502. package/packages/core/dist/lifecycle-graph/kernel.d.ts +16 -0
  503. package/packages/core/dist/lifecycle-graph/kernel.js +461 -0
  504. package/packages/core/dist/lifecycle-graph/kernel.js.map +1 -0
  505. package/packages/core/dist/lifecycle-graph.d.ts +2 -0
  506. package/packages/core/dist/lifecycle-graph.js +3 -0
  507. package/packages/core/dist/lifecycle-graph.js.map +1 -0
  508. package/packages/core/dist/orchestration/contracts.d.ts +1 -1
  509. package/packages/core/dist/orchestration/runtime.js +21 -28
  510. package/packages/core/dist/orchestration/runtime.js.map +1 -1
  511. package/packages/core/dist/registries/agent-registry.js +124 -40
  512. package/packages/core/dist/registries/agent-registry.js.map +1 -1
  513. package/packages/core/dist/registries/command-team-runtime.d.ts +1 -1
  514. package/packages/core/dist/registries/command-team-runtime.js +6 -13
  515. package/packages/core/dist/registries/command-team-runtime.js.map +1 -1
  516. package/packages/core/dist/registries/plan-scout-domains.d.ts +13 -0
  517. package/packages/core/dist/registries/plan-scout-domains.js +76 -0
  518. package/packages/core/dist/registries/plan-scout-domains.js.map +1 -0
  519. package/packages/core/dist/registries/skill-capabilities.js +7 -7
  520. package/packages/core/dist/registries/skill-capabilities.js.map +1 -1
  521. package/packages/core/dist/registries/tool-capabilities.js +6 -6
  522. package/packages/core/dist/registries/tool-capabilities.js.map +1 -1
  523. package/packages/core/dist/registries/workflow-gates.d.ts +1 -1
  524. package/packages/core/dist/registries/workflow-gates.js +18 -18
  525. package/packages/core/dist/registries/workflow-gates.js.map +1 -1
  526. package/packages/core/dist/risk/consumer-diagnostics.js +2 -1
  527. package/packages/core/dist/risk/consumer-diagnostics.js.map +1 -1
  528. package/packages/core/dist/risk/contracts.d.ts +2 -2
  529. package/packages/core/dist/risk/kernel.js +7 -7
  530. package/packages/core/dist/risk/kernel.js.map +1 -1
  531. package/packages/core/dist/risk/legacy-adapters.js +12 -27
  532. package/packages/core/dist/risk/legacy-adapters.js.map +1 -1
  533. package/packages/core/dist/risk/workflow-gates.js +6 -6
  534. package/packages/core/dist/risk/workflow-gates.js.map +1 -1
  535. package/packages/core/dist/router/agent-runtime-config.js +1 -1
  536. package/packages/core/dist/router/agent-runtime-config.js.map +1 -1
  537. package/packages/core/dist/router/routing.js +2 -4
  538. package/packages/core/dist/router/routing.js.map +1 -1
  539. package/packages/core/dist/router/runtime-import.d.ts +28 -0
  540. package/packages/core/dist/router/runtime-import.js +383 -0
  541. package/packages/core/dist/router/runtime-import.js.map +1 -0
  542. package/packages/core/dist/router/stage-route-binding.d.ts +37 -0
  543. package/packages/core/dist/router/stage-route-binding.js +227 -0
  544. package/packages/core/dist/router/stage-route-binding.js.map +1 -0
  545. package/packages/core/dist/router.d.ts +1 -0
  546. package/packages/core/dist/router.js +1 -0
  547. package/packages/core/dist/router.js.map +1 -1
  548. package/packages/core/dist/run-state/artifacts.d.ts +16 -0
  549. package/packages/core/dist/run-state/artifacts.js +6 -0
  550. package/packages/core/dist/run-state/artifacts.js.map +1 -1
  551. package/packages/core/dist/run-state/model.d.ts +20 -0
  552. package/packages/core/dist/run-state/run-state.js +7 -7
  553. package/packages/core/dist/run-state/run-state.js.map +1 -1
  554. package/packages/core/dist/run-state/task-evidence.d.ts +1 -2
  555. package/packages/core/dist/run-state/task-evidence.js +2 -9
  556. package/packages/core/dist/run-state/task-evidence.js.map +1 -1
  557. package/packages/core/dist/run-state/timing.d.ts +8 -0
  558. package/packages/core/dist/run-state/timing.js +131 -0
  559. package/packages/core/dist/run-state/timing.js.map +1 -0
  560. package/packages/core/dist/runtime-analysis/build.js +1 -4
  561. package/packages/core/dist/runtime-analysis/build.js.map +1 -1
  562. package/packages/core/dist/runtime-analysis/findings.js +0 -39
  563. package/packages/core/dist/runtime-analysis/findings.js.map +1 -1
  564. package/packages/core/dist/runtime-analysis/model.d.ts +1 -17
  565. package/packages/core/dist/runtime-paths.d.ts +10 -0
  566. package/packages/core/dist/runtime-paths.js +65 -0
  567. package/packages/core/dist/runtime-paths.js.map +1 -1
  568. package/packages/core/dist/runtime-projection-p0.d.ts +64 -0
  569. package/packages/core/dist/runtime-projection-p0.js +211 -0
  570. package/packages/core/dist/runtime-projection-p0.js.map +1 -0
  571. package/packages/core/dist/sdd-docs/artifact-depth.d.ts +14 -0
  572. package/packages/core/dist/sdd-docs/artifact-depth.js +179 -0
  573. package/packages/core/dist/sdd-docs/artifact-depth.js.map +1 -0
  574. package/packages/core/dist/sdd-docs/task-parser.d.ts +5 -1
  575. package/packages/core/dist/sdd-docs/task-parser.js +60 -22
  576. package/packages/core/dist/sdd-docs/task-parser.js.map +1 -1
  577. package/packages/core/dist/sdd-docs/task-rendering.js +2 -2
  578. package/packages/core/dist/sdd-docs/task-rendering.js.map +1 -1
  579. package/packages/core/dist/spec-entry.js +40 -0
  580. package/packages/core/dist/spec-entry.js.map +1 -0
  581. package/packages/core/dist/spec-manager-contracts.d.ts +12 -0
  582. package/packages/core/dist/spec-manager-contracts.js +2 -0
  583. package/packages/core/dist/spec-manager-contracts.js.map +1 -0
  584. package/packages/core/dist/stage-artifacts.d.ts +55 -0
  585. package/packages/core/dist/stage-artifacts.js +315 -0
  586. package/packages/core/dist/stage-artifacts.js.map +1 -0
  587. package/packages/core/dist/stage-collaboration-contracts.d.ts +55 -0
  588. package/packages/core/dist/stage-collaboration-contracts.js +238 -0
  589. package/packages/core/dist/stage-collaboration-contracts.js.map +1 -0
  590. package/packages/core/dist/stage-collaboration.d.ts +736 -0
  591. package/packages/core/dist/stage-collaboration.js +4018 -0
  592. package/packages/core/dist/stage-collaboration.js.map +1 -0
  593. package/packages/core/dist/stage-runtime/runtime.js +8 -1
  594. package/packages/core/dist/stage-runtime/runtime.js.map +1 -1
  595. package/packages/core/dist/status/project-status.js +25 -1
  596. package/packages/core/dist/status/project-status.js.map +1 -1
  597. package/packages/core/dist/storage/runtime-store.d.ts +170 -18
  598. package/packages/core/dist/storage/runtime-store.js +597 -85
  599. package/packages/core/dist/storage/runtime-store.js.map +1 -1
  600. package/packages/core/dist/sync-back/apply.d.ts +1 -17
  601. package/packages/core/dist/sync-back/apply.js +1 -242
  602. package/packages/core/dist/sync-back/apply.js.map +1 -1
  603. package/packages/core/dist/sync-back/inspect.d.ts +1 -110
  604. package/packages/core/dist/sync-back/inspect.js +1 -496
  605. package/packages/core/dist/sync-back/inspect.js.map +1 -1
  606. package/packages/core/dist/sync-back.d.ts +1 -2
  607. package/packages/core/dist/sync-back.js +1 -2
  608. package/packages/core/dist/sync-back.js.map +1 -1
  609. package/packages/core/dist/task-execution-contract.d.ts +167 -0
  610. package/packages/core/dist/task-execution-contract.js +377 -0
  611. package/packages/core/dist/task-execution-contract.js.map +1 -0
  612. package/packages/core/dist/test-support/fixtures.js +329 -314
  613. package/packages/core/dist/test-support/fixtures.js.map +1 -1
  614. package/packages/core/dist/test-support/run-state.d.ts +1 -0
  615. package/packages/core/dist/test-support/run-state.js +31 -0
  616. package/packages/core/dist/test-support/run-state.js.map +1 -1
  617. package/packages/core/dist/truth-reconciliation.d.ts +44 -0
  618. package/packages/core/dist/truth-reconciliation.js +135 -0
  619. package/packages/core/dist/truth-reconciliation.js.map +1 -0
  620. package/packages/core/dist/tsconfig.tsbuildinfo +1 -1
  621. package/packages/core/dist/verification/goal-verify.d.ts +0 -49
  622. package/packages/core/dist/verification/goal-verify.js +1 -545
  623. package/packages/core/dist/verification/goal-verify.js.map +1 -1
  624. package/packages/core/dist/verification/rendering.d.ts +5 -7
  625. package/packages/core/dist/verification/rendering.js +15 -55
  626. package/packages/core/dist/verification/rendering.js.map +1 -1
  627. package/packages/core/dist/verification/single-task-loop.js +1 -40
  628. package/packages/core/dist/verification/single-task-loop.js.map +1 -1
  629. package/packages/core/dist/verification/task-evidence-judgment.d.ts +49 -0
  630. package/packages/core/dist/verification/task-evidence-judgment.js +521 -0
  631. package/packages/core/dist/verification/task-evidence-judgment.js.map +1 -0
  632. package/packages/core/dist/verification/test-runtime.d.ts +12 -2
  633. package/packages/core/dist/verification/test-runtime.js +247 -112
  634. package/packages/core/dist/verification/test-runtime.js.map +1 -1
  635. package/packages/core/dist/verification/validation-cache.d.ts +26 -0
  636. package/packages/core/dist/verification/validation-cache.js +73 -0
  637. package/packages/core/dist/verification/validation-cache.js.map +1 -0
  638. package/packages/core/dist/verification/verify-contract.d.ts +1 -1
  639. package/packages/core/dist/verification/verify-contract.js +49 -72
  640. package/packages/core/dist/verification/verify-contract.js.map +1 -1
  641. package/packages/core/dist/verification.d.ts +3 -3
  642. package/packages/core/dist/verification.js +2 -2
  643. package/packages/core/dist/verification.js.map +1 -1
  644. package/packages/core/dist/workflow-gate/evidence-packet.js +2 -7
  645. package/packages/core/dist/workflow-gate/evidence-packet.js.map +1 -1
  646. package/packages/core/dist/workflow-gate/hard-checks.js +0 -7
  647. package/packages/core/dist/workflow-gate/hard-checks.js.map +1 -1
  648. package/packages/core/dist/workflow-gate/policy.js +2 -4
  649. package/packages/core/dist/workflow-gate/policy.js.map +1 -1
  650. package/packages/core/dist/workflow-gate/types.d.ts +3 -5
  651. package/packages/core/dist/workflow-state/latest-eligible-run.js +30 -4
  652. package/packages/core/dist/workflow-state/latest-eligible-run.js.map +1 -1
  653. package/packages/core/dist/workflow-state/migration-recovery.d.ts +40 -0
  654. package/packages/core/dist/workflow-state/migration-recovery.js +110 -0
  655. package/packages/core/dist/workflow-state/migration-recovery.js.map +1 -0
  656. package/packages/core/dist/workflow-state/repair-contract.d.ts +12 -0
  657. package/packages/core/dist/workflow-state/repair-contract.js +63 -0
  658. package/packages/core/dist/workflow-state/repair-contract.js.map +1 -0
  659. package/packages/core/dist/workflow-state/resolve-task-run.d.ts +21 -0
  660. package/packages/core/dist/workflow-state/resolve-task-run.js +95 -0
  661. package/packages/core/dist/workflow-state/resolve-task-run.js.map +1 -0
  662. package/packages/core/dist/workflow-state/resolve.d.ts +55 -5
  663. package/packages/core/dist/workflow-state/resolve.js +518 -36
  664. package/packages/core/dist/workflow-state/resolve.js.map +1 -1
  665. package/packages/core/dist/workflow-state/runtime-projections.d.ts +228 -0
  666. package/packages/core/dist/workflow-state/runtime-projections.js +452 -0
  667. package/packages/core/dist/workflow-state/runtime-projections.js.map +1 -0
  668. package/packages/core/package.json +6 -3
  669. package/tsconfig.build.json +6 -7
  670. package/node_modules/@sdd-agent-platform/core/dist/doctor/render.d.ts +0 -2
  671. package/node_modules/@sdd-agent-platform/core/dist/doctor/render.js +0 -44
  672. package/node_modules/@sdd-agent-platform/core/dist/doctor/render.js.map +0 -1
  673. package/node_modules/@sdd-agent-platform/core/src/sync-back/apply.ts +0 -270
  674. package/node_modules/@sdd-agent-platform/core/src/sync-back/inspect.ts +0 -655
  675. package/node_modules/@sdd-agent-platform/core/src/sync-back/sync-back.test.ts +0 -569
  676. package/node_modules/@sdd-agent-platform/core/src/sync-back.ts +0 -2
  677. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.test.ts +0 -255
  678. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.test.ts +0 -439
  679. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.test.ts +0 -341
  680. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.test.ts +0 -204
  681. package/packages/cli/dist/commands/lifecycle.d.ts +0 -6
  682. package/packages/cli/dist/commands/lifecycle.js +0 -112
  683. package/packages/cli/dist/commands/lifecycle.js.map +0 -1
  684. package/packages/cli/dist/commands/sync-back.d.ts +0 -6
  685. package/packages/cli/dist/commands/sync-back.js +0 -82
  686. package/packages/cli/dist/commands/sync-back.js.map +0 -1
  687. package/packages/cli/dist/commands/test.d.ts +0 -6
  688. package/packages/cli/dist/commands/test.js +0 -195
  689. package/packages/cli/dist/commands/test.js.map +0 -1
  690. package/packages/cli/dist/commands/verifies.d.ts +0 -6
  691. package/packages/cli/dist/commands/verifies.js +0 -85
  692. package/packages/cli/dist/commands/verifies.js.map +0 -1
  693. package/packages/cli/dist/commands/verify.d.ts +0 -6
  694. package/packages/cli/dist/commands/verify.js +0 -134
  695. package/packages/cli/dist/commands/verify.js.map +0 -1
  696. package/packages/core/dist/doctor/render.d.ts +0 -2
  697. package/packages/core/dist/doctor/render.js +0 -44
  698. package/packages/core/dist/doctor/render.js.map +0 -1
@@ -1,363 +1,967 @@
1
- import { WORKFLOW_STATE_RESOLVER_CONTRACT_VERSION } from '../contracts.js';
2
- import { recordRuntimeProjection } from '../storage/runtime-store.js';
3
- import type { RunState, RunStateTaskRuntime, RunSummary } from '../run-state/model.js';
4
- import { affectedFileConflictsForSelectedRun, type WorkflowAffectedFileConflict } from './affected-file-conflicts.js';
5
- import { readAllRunStates, summarizeRunState } from '../run-state/run-state.js';
6
- import { resolveSddContext, type ContextBranchSource, type ContextResolverContract } from '../sdd-docs/context.js';
7
- import { parseSddBranch, type SddTask, type SddTaskGap, type SddTaskModel } from '../sdd-docs/task-parser.js';
8
- import { dependencyBlockingReasonsForTask, workflowDependencyBlockers, type WorkflowDependencyBlocker } from './dependencies.js';
9
- import { selectLatestEligibleRunsByTask, type DocumentCompatibilityClass, type LatestEligibleRunSelection } from './latest-eligible-run.js';
10
-
11
- export interface WorkflowTaskCounts {
12
- total: number;
13
- pending: number;
14
- inProgress: number;
15
- completed: number;
16
- blocked: number;
17
- deferred: number;
18
- unknown: number;
19
- gaps: number;
20
- }
21
-
22
- export interface WorkflowLatestTaskRun {
23
- partition: string;
24
- gitBranch: string | null;
25
- taskId: string;
26
- runId: string;
27
- runStatus: RunState['status'];
28
- validationStatus: RunState['validation']['status'];
29
- syncBackStatus: RunState['syncBack']['status'];
30
- affectedFiles: string[];
31
- updatedAt: string;
32
- compatibility: DocumentCompatibilityClass;
33
- eligibleForDefaultApply: boolean;
34
- reasons: string[];
35
- }
36
-
37
- export type WorkflowCommandSemantics = 'inspection_navigation' | 'gate_execution';
38
- export type WorkflowHostProjectionStatus = 'active' | 'future' | 'unsupported';
39
- export type WorkflowNextStage = 'spec' | 'tasks' | 'do' | 'test' | 'ship';
40
- export type WorkflowNextIntentKind = 'start_spec' | 'resolve_task_gaps' | 'inspect_dependency' | 'ship_readiness' | 'inspect_task' | 'list_tasks' | 'continue_do' | 'run_task_validation' | 'run_batch_validation' | 'run_wave_validation';
41
-
42
- export interface WorkflowHostCommandProjection {
43
- host: 'claude_code' | 'codex' | 'opencode';
44
- status: WorkflowHostProjectionStatus;
45
- entry: string | null;
46
- projectionSurfaces: string[];
47
- permissionProjection: string;
48
- reason: string;
49
- }
50
-
51
- export interface WorkflowNextIntent {
52
- stage: WorkflowNextStage;
53
- intent: WorkflowNextIntentKind;
54
- canonicalCommand: string;
55
- commandSemantics: WorkflowCommandSemantics;
56
- evidenceRequirement: string;
57
- blockingReason: string | null;
58
- hostProjections: WorkflowHostCommandProjection[];
59
- }
60
-
61
-
62
- export interface WorkflowStateResolution {
63
- contract: typeof WORKFLOW_STATE_RESOLVER_CONTRACT_VERSION;
64
- generatedAt: string;
65
- branch: string;
66
- workflowStatus: 'active' | 'not_started';
67
- context: ContextResolverContract;
68
- documents: SddTaskModel['documents'];
69
- model: SddTaskModel;
70
- taskCounts: WorkflowTaskCounts;
71
- visibleGaps: SddTaskGap[];
72
- latestRun: RunSummary | null;
73
- latestRunState: RunState | null;
74
- latestRunsByTask: WorkflowLatestTaskRun[];
75
- latestEligibleRunsByTask: LatestEligibleRunSelection[];
76
- affectedFileConflicts: WorkflowAffectedFileConflict[];
77
- blockingReasons: string[];
78
- dependencyBlockers: WorkflowDependencyBlocker[];
79
- recommendedNextCommand: string;
80
- nextIntent: WorkflowNextIntent;
81
- }
82
-
83
- export async function resolveWorkflowState(projectRoot: string, options: { branch?: string | null; branchSource?: ContextBranchSource; taskId?: string | null } = {}): Promise<WorkflowStateResolution> {
84
- const context = await resolveSddContext(projectRoot, options);
85
- const branch = context.partition;
86
- const [model, states] = await Promise.all([parseSddBranch(projectRoot, branch), readAllRunStates(projectRoot)]);
87
- const visibleGaps = workflowIsActive(model) ? model.gaps : [];
88
- const latestEligibleRunsByTask = selectLatestEligibleRunsByTask({ states, model, partition: branch, currentGitBranch: context.currentGitBranch });
89
- const latestRunsByTask = selectedLatestTaskRuns(latestEligibleRunsByTask);
90
- const selectedTaskRun = options.taskId
91
- ? latestRunsByTask.find((entry) => entry.taskId === options.taskId) ?? null
92
- : latestRunsByTask.slice().sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt))[0] ?? null;
93
- const latestRunState = selectedTaskRun ? states.find((state) => state.runId === selectedTaskRun.runId) ?? null : null;
94
- const affectedFileConflicts = latestRunState ? affectedFileConflictsForSelectedRun(states, latestRunState) : [];
95
- const runtimeByTask = latestRuntimeTaskStates(latestEligibleRunsByTask, states);
96
- const dependencyBlockers = workflowDependencyBlockers(model, { runtimeByTask });
97
- const blockingReasons = blockingWorkflowReasons(visibleGaps, affectedFileConflicts, dependencyBlockers);
98
- const resolution: WorkflowStateResolution = {
99
- contract: WORKFLOW_STATE_RESOLVER_CONTRACT_VERSION,
100
- generatedAt: new Date().toISOString(),
101
- branch,
102
- workflowStatus: workflowIsActive(model) ? 'active' : 'not_started',
103
- context,
104
- documents: model.documents,
105
- model,
106
- taskCounts: taskCounts(model, visibleGaps),
107
- visibleGaps,
108
- latestRun: latestRunState ? summarizeRunState(latestRunState) : null,
109
- latestRunState,
110
- latestRunsByTask,
111
- latestEligibleRunsByTask,
112
- affectedFileConflicts,
113
- dependencyBlockers,
114
- blockingReasons,
115
- nextIntent: recommendedWorkflowNextIntent(context, model, latestRunsByTask, visibleGaps, dependencyBlockers, runtimeByTask),
116
- recommendedNextCommand: ''
117
- };
118
- resolution.recommendedNextCommand = resolution.nextIntent.canonicalCommand;
119
- try {
120
- await recordRuntimeProjection(projectRoot, 'workflow_state', branch, projectWorkflowStateProjection(resolution));
121
- } catch {
122
- // Projection writes are rebuildable and must not block workflow resolution.
123
- }
124
- return resolution;
125
- }
126
-
127
- function workflowIsActive(model: SddTaskModel): boolean {
128
- return model.documents.specExists || model.documents.planExists || model.documents.tasksExists;
129
- }
130
-
131
- function taskCounts(model: SddTaskModel, gaps: SddTaskGap[]): WorkflowTaskCounts {
132
- return {
133
- total: model.tasks.length,
134
- pending: model.tasks.filter((task) => task.status === 'pending').length,
135
- inProgress: model.tasks.filter((task) => task.status === 'in_progress').length,
136
- completed: model.tasks.filter((task) => task.status === 'completed').length,
137
- blocked: model.tasks.filter((task) => task.status === 'blocked').length,
138
- deferred: model.tasks.filter((task) => task.status === 'deferred').length,
139
- unknown: model.tasks.filter((task) => task.status === 'unknown').length,
140
- gaps: gaps.length
141
- };
142
- }
143
-
144
- function selectedLatestTaskRuns(selections: LatestEligibleRunSelection[]): WorkflowLatestTaskRun[] {
145
- return selections
146
- .flatMap((selection) => selection.selected ? [selection.selected] : [])
147
- .map((candidate) => ({
148
- partition: candidate.partition,
149
- gitBranch: candidate.gitBranch,
150
- taskId: candidate.taskId,
151
- runId: candidate.runId,
152
- runStatus: candidate.runStatus,
153
- validationStatus: candidate.validationStatus,
154
- syncBackStatus: candidate.syncBackStatus,
155
- affectedFiles: candidate.affectedFiles,
156
- updatedAt: candidate.updatedAt,
157
- compatibility: candidate.compatibility,
158
- eligibleForDefaultApply: candidate.eligibleForDefaultApply,
159
- reasons: candidate.reasons
160
- }))
161
- .sort((left, right) => left.taskId.localeCompare(right.taskId));
162
- }
163
-
164
-
165
- function blockingWorkflowReasons(gaps: SddTaskGap[], conflicts: WorkflowAffectedFileConflict[], dependencyBlockers: WorkflowDependencyBlocker[]): string[] {
166
- const reasons = gaps.filter((gap) => gap.severity === 'blocking').map((gap) => `${gap.field}: ${gap.message}`);
167
- for (const conflict of conflicts) {
168
- reasons.push(`Affected file ${conflict.file} is active in run ${conflict.runId} for ${conflict.partition}/${conflict.taskId}.`);
169
- }
170
- for (const blocker of dependencyBlockers) {
171
- reasons.push(blocker.reason);
172
- }
173
- return reasons;
174
- }
175
-
176
- function recommendedWorkflowNextIntent(
177
- context: ContextResolverContract,
178
- model: SddTaskModel,
179
- latestRunsByTask: WorkflowLatestTaskRun[],
180
- gaps: SddTaskGap[],
181
- dependencyBlockers: WorkflowDependencyBlocker[],
182
- runtimeByTask: Map<string, RunStateTaskRuntime>
183
- ): WorkflowNextIntent {
184
- if (!workflowIsActive(model)) {
185
- return workflowNextIntent('spec', 'start_spec', `sdd spec --branch ${context.partition}`, 'Start the spec stage before planning or task execution.', null);
186
- }
187
- const blockingGap = gaps.find((gap) => gap.severity === 'blocking');
188
- if (blockingGap) {
189
- 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}`);
190
- }
191
-
192
- const strictTask = model.tasks.find((task) => needsTaskValidation(task, runtimeByTask.get(task.id)));
193
- if (strictTask) {
194
- return workflowNextIntent('test', 'run_task_validation', `sdd test task ${strictTask.id} --branch ${context.partition}`, 'Validate this strict or task_end task before more implementation proceeds.', null);
195
- }
196
-
197
- const readyBoundary = readyValidationBoundary(model, runtimeByTask);
198
- if (readyBoundary?.kind === 'batch') {
199
- return workflowNextIntent('test', 'run_batch_validation', `sdd test batch ${readyBoundary.id} --branch ${context.partition}`, `Validate accumulated implementation evidence for batch ${readyBoundary.id}.`, null);
200
- }
201
- if (readyBoundary?.kind === 'wave') {
202
- return workflowNextIntent('test', 'run_wave_validation', waveValidationCommand(context.partition, readyBoundary.wave), `Validate accumulated implementation evidence for wave ${readyBoundary.wave ?? 'all'}.`, null);
203
- }
204
-
205
- if (latestRunsByTask.some(latestEligibleRunReadyForShip)) {
206
- return workflowNextIntent('ship', 'ship_readiness', `sdd ship --branch ${context.partition} --dry-run`, 'Run release readiness after validation PASS; create a decision card only if the gate requires human review.', null);
207
- }
208
-
209
- const nextTask = model.tasks.find((task) => task.status === 'pending' && !runtimeTaskImplemented(runtimeByTask.get(task.id)) && dependencyBlockingReasonsForTask(model, task.id, { runtimeByTask }).length === 0);
210
- if (nextTask) {
211
- 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);
212
- }
213
-
214
- const dependencyBlocker = dependencyBlockers[0];
215
- if (dependencyBlocker) {
216
- return workflowNextIntent('tasks', 'inspect_dependency', `sdd tasks inspect ${dependencyBlocker.dependencyId} --branch ${context.partition}`, 'Inspect the dependency task before continuing this workflow.', dependencyBlocker.reason);
217
- }
218
-
219
- const pendingTask = model.tasks.find((task) => task.status === 'pending');
220
- return pendingTask
221
- ? workflowNextIntent('tasks', 'inspect_task', `sdd tasks inspect ${pendingTask.id} --branch ${context.partition}`, 'Inspect task boundary, acceptance, validation, and capability needs before do/test.', null)
222
- : workflowNextIntent('tasks', 'list_tasks', `sdd tasks list --branch ${context.partition}`, 'Inspect task state and decide whether to continue or ship.', null);
223
- }
224
-
225
- function latestRuntimeTaskStates(selections: LatestEligibleRunSelection[], states: RunState[]): Map<string, RunStateTaskRuntime> {
226
- const stateByRunId = new Map(states.map((state) => [state.runId, state]));
227
- const result = new Map<string, RunStateTaskRuntime>();
228
- for (const selection of selections) {
229
- const selected = selection.selected;
230
- if (!selected) {
231
- continue;
232
- }
233
- const taskState = stateByRunId.get(selected.runId)?.tasks[selected.taskId];
234
- if (taskState) {
235
- result.set(selected.taskId, taskState);
236
- }
237
- }
238
- return result;
239
- }
240
-
241
- function needsTaskValidation(task: SddTask, runtime: RunStateTaskRuntime | undefined): boolean {
242
- return Boolean(runtimeTaskImplemented(runtime) && runtime?.verificationStatus !== 'pass' && (task.requiresVerifyBeforeNext || task.validationTiming === 'task_end'));
243
- }
244
-
245
- function readyValidationBoundary(model: SddTaskModel, runtimeByTask: Map<string, RunStateTaskRuntime>): { kind: 'batch'; id: string } | { kind: 'wave'; wave: number | null } | null {
246
- const batchGroups = new Map<string, SddTask[]>();
247
- const waveGroups = new Map<string, { wave: number | null; tasks: SddTask[] }>();
248
- for (const task of model.tasks) {
249
- if (task.validationTiming === 'batch_end' && task.validationBatch) {
250
- batchGroups.set(task.validationBatch, [...(batchGroups.get(task.validationBatch) ?? []), task]);
251
- }
252
- if (task.validationTiming === 'wave_end') {
253
- const key = String(task.wave ?? 'all');
254
- const group = waveGroups.get(key) ?? { wave: task.wave, tasks: [] };
255
- group.tasks.push(task);
256
- waveGroups.set(key, group);
257
- }
258
- }
259
- for (const [id, tasks] of batchGroups) {
260
- if (validationBoundaryReady(tasks, runtimeByTask)) {
261
- return { kind: 'batch', id };
262
- }
263
- }
264
- for (const group of waveGroups.values()) {
265
- if (validationBoundaryReady(group.tasks, runtimeByTask)) {
266
- return { kind: 'wave', wave: group.wave };
267
- }
268
- }
269
- return null;
270
- }
271
-
272
- function validationBoundaryReady(tasks: SddTask[], runtimeByTask: Map<string, RunStateTaskRuntime>): boolean {
273
- return tasks.every((task) => runtimeTaskImplemented(runtimeByTask.get(task.id)))
274
- && tasks.some((task) => runtimeByTask.get(task.id)?.verificationStatus !== 'pass');
275
- }
276
-
277
- function runtimeTaskImplemented(runtime: RunStateTaskRuntime | undefined): boolean {
278
- return runtime?.implementationStatus === 'implemented' || runtime?.status === 'implemented_pending_validation' || runtime?.status === 'implemented_verified';
279
- }
280
-
281
- function latestEligibleRunReadyForShip(run: WorkflowLatestTaskRun): boolean {
282
- return run.runStatus === 'completed' && run.validationStatus === 'pass';
283
- }
284
-
285
- function waveValidationCommand(branch: string, wave: number | null): string {
286
- return wave === null ? `sdd test wave --branch ${branch}` : `sdd test wave --branch ${branch} --wave ${wave}`;
287
- }
288
-
289
-
290
- function workflowNextIntent(
291
- stage: WorkflowNextStage,
292
- intent: WorkflowNextIntentKind,
293
- canonicalCommand: string,
294
- evidenceRequirement: string,
295
- blockingReason: string | null
296
- ): WorkflowNextIntent {
297
- return {
298
- stage,
299
- intent,
300
- canonicalCommand,
301
- commandSemantics: stage === 'do' || stage === 'test' || stage === 'ship' ? 'gate_execution' : 'inspection_navigation',
302
- evidenceRequirement,
303
- blockingReason,
304
- hostProjections: hostCommandProjections(canonicalCommand)
305
- };
306
- }
307
-
308
- function hostCommandProjections(canonicalCommand: string): WorkflowHostCommandProjection[] {
309
- return [
310
- {
311
- host: 'claude_code',
312
- status: 'active',
313
- entry: claudeCodeSlashEntry(canonicalCommand),
314
- projectionSurfaces: ['slash command', 'skill', 'settings/hooks/statusline metadata'],
315
- permissionProjection: 'Claude Code permission mode/tool prompts remain host enforcement, not SDD lifecycle truth.',
316
- reason: 'Claude Code supports slash/skill/statusline projections; the canonical CLI command remains the portable source of workflow intent.'
317
- },
318
- {
319
- host: 'codex',
320
- status: 'future',
321
- entry: null,
322
- projectionSurfaces: ['config.toml profile', 'AGENTS.md instruction surface', 'approval_policy', 'sandbox_mode'],
323
- permissionProjection: 'Codex approval and sandbox controls can project execution policy; custom command/skill projection is not marked active without stronger evidence.',
324
- reason: 'Codex exposes approval, sandbox, AGENTS.md, and built-in slash surfaces, but project custom workflow command semantics stay future until validated.'
325
- },
326
- {
327
- host: 'opencode',
328
- status: 'active',
329
- entry: opencodeCommandEntry(canonicalCommand),
330
- projectionSurfaces: ['opencode.json/jsonc', '.opencode/commands', '.opencode/agents', '.opencode/skills', 'permissions'],
331
- permissionProjection: 'OpenCode allow/ask/deny permissions can project SDD tool policy; SDD artifacts remain authoritative evidence.',
332
- reason: 'OpenCode documents project commands, agents, skills, and permissions suitable for host-specific projection.'
333
- }
334
- ];
335
- }
336
-
337
- function claudeCodeSlashEntry(canonicalCommand: string): string {
338
- const [command, ...rest] = canonicalCommand.replace(/^sdd\s+/, '').split(' ');
339
- return `/sdd:${command}${rest.length > 0 ? ` ${rest.join(' ')}` : ''}`;
340
- }
341
-
342
- function opencodeCommandEntry(canonicalCommand: string): string {
343
- return `/sdd ${canonicalCommand.replace(/^sdd\s+/, '')}`;
344
- }
345
-
346
- function projectWorkflowStateProjection(resolution: WorkflowStateResolution): unknown {
347
- return {
348
- contract: resolution.contract,
349
- generatedAt: resolution.generatedAt,
350
- branch: resolution.branch,
351
- workflowStatus: resolution.workflowStatus,
352
- documents: resolution.documents,
353
- taskCounts: resolution.taskCounts,
354
- latestRun: resolution.latestRun,
355
- latestRunsByTask: resolution.latestRunsByTask,
356
- latestEligibleRunsByTask: resolution.latestEligibleRunsByTask,
357
- affectedFileConflicts: resolution.affectedFileConflicts,
358
- dependencyBlockers: resolution.dependencyBlockers,
359
- blockingReasons: resolution.blockingReasons,
360
- nextIntent: resolution.nextIntent,
361
- recommendedNextCommand: resolution.recommendedNextCommand
362
- };
363
- }
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
+ }