sdd-agent-platform 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (417) hide show
  1. package/README.md +18 -23
  2. package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js +31 -28
  3. package/node_modules/@sdd-agent-platform/core/dist/ai-tools.js.map +1 -1
  4. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js +3 -2
  5. package/node_modules/@sdd-agent-platform/core/dist/config/init-project.js.map +1 -1
  6. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.d.ts +1 -1
  7. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js +14 -5
  8. package/node_modules/@sdd-agent-platform/core/dist/config/starter-documents.js.map +1 -1
  9. package/node_modules/@sdd-agent-platform/core/dist/contracts.d.ts +2 -0
  10. package/node_modules/@sdd-agent-platform/core/dist/contracts.js +2 -0
  11. package/node_modules/@sdd-agent-platform/core/dist/contracts.js.map +1 -1
  12. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js +3 -3
  13. package/node_modules/@sdd-agent-platform/core/dist/doctor/checks/run-evidence.js.map +1 -1
  14. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js +155 -1
  15. package/node_modules/@sdd-agent-platform/core/dist/doctor/doctor.js.map +1 -1
  16. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.d.ts +23 -0
  17. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js +54 -0
  18. package/node_modules/@sdd-agent-platform/core/dist/evidence/lookup.js.map +1 -0
  19. package/node_modules/@sdd-agent-platform/core/dist/evidence-runtime/contracts.d.ts +11 -0
  20. package/node_modules/@sdd-agent-platform/core/dist/execution/agent-execution-records.js +15 -8
  21. package/node_modules/@sdd-agent-platform/core/dist/execution/agent-execution-records.js.map +1 -1
  22. package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js +14 -6
  23. package/node_modules/@sdd-agent-platform/core/dist/execution/resident-worker.js.map +1 -1
  24. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.d.ts +112 -0
  25. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js +145 -0
  26. package/node_modules/@sdd-agent-platform/core/dist/execution/stage-team-runtime.js.map +1 -0
  27. package/node_modules/@sdd-agent-platform/core/dist/instructions.js +36 -36
  28. package/node_modules/@sdd-agent-platform/core/dist/instructions.js.map +1 -1
  29. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.d.ts +2 -0
  30. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js +37 -17
  31. package/node_modules/@sdd-agent-platform/core/dist/lifecycle/ship.js.map +1 -1
  32. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.d.ts +16 -1
  33. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js +174 -16
  34. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-capability-catalog.js.map +1 -1
  35. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js +2 -2
  36. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-registry.js.map +1 -1
  37. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.d.ts +10 -0
  38. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js +31 -1
  39. package/node_modules/@sdd-agent-platform/core/dist/registries/agent-runtime-static.js.map +1 -1
  40. package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.d.ts +2 -17
  41. package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.js +222 -10
  42. package/node_modules/@sdd-agent-platform/core/dist/registries/capability-sources.js.map +1 -1
  43. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js +5 -5
  44. package/node_modules/@sdd-agent-platform/core/dist/registries/workflow-gates.js.map +1 -1
  45. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime-config.js +27 -12
  46. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime-config.js.map +1 -1
  47. package/node_modules/@sdd-agent-platform/core/dist/router/agent-runtime.d.ts +59 -1
  48. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.d.ts +3 -1
  49. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js +191 -0
  50. package/node_modules/@sdd-agent-platform/core/dist/router/route-projection.js.map +1 -1
  51. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js +32 -6
  52. package/node_modules/@sdd-agent-platform/core/dist/router/routing.js.map +1 -1
  53. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-inspection.js +11 -4
  54. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-inspection.js.map +1 -1
  55. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js +31 -3
  56. package/node_modules/@sdd-agent-platform/core/dist/router/runtime-validation.js.map +1 -1
  57. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js +48 -15
  58. package/node_modules/@sdd-agent-platform/core/dist/run-state/artifacts.js.map +1 -1
  59. package/node_modules/@sdd-agent-platform/core/dist/run-state/events.js +2 -2
  60. package/node_modules/@sdd-agent-platform/core/dist/run-state/events.js.map +1 -1
  61. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.d.ts +3 -1
  62. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js +15 -49
  63. package/node_modules/@sdd-agent-platform/core/dist/run-state/inspect-run.js.map +1 -1
  64. package/node_modules/@sdd-agent-platform/core/dist/run-state/invocation-ledger.js +2 -2
  65. package/node_modules/@sdd-agent-platform/core/dist/run-state/invocation-ledger.js.map +1 -1
  66. package/node_modules/@sdd-agent-platform/core/dist/run-state/model.d.ts +25 -1
  67. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js +21 -14
  68. package/node_modules/@sdd-agent-platform/core/dist/run-state/run-state.js.map +1 -1
  69. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.d.ts +62 -0
  70. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js +130 -0
  71. package/node_modules/@sdd-agent-platform/core/dist/run-state/task-evidence.js.map +1 -0
  72. package/node_modules/@sdd-agent-platform/core/dist/run-state.d.ts +1 -0
  73. package/node_modules/@sdd-agent-platform/core/dist/run-state.js +1 -0
  74. package/node_modules/@sdd-agent-platform/core/dist/run-state.js.map +1 -1
  75. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.d.ts +10 -0
  76. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js +44 -14
  77. package/node_modules/@sdd-agent-platform/core/dist/runtime-paths.js.map +1 -1
  78. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/context.js +1 -1
  79. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/context.js.map +1 -1
  80. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.d.ts +4 -0
  81. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js +189 -0
  82. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/document-hashes.js.map +1 -0
  83. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js +12 -3
  84. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/run-binding.js.map +1 -1
  85. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.d.ts +20 -0
  86. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js +101 -21
  87. package/node_modules/@sdd-agent-platform/core/dist/sdd-docs/task-parser.js.map +1 -1
  88. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.d.ts +62 -1
  89. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js +192 -4
  90. package/node_modules/@sdd-agent-platform/core/dist/status/project-status.js.map +1 -1
  91. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.d.ts +195 -2
  92. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js +499 -2
  93. package/node_modules/@sdd-agent-platform/core/dist/storage/runtime-store.js.map +1 -1
  94. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js +23 -1
  95. package/node_modules/@sdd-agent-platform/core/dist/sync-back/apply.js.map +1 -1
  96. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.d.ts +19 -0
  97. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js +114 -12
  98. package/node_modules/@sdd-agent-platform/core/dist/sync-back/inspect.js.map +1 -1
  99. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js +21 -0
  100. package/node_modules/@sdd-agent-platform/core/dist/test-support/fixtures.js.map +1 -1
  101. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js +16 -2
  102. package/node_modules/@sdd-agent-platform/core/dist/test-support/run-state.js.map +1 -1
  103. package/node_modules/@sdd-agent-platform/core/dist/tsconfig.tsbuildinfo +1 -1
  104. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js +34 -2
  105. package/node_modules/@sdd-agent-platform/core/dist/verification/goal-verify.js.map +1 -1
  106. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js +15 -5
  107. package/node_modules/@sdd-agent-platform/core/dist/verification/rendering.js.map +1 -1
  108. package/node_modules/@sdd-agent-platform/core/dist/verification/review-gate.d.ts +22 -0
  109. package/node_modules/@sdd-agent-platform/core/dist/verification/review-gate.js +53 -0
  110. package/node_modules/@sdd-agent-platform/core/dist/verification/review-gate.js.map +1 -0
  111. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js +102 -9
  112. package/node_modules/@sdd-agent-platform/core/dist/verification/single-task-loop.js.map +1 -1
  113. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.d.ts +16 -1
  114. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js +355 -69
  115. package/node_modules/@sdd-agent-platform/core/dist/verification/test-runtime.js.map +1 -1
  116. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.d.ts +58 -0
  117. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js +428 -0
  118. package/node_modules/@sdd-agent-platform/core/dist/verification/validation-wave.js.map +1 -0
  119. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.d.ts +2 -0
  120. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js +116 -18
  121. package/node_modules/@sdd-agent-platform/core/dist/verification/verify-contract.js.map +1 -1
  122. package/node_modules/@sdd-agent-platform/core/dist/verification.d.ts +2 -0
  123. package/node_modules/@sdd-agent-platform/core/dist/verification.js +2 -0
  124. package/node_modules/@sdd-agent-platform/core/dist/verification.js.map +1 -1
  125. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.d.ts +24 -0
  126. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js +182 -0
  127. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/evidence-packet.js.map +1 -0
  128. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.d.ts +4 -0
  129. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js +130 -0
  130. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/hard-checks.js.map +1 -0
  131. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.d.ts +4 -0
  132. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js +146 -0
  133. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/policy.js.map +1 -0
  134. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.d.ts +89 -0
  135. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.js +2 -0
  136. package/node_modules/@sdd-agent-platform/core/dist/workflow-gate/types.js.map +1 -0
  137. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
  138. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js +16 -1
  139. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
  140. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.d.ts +8 -4
  141. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.js +25 -11
  142. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/dependencies.js.map +1 -1
  143. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.d.ts +38 -0
  144. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js +122 -0
  145. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/latest-eligible-run.js.map +1 -0
  146. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.d.ts +27 -0
  147. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js +166 -37
  148. package/node_modules/@sdd-agent-platform/core/dist/workflow-state/resolve.js.map +1 -1
  149. package/node_modules/@sdd-agent-platform/core/dist/workflow-state.d.ts +1 -0
  150. package/node_modules/@sdd-agent-platform/core/dist/workflow-state.js +1 -0
  151. package/node_modules/@sdd-agent-platform/core/dist/workflow-state.js.map +1 -1
  152. package/node_modules/@sdd-agent-platform/core/package.json +1 -1
  153. package/node_modules/@sdd-agent-platform/core/src/ai-tools.ts +31 -28
  154. package/node_modules/@sdd-agent-platform/core/src/artifacts/sdd-result.test.ts +50 -4
  155. package/node_modules/@sdd-agent-platform/core/src/config/init-project.test.ts +13 -10
  156. package/node_modules/@sdd-agent-platform/core/src/config/init-project.ts +3 -2
  157. package/node_modules/@sdd-agent-platform/core/src/config/starter-documents.ts +15 -5
  158. package/node_modules/@sdd-agent-platform/core/src/contracts.ts +2 -0
  159. package/node_modules/@sdd-agent-platform/core/src/doctor/checks/run-evidence.ts +3 -3
  160. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.test.ts +117 -5
  161. package/node_modules/@sdd-agent-platform/core/src/doctor/doctor.ts +164 -1
  162. package/node_modules/@sdd-agent-platform/core/src/evidence/lookup.ts +80 -0
  163. package/node_modules/@sdd-agent-platform/core/src/evidence-runtime/contracts.ts +12 -0
  164. package/node_modules/@sdd-agent-platform/core/src/execution/agent-execution-records.ts +16 -11
  165. package/node_modules/@sdd-agent-platform/core/src/execution/background-executor.test.ts +7 -0
  166. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.test.ts +5 -0
  167. package/node_modules/@sdd-agent-platform/core/src/execution/resident-worker.ts +14 -6
  168. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.test.ts +102 -0
  169. package/node_modules/@sdd-agent-platform/core/src/execution/stage-team-runtime.ts +271 -0
  170. package/node_modules/@sdd-agent-platform/core/src/execution/wave-executor.test.ts +4 -0
  171. package/node_modules/@sdd-agent-platform/core/src/governance/policy.test.ts +2 -0
  172. package/node_modules/@sdd-agent-platform/core/src/instructions.test.ts +11 -5
  173. package/node_modules/@sdd-agent-platform/core/src/instructions.ts +36 -36
  174. package/node_modules/@sdd-agent-platform/core/src/lifecycle/ship.ts +39 -17
  175. package/node_modules/@sdd-agent-platform/core/src/phase8-contracts.test.ts +3 -2
  176. package/node_modules/@sdd-agent-platform/core/src/phase8-risk-kernel.test.ts +5 -0
  177. package/node_modules/@sdd-agent-platform/core/src/planning/task-graph.test.ts +2 -0
  178. package/node_modules/@sdd-agent-platform/core/src/planning/wave-plan.test.ts +3 -0
  179. package/node_modules/@sdd-agent-platform/core/src/registries/agent-capability-catalog.ts +269 -17
  180. package/node_modules/@sdd-agent-platform/core/src/registries/agent-registry.ts +2 -2
  181. package/node_modules/@sdd-agent-platform/core/src/registries/agent-runtime-static.ts +41 -1
  182. package/node_modules/@sdd-agent-platform/core/src/registries/capability-sources.ts +238 -15
  183. package/node_modules/@sdd-agent-platform/core/src/registries/registries.test.ts +27 -2
  184. package/node_modules/@sdd-agent-platform/core/src/registries/workflow-gates.ts +5 -5
  185. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime-config.ts +31 -12
  186. package/node_modules/@sdd-agent-platform/core/src/router/agent-runtime.ts +66 -1
  187. package/node_modules/@sdd-agent-platform/core/src/router/route-projection.ts +211 -0
  188. package/node_modules/@sdd-agent-platform/core/src/router/route-sdd-task.test.ts +151 -3
  189. package/node_modules/@sdd-agent-platform/core/src/router/routing.ts +35 -6
  190. package/node_modules/@sdd-agent-platform/core/src/router/runtime-inspection.ts +11 -4
  191. package/node_modules/@sdd-agent-platform/core/src/router/runtime-validation.ts +32 -3
  192. package/node_modules/@sdd-agent-platform/core/src/run-state/artifacts.ts +48 -15
  193. package/node_modules/@sdd-agent-platform/core/src/run-state/events.ts +2 -2
  194. package/node_modules/@sdd-agent-platform/core/src/run-state/inspect-run.ts +17 -52
  195. package/node_modules/@sdd-agent-platform/core/src/run-state/invocation-ledger.ts +2 -2
  196. package/node_modules/@sdd-agent-platform/core/src/run-state/model.ts +28 -1
  197. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.test.ts +3 -0
  198. package/node_modules/@sdd-agent-platform/core/src/run-state/run-state.ts +22 -18
  199. package/node_modules/@sdd-agent-platform/core/src/run-state/task-evidence.ts +206 -0
  200. package/node_modules/@sdd-agent-platform/core/src/run-state.ts +1 -0
  201. package/node_modules/@sdd-agent-platform/core/src/runtime-paths.ts +54 -14
  202. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/context.ts +1 -1
  203. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/document-hashes.ts +207 -0
  204. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/run-binding.ts +12 -3
  205. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.test.ts +139 -0
  206. package/node_modules/@sdd-agent-platform/core/src/sdd-docs/task-parser.ts +137 -24
  207. package/node_modules/@sdd-agent-platform/core/src/status/project-status.ts +268 -5
  208. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.test.ts +368 -4
  209. package/node_modules/@sdd-agent-platform/core/src/storage/runtime-store.ts +697 -2
  210. package/node_modules/@sdd-agent-platform/core/src/sync-back/apply.ts +23 -1
  211. package/node_modules/@sdd-agent-platform/core/src/sync-back/inspect.ts +145 -12
  212. package/node_modules/@sdd-agent-platform/core/src/sync-back/sync-back.test.ts +132 -9
  213. package/node_modules/@sdd-agent-platform/core/src/test-support/fixtures.ts +21 -0
  214. package/node_modules/@sdd-agent-platform/core/src/test-support/run-state.ts +16 -2
  215. package/node_modules/@sdd-agent-platform/core/src/verification/goal-verify.test.ts +1 -1
  216. package/node_modules/@sdd-agent-platform/core/src/verification/goal-verify.ts +38 -5
  217. package/node_modules/@sdd-agent-platform/core/src/verification/rendering.ts +15 -5
  218. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.test.ts +77 -0
  219. package/node_modules/@sdd-agent-platform/core/src/verification/review-gate.ts +77 -0
  220. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.test.ts +64 -4
  221. package/node_modules/@sdd-agent-platform/core/src/verification/single-task-loop.ts +110 -12
  222. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.test.ts +72 -25
  223. package/node_modules/@sdd-agent-platform/core/src/verification/test-runtime.ts +402 -77
  224. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.test.ts +341 -0
  225. package/node_modules/@sdd-agent-platform/core/src/verification/validation-wave.ts +513 -0
  226. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.test.ts +144 -5
  227. package/node_modules/@sdd-agent-platform/core/src/verification/verify-contract.ts +129 -18
  228. package/node_modules/@sdd-agent-platform/core/src/verification.ts +2 -0
  229. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/evidence-packet.ts +196 -0
  230. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.test.ts +171 -0
  231. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/hard-checks.ts +143 -0
  232. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.test.ts +137 -0
  233. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/policy.ts +155 -0
  234. package/node_modules/@sdd-agent-platform/core/src/workflow-gate/types.ts +114 -0
  235. package/node_modules/@sdd-agent-platform/core/src/workflow-state/affected-file-conflicts.ts +18 -1
  236. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.test.ts +1 -1
  237. package/node_modules/@sdd-agent-platform/core/src/workflow-state/dependencies.ts +33 -11
  238. package/node_modules/@sdd-agent-platform/core/src/workflow-state/latest-eligible-run.ts +156 -0
  239. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.test.ts +351 -2
  240. package/node_modules/@sdd-agent-platform/core/src/workflow-state/resolve.ts +227 -39
  241. package/node_modules/@sdd-agent-platform/core/src/workflow-state.ts +1 -0
  242. package/package.json +1 -1
  243. package/packages/cli/dist/commands/status.js +2 -2
  244. package/packages/cli/dist/commands/status.js.map +1 -1
  245. package/packages/cli/dist/commands/sync-back.js +1 -1
  246. package/packages/cli/dist/commands/sync-back.js.map +1 -1
  247. package/packages/cli/dist/commands/tasks.js +4 -4
  248. package/packages/cli/dist/commands/tasks.js.map +1 -1
  249. package/packages/cli/dist/commands/test.js +94 -5
  250. package/packages/cli/dist/commands/test.js.map +1 -1
  251. package/packages/cli/dist/commands/verifies.js +5 -3
  252. package/packages/cli/dist/commands/verifies.js.map +1 -1
  253. package/packages/cli/dist/commands/verify.js +48 -7
  254. package/packages/cli/dist/commands/verify.js.map +1 -1
  255. package/packages/cli/dist/help.js +32 -18
  256. package/packages/cli/dist/help.js.map +1 -1
  257. package/packages/cli/dist/renderers/artifacts.js +1 -1
  258. package/packages/cli/dist/renderers/artifacts.js.map +1 -1
  259. package/packages/cli/dist/renderers/registry-runtime.js +7 -2
  260. package/packages/cli/dist/renderers/registry-runtime.js.map +1 -1
  261. package/packages/cli/dist/renderers/router.js +4 -2
  262. package/packages/cli/dist/renderers/router.js.map +1 -1
  263. package/packages/cli/dist/renderers/workflow.js +33 -12
  264. package/packages/cli/dist/renderers/workflow.js.map +1 -1
  265. package/packages/cli/dist/tsconfig.tsbuildinfo +1 -1
  266. package/packages/cli/package.json +2 -2
  267. package/packages/core/dist/ai-tools.js +31 -28
  268. package/packages/core/dist/ai-tools.js.map +1 -1
  269. package/packages/core/dist/config/init-project.js +3 -2
  270. package/packages/core/dist/config/init-project.js.map +1 -1
  271. package/packages/core/dist/config/starter-documents.d.ts +1 -1
  272. package/packages/core/dist/config/starter-documents.js +14 -5
  273. package/packages/core/dist/config/starter-documents.js.map +1 -1
  274. package/packages/core/dist/contracts.d.ts +2 -0
  275. package/packages/core/dist/contracts.js +2 -0
  276. package/packages/core/dist/contracts.js.map +1 -1
  277. package/packages/core/dist/doctor/checks/run-evidence.js +3 -3
  278. package/packages/core/dist/doctor/checks/run-evidence.js.map +1 -1
  279. package/packages/core/dist/doctor/doctor.js +155 -1
  280. package/packages/core/dist/doctor/doctor.js.map +1 -1
  281. package/packages/core/dist/evidence/lookup.d.ts +23 -0
  282. package/packages/core/dist/evidence/lookup.js +54 -0
  283. package/packages/core/dist/evidence/lookup.js.map +1 -0
  284. package/packages/core/dist/evidence-runtime/contracts.d.ts +11 -0
  285. package/packages/core/dist/execution/agent-execution-records.js +15 -8
  286. package/packages/core/dist/execution/agent-execution-records.js.map +1 -1
  287. package/packages/core/dist/execution/resident-worker.js +14 -6
  288. package/packages/core/dist/execution/resident-worker.js.map +1 -1
  289. package/packages/core/dist/execution/stage-team-runtime.d.ts +112 -0
  290. package/packages/core/dist/execution/stage-team-runtime.js +145 -0
  291. package/packages/core/dist/execution/stage-team-runtime.js.map +1 -0
  292. package/packages/core/dist/instructions.js +36 -36
  293. package/packages/core/dist/instructions.js.map +1 -1
  294. package/packages/core/dist/lifecycle/ship.d.ts +2 -0
  295. package/packages/core/dist/lifecycle/ship.js +37 -17
  296. package/packages/core/dist/lifecycle/ship.js.map +1 -1
  297. package/packages/core/dist/registries/agent-capability-catalog.d.ts +16 -1
  298. package/packages/core/dist/registries/agent-capability-catalog.js +174 -16
  299. package/packages/core/dist/registries/agent-capability-catalog.js.map +1 -1
  300. package/packages/core/dist/registries/agent-registry.js +2 -2
  301. package/packages/core/dist/registries/agent-registry.js.map +1 -1
  302. package/packages/core/dist/registries/agent-runtime-static.d.ts +10 -0
  303. package/packages/core/dist/registries/agent-runtime-static.js +31 -1
  304. package/packages/core/dist/registries/agent-runtime-static.js.map +1 -1
  305. package/packages/core/dist/registries/capability-sources.d.ts +2 -17
  306. package/packages/core/dist/registries/capability-sources.js +222 -10
  307. package/packages/core/dist/registries/capability-sources.js.map +1 -1
  308. package/packages/core/dist/registries/workflow-gates.js +5 -5
  309. package/packages/core/dist/registries/workflow-gates.js.map +1 -1
  310. package/packages/core/dist/router/agent-runtime-config.js +27 -12
  311. package/packages/core/dist/router/agent-runtime-config.js.map +1 -1
  312. package/packages/core/dist/router/agent-runtime.d.ts +59 -1
  313. package/packages/core/dist/router/route-projection.d.ts +3 -1
  314. package/packages/core/dist/router/route-projection.js +191 -0
  315. package/packages/core/dist/router/route-projection.js.map +1 -1
  316. package/packages/core/dist/router/routing.js +32 -6
  317. package/packages/core/dist/router/routing.js.map +1 -1
  318. package/packages/core/dist/router/runtime-inspection.js +11 -4
  319. package/packages/core/dist/router/runtime-inspection.js.map +1 -1
  320. package/packages/core/dist/router/runtime-validation.js +31 -3
  321. package/packages/core/dist/router/runtime-validation.js.map +1 -1
  322. package/packages/core/dist/run-state/artifacts.js +48 -15
  323. package/packages/core/dist/run-state/artifacts.js.map +1 -1
  324. package/packages/core/dist/run-state/events.js +2 -2
  325. package/packages/core/dist/run-state/events.js.map +1 -1
  326. package/packages/core/dist/run-state/inspect-run.d.ts +3 -1
  327. package/packages/core/dist/run-state/inspect-run.js +15 -49
  328. package/packages/core/dist/run-state/inspect-run.js.map +1 -1
  329. package/packages/core/dist/run-state/invocation-ledger.js +2 -2
  330. package/packages/core/dist/run-state/invocation-ledger.js.map +1 -1
  331. package/packages/core/dist/run-state/model.d.ts +25 -1
  332. package/packages/core/dist/run-state/run-state.js +21 -14
  333. package/packages/core/dist/run-state/run-state.js.map +1 -1
  334. package/packages/core/dist/run-state/task-evidence.d.ts +62 -0
  335. package/packages/core/dist/run-state/task-evidence.js +130 -0
  336. package/packages/core/dist/run-state/task-evidence.js.map +1 -0
  337. package/packages/core/dist/run-state.d.ts +1 -0
  338. package/packages/core/dist/run-state.js +1 -0
  339. package/packages/core/dist/run-state.js.map +1 -1
  340. package/packages/core/dist/runtime-paths.d.ts +10 -0
  341. package/packages/core/dist/runtime-paths.js +44 -14
  342. package/packages/core/dist/runtime-paths.js.map +1 -1
  343. package/packages/core/dist/sdd-docs/context.js +1 -1
  344. package/packages/core/dist/sdd-docs/context.js.map +1 -1
  345. package/packages/core/dist/sdd-docs/document-hashes.d.ts +4 -0
  346. package/packages/core/dist/sdd-docs/document-hashes.js +189 -0
  347. package/packages/core/dist/sdd-docs/document-hashes.js.map +1 -0
  348. package/packages/core/dist/sdd-docs/run-binding.js +12 -3
  349. package/packages/core/dist/sdd-docs/run-binding.js.map +1 -1
  350. package/packages/core/dist/sdd-docs/task-parser.d.ts +20 -0
  351. package/packages/core/dist/sdd-docs/task-parser.js +101 -21
  352. package/packages/core/dist/sdd-docs/task-parser.js.map +1 -1
  353. package/packages/core/dist/status/project-status.d.ts +62 -1
  354. package/packages/core/dist/status/project-status.js +192 -4
  355. package/packages/core/dist/status/project-status.js.map +1 -1
  356. package/packages/core/dist/storage/runtime-store.d.ts +195 -2
  357. package/packages/core/dist/storage/runtime-store.js +499 -2
  358. package/packages/core/dist/storage/runtime-store.js.map +1 -1
  359. package/packages/core/dist/sync-back/apply.js +23 -1
  360. package/packages/core/dist/sync-back/apply.js.map +1 -1
  361. package/packages/core/dist/sync-back/inspect.d.ts +19 -0
  362. package/packages/core/dist/sync-back/inspect.js +114 -12
  363. package/packages/core/dist/sync-back/inspect.js.map +1 -1
  364. package/packages/core/dist/test-support/fixtures.js +21 -0
  365. package/packages/core/dist/test-support/fixtures.js.map +1 -1
  366. package/packages/core/dist/test-support/run-state.js +16 -2
  367. package/packages/core/dist/test-support/run-state.js.map +1 -1
  368. package/packages/core/dist/tsconfig.tsbuildinfo +1 -1
  369. package/packages/core/dist/verification/goal-verify.js +34 -2
  370. package/packages/core/dist/verification/goal-verify.js.map +1 -1
  371. package/packages/core/dist/verification/rendering.js +15 -5
  372. package/packages/core/dist/verification/rendering.js.map +1 -1
  373. package/packages/core/dist/verification/review-gate.d.ts +22 -0
  374. package/packages/core/dist/verification/review-gate.js +53 -0
  375. package/packages/core/dist/verification/review-gate.js.map +1 -0
  376. package/packages/core/dist/verification/single-task-loop.js +102 -9
  377. package/packages/core/dist/verification/single-task-loop.js.map +1 -1
  378. package/packages/core/dist/verification/test-runtime.d.ts +16 -1
  379. package/packages/core/dist/verification/test-runtime.js +355 -69
  380. package/packages/core/dist/verification/test-runtime.js.map +1 -1
  381. package/packages/core/dist/verification/validation-wave.d.ts +58 -0
  382. package/packages/core/dist/verification/validation-wave.js +428 -0
  383. package/packages/core/dist/verification/validation-wave.js.map +1 -0
  384. package/packages/core/dist/verification/verify-contract.d.ts +2 -0
  385. package/packages/core/dist/verification/verify-contract.js +116 -18
  386. package/packages/core/dist/verification/verify-contract.js.map +1 -1
  387. package/packages/core/dist/verification.d.ts +2 -0
  388. package/packages/core/dist/verification.js +2 -0
  389. package/packages/core/dist/verification.js.map +1 -1
  390. package/packages/core/dist/workflow-gate/evidence-packet.d.ts +24 -0
  391. package/packages/core/dist/workflow-gate/evidence-packet.js +182 -0
  392. package/packages/core/dist/workflow-gate/evidence-packet.js.map +1 -0
  393. package/packages/core/dist/workflow-gate/hard-checks.d.ts +4 -0
  394. package/packages/core/dist/workflow-gate/hard-checks.js +130 -0
  395. package/packages/core/dist/workflow-gate/hard-checks.js.map +1 -0
  396. package/packages/core/dist/workflow-gate/policy.d.ts +4 -0
  397. package/packages/core/dist/workflow-gate/policy.js +146 -0
  398. package/packages/core/dist/workflow-gate/policy.js.map +1 -0
  399. package/packages/core/dist/workflow-gate/types.d.ts +89 -0
  400. package/packages/core/dist/workflow-gate/types.js +2 -0
  401. package/packages/core/dist/workflow-gate/types.js.map +1 -0
  402. package/packages/core/dist/workflow-state/affected-file-conflicts.d.ts +1 -0
  403. package/packages/core/dist/workflow-state/affected-file-conflicts.js +16 -1
  404. package/packages/core/dist/workflow-state/affected-file-conflicts.js.map +1 -1
  405. package/packages/core/dist/workflow-state/dependencies.d.ts +8 -4
  406. package/packages/core/dist/workflow-state/dependencies.js +25 -11
  407. package/packages/core/dist/workflow-state/dependencies.js.map +1 -1
  408. package/packages/core/dist/workflow-state/latest-eligible-run.d.ts +38 -0
  409. package/packages/core/dist/workflow-state/latest-eligible-run.js +122 -0
  410. package/packages/core/dist/workflow-state/latest-eligible-run.js.map +1 -0
  411. package/packages/core/dist/workflow-state/resolve.d.ts +27 -0
  412. package/packages/core/dist/workflow-state/resolve.js +166 -37
  413. package/packages/core/dist/workflow-state/resolve.js.map +1 -1
  414. package/packages/core/dist/workflow-state.d.ts +1 -0
  415. package/packages/core/dist/workflow-state.js +1 -0
  416. package/packages/core/dist/workflow-state.js.map +1 -1
  417. package/packages/core/package.json +1 -1
@@ -5,6 +5,7 @@ import { tmpdir } from 'node:os';
5
5
  import path from 'node:path';
6
6
 
7
7
  import { validTaskMarkdown } from '../test-support/fixtures.js';
8
+ import { hashTasksContract } from './document-hashes.js';
8
9
  import { inspectSddTask } from './task-inspection.js';
9
10
  import { parseSddBranch, parseSddTasksMarkdown } from './task-parser.js';
10
11
  import { renderTaskGapReport } from './task-rendering.js';
@@ -21,6 +22,11 @@ wave: 1
21
22
  depends_on: []
22
23
  affected_files:
23
24
  - packages/core/src/index.ts
25
+ change_surface: backend_only
26
+ implementation_wave: wave-1
27
+ validation_batch: backend-unit-wave-1
28
+ validation_timing: batch_end
29
+ requires_verify_before_next: false
24
30
  validation:
25
31
  - npm test => AC-1, AC-2
26
32
  risk:
@@ -49,6 +55,11 @@ None yet.
49
55
  assert.equal(model.tasks[0].wave, 1);
50
56
  assert.deepEqual(model.tasks[0].dependsOn, []);
51
57
  assert.deepEqual(model.tasks[0].affectedFiles, ['packages/core/src/index.ts']);
58
+ assert.equal(model.tasks[0].changeSurface, 'backend_only');
59
+ assert.equal(model.tasks[0].implementationWave, 'wave-1');
60
+ assert.equal(model.tasks[0].validationBatch, 'backend-unit-wave-1');
61
+ assert.equal(model.tasks[0].validationTiming, 'batch_end');
62
+ assert.equal(model.tasks[0].requiresVerifyBeforeNext, false);
52
63
  assert.deepEqual(model.tasks[0].validation, ['npm test']);
53
64
  assert.deepEqual(model.tasks[0].validationCommands, [{ command: 'npm test', acceptanceRefs: ['AC-1', 'AC-2'], raw: 'npm test => AC-1, AC-2' }]);
54
65
  assert.deepEqual(model.tasks[0].risk, ['parser boundary']);
@@ -56,6 +67,134 @@ None yet.
56
67
  assert.deepEqual(model.tasks[0].acceptance, ['Task metadata is structured.', 'Boundary is retained.']);
57
68
  });
58
69
 
70
+ test('parseSddTasksMarkdown blocks backend build validation for frontend-only tasks', () => {
71
+ const markdown = `# Tasks
72
+
73
+ ### T23: JSP rendering copy update
74
+
75
+ \`\`\`sdd-task
76
+ id: T23
77
+ status: pending
78
+ wave: 1
79
+ depends_on: []
80
+ affected_files:
81
+ - emp-upms/emp-upms-server/src/main/webapp/WEB-INF/views/demo.jsp
82
+ - emp-upms/emp-upms-server/src/main/webapp/static/img/banner.svg
83
+ validation:
84
+ - mvn compile -Ptest -pl emp-upms/emp-upms-server -am
85
+ risk: []
86
+ \`\`\`
87
+
88
+ #### Boundary
89
+
90
+ Only JSP copy and static image rendering.
91
+
92
+ #### Acceptance
93
+
94
+ - JSP copy renders correctly.
95
+ `;
96
+ const model = parseSddTasksMarkdown(markdown, { tasksPath: 'specs/master/tasks.md' });
97
+
98
+ assert.equal(model.gaps.some((gap) => gap.taskId === 'T23' && gap.field === 'validation' && /frontend-only/.test(gap.message)), true);
99
+ assert.equal(model.gaps.some((gap) => /Maven\/Gradle/.test(gap.recommendation)), true);
100
+ });
101
+
102
+ test('parseSddTasksMarkdown validates Phase 8.19 batch contract fields', () => {
103
+ const markdown = `# Tasks
104
+
105
+ ### T24: Invalid batch contract
106
+
107
+ \`\`\`sdd-task
108
+ id: T24
109
+ status: pending
110
+ wave: 1
111
+ depends_on: []
112
+ affected_files:
113
+ - packages/core/src/index.ts
114
+ change_surface: api_only
115
+ validation_timing: batch_end
116
+ requires_verify_before_next: sometimes
117
+ validation:
118
+ - npm test
119
+ risk: []
120
+ \`\`\`
121
+
122
+ #### Boundary
123
+
124
+ Stay in parser scope.
125
+
126
+ #### Acceptance
127
+
128
+ - Parser blocks invalid batch contract.
129
+ `;
130
+ const model = parseSddTasksMarkdown(markdown, { tasksPath: 'specs/master/tasks.md' });
131
+ const fields = model.gaps.map((gap) => gap.field);
132
+
133
+ assert.equal(fields.includes('change_surface'), true);
134
+ assert.equal(fields.includes('validation_batch'), true);
135
+ assert.equal(fields.includes('requires_verify_before_next'), true);
136
+ });
137
+
138
+ test('hashTasksContract includes Phase 8.19 validation grouping fields', () => {
139
+ const base = `# Tasks
140
+
141
+ ### T1: Hash grouping
142
+
143
+ \`\`\`sdd-task
144
+ id: T1
145
+ status: pending
146
+ wave: 1
147
+ depends_on: []
148
+ affected_files:
149
+ - packages/core/src/index.ts
150
+ change_surface: backend_only
151
+ implementation_wave: wave-1
152
+ validation_batch: batch-a
153
+ validation_timing: batch_end
154
+ requires_verify_before_next: false
155
+ validation:
156
+ - npm test
157
+ risk: []
158
+ \`\`\`
159
+
160
+ #### Boundary
161
+
162
+ Stay in parser scope.
163
+
164
+ #### Acceptance
165
+
166
+ - Hash includes validation grouping.
167
+ `;
168
+ const changed = base.replace('validation_batch: batch-a', 'validation_batch: batch-b');
169
+
170
+ assert.notEqual(hashTasksContract(base), hashTasksContract(changed));
171
+ });
172
+
173
+ test('parseSddBranch separates raw doc hash from semantic tasks contract hash', async () => {
174
+ const root = await mkdtemp(path.join(tmpdir(), 'sdd-contract-hash-'));
175
+ try {
176
+ const branchDir = path.join(root, 'specs', 'feature');
177
+ await mkdir(branchDir, { recursive: true });
178
+ await writeFile(path.join(branchDir, 'spec.md'), '# Spec\n', 'utf8');
179
+ await writeFile(path.join(branchDir, 'plan.md'), '# Plan\n', 'utf8');
180
+ const original = validTaskMarkdown('T1', []);
181
+ await writeFile(path.join(branchDir, 'tasks.md'), original, 'utf8');
182
+ const base = await parseSddBranch(root, 'feature');
183
+
184
+ await writeFile(path.join(branchDir, 'tasks.md'), `${original}\n\n<!-- formatting-only note -->\n`, 'utf8');
185
+ const formattingOnly = await parseSddBranch(root, 'feature');
186
+
187
+ await writeFile(path.join(branchDir, 'tasks.md'), original.replace('risk: []', 'risk:\n - security'), 'utf8');
188
+ const semanticChange = await parseSddBranch(root, 'feature');
189
+
190
+ assert.notEqual(formattingOnly.documents.tasksHash, base.documents.tasksHash);
191
+ assert.equal(formattingOnly.documents.tasksContractHash, base.documents.tasksContractHash);
192
+ assert.notEqual(semanticChange.documents.tasksContractHash, base.documents.tasksContractHash);
193
+ } finally {
194
+ await rm(root, { recursive: true, force: true });
195
+ }
196
+ });
197
+
59
198
  test('parseSddTasksMarkdown does not leak companion sections across indented task headings', () => {
60
199
  const markdown = `# Tasks
61
200
 
@@ -1,10 +1,12 @@
1
- import { createHash } from 'node:crypto';
1
+ import { hashDocumentContent, hashSemanticDocument, hashTasksContract, documentHashMatches } from './document-hashes.js';
2
2
  import { readdir, readFile } from 'node:fs/promises';
3
3
  import path from 'node:path';
4
4
  import { assertSafePathSegment } from '../path-safety.js';
5
5
  import { exists } from '../storage/json-io.js';
6
6
 
7
7
  export type SddTaskStatus = 'pending' | 'in_progress' | 'completed' | 'blocked' | 'deferred' | 'unknown';
8
+ export type SddChangeSurface = 'frontend_only' | 'backend_only' | 'full_stack' | 'docs_only' | 'config_only' | 'unknown';
9
+ export type SddValidationTiming = 'task_end' | 'batch_end' | 'wave_end';
8
10
  export type SddGapSeverity = 'blocking' | 'warning';
9
11
  export type SddGapType = 'Document Gap' | 'Task Gap' | 'Dependency Gap';
10
12
 
@@ -26,6 +28,11 @@ export interface SddTask {
26
28
  title: string | null;
27
29
  status: SddTaskStatus;
28
30
  wave: number | null;
31
+ implementationWave: string | null;
32
+ validationBatch: string | null;
33
+ validationTiming: SddValidationTiming;
34
+ requiresVerifyBeforeNext: boolean;
35
+ changeSurface: SddChangeSurface;
29
36
  dependsOn: string[];
30
37
  affectedFiles: string[];
31
38
  validation: string[];
@@ -71,9 +78,20 @@ export interface SddTaskModel {
71
78
  planHash?: string | null;
72
79
  tasksHash?: string | null;
73
80
  verifyHash?: string | null;
81
+ specDocHash?: string | null;
82
+ planDocHash?: string | null;
83
+ tasksDocHash?: string | null;
84
+ verifyDocHash?: string | null;
85
+ specContractHash?: string | null;
86
+ planContractHash?: string | null;
87
+ tasksContractHash?: string | null;
88
+ verifyContractHash?: string | null;
74
89
  planBasedOnSpecHash?: string | null;
75
90
  tasksBasedOnPlanHash?: string | null;
76
91
  verifyBasedOnTasksHash?: string | null;
92
+ planBasedOnSpecContractHash?: string | null;
93
+ tasksBasedOnPlanContractHash?: string | null;
94
+ verifyBasedOnTasksContractHash?: string | null;
77
95
  planStale?: boolean;
78
96
  tasksStale?: boolean;
79
97
  verifyStale?: boolean;
@@ -99,13 +117,15 @@ export async function parseSddBranch(projectRoot: string, branch = 'master'): Pr
99
117
  const gaps: SddTaskGap[] = [];
100
118
 
101
119
  if (documents.planStale) {
102
- gaps.push(documentGap('plan.md', `Plan document is stale because based_on_spec_hash ${documents.planBasedOnSpecHash} no longer matches current spec hash ${documents.specHash}.`, 'Re-run /sdd:plan for this partition before updating tasks or executing implementation.'));
120
+ gaps.push(documentGap('plan.md', `Plan document is stale because based_on_spec_hash ${documents.planBasedOnSpecHash} no longer matches current spec hash ${documents.specHash}.`, 'Refresh the plan stage for this partition before updating tasks or executing implementation.'));
103
121
  }
104
122
  if (documents.tasksStale) {
105
- gaps.push(documentGap('tasks.md', `Tasks document is stale because based_on_plan_hash ${documents.tasksBasedOnPlanHash} no longer matches current plan hash ${documents.planHash}.`, 'Re-run /sdd:tasks for this partition before executing implementation.'));
123
+ gaps.push(documentGap('tasks.md', `Tasks document is stale because based_on_plan_hash ${documents.tasksBasedOnPlanHash} no longer matches current plan hash ${documents.planHash}.`, 'Refresh the tasks stage for this partition before executing implementation.'));
106
124
  }
107
125
  if (documents.verifyStale) {
108
- gaps.push(documentGap('verify.md', `Verify document is stale because based_on_tasks_hash ${documents.verifyBasedOnTasksHash} no longer matches current tasks hash ${documents.tasksHash}.`, 'Run /sdd:test for this partition so the test gate can refresh or block on the verification contract.'));
126
+ const staleBoundary = documents.verifyBasedOnTasksContractHash ? 'tasks contract hash' : 'tasks contract hash binding';
127
+ const currentHash = documents.verifyBasedOnTasksContractHash ? documents.tasksContractHash : 'required';
128
+ gaps.push(documentGap('verify.md', `Verify document is stale because based_on_${staleBoundary.replace(/ /g, '_')} ${documents.verifyBasedOnTasksContractHash ?? 'missing'} no longer matches current ${staleBoundary} ${currentHash}.`, 'Run /sdd:tasks or explicit sdd verifies write recovery before /sdd:test.'));
109
129
  }
110
130
  if (!specExists) {
111
131
  gaps.push(documentGap('spec.md', 'Spec document is missing.', 'Create or restore specs/<branch>/spec.md before full SDD execution.'));
@@ -224,6 +244,11 @@ export function parseSddTasksMarkdown(raw: string, options: { branch?: string; t
224
244
  title: heading?.title ?? null,
225
245
  status: parseTaskStatus(scalarValue(metadata.status)),
226
246
  wave: parseWave(scalarValue(metadata.wave)),
247
+ implementationWave: scalarValue(metadata.implementation_wave),
248
+ validationBatch: scalarValue(metadata.validation_batch),
249
+ validationTiming: parseValidationTiming(scalarValue(metadata.validation_timing)),
250
+ requiresVerifyBeforeNext: parseRequiresVerifyBeforeNext(scalarValue(metadata.requires_verify_before_next)),
251
+ changeSurface: parseChangeSurface(scalarValue(metadata.change_surface)),
227
252
  dependsOn: listValue(metadata.depends_on),
228
253
  affectedFiles: listValue(metadata.affected_files),
229
254
  validation: parseValidationCommands(metadata.validation).map((command) => command.command),
@@ -256,50 +281,71 @@ export function parseSddTasksMarkdown(raw: string, options: { branch?: string; t
256
281
  }
257
282
 
258
283
  function buildDocumentChainState(input: { specExists: boolean; planExists: boolean; tasksExists: boolean; verifyExists: boolean; rawSpec: string | null; rawPlan: string | null; rawTasks: string | null; rawVerify: string | null }): SddTaskModel['documents'] {
259
- const specHash = input.rawSpec === null ? null : hashDocumentContent(input.rawSpec);
260
- const planHash = input.rawPlan === null ? null : hashDocumentContent(input.rawPlan);
261
- const tasksHash = input.rawTasks === null ? null : hashDocumentContent(input.rawTasks);
262
- const verifyHash = input.rawVerify === null ? null : hashDocumentContent(input.rawVerify);
284
+ const specDocHash = input.rawSpec === null ? null : hashDocumentContent(input.rawSpec);
285
+ const planDocHash = input.rawPlan === null ? null : hashDocumentContent(input.rawPlan);
286
+ const tasksDocHash = input.rawTasks === null ? null : hashDocumentContent(input.rawTasks);
287
+ const verifyDocHash = input.rawVerify === null ? null : hashDocumentContent(input.rawVerify);
288
+ const specContractHash = hashSemanticDocument(input.rawSpec);
289
+ const planContractHash = hashSemanticDocument(input.rawPlan);
290
+ const tasksContractHash = hashTasksContract(input.rawTasks);
291
+ const verifyContractHash = hashSemanticDocument(input.rawVerify);
263
292
  const planBasedOnSpecHash = input.rawPlan === null ? null : readDocumentScalar(input.rawPlan, 'based_on_spec_hash');
264
293
  const tasksBasedOnPlanHash = input.rawTasks === null ? null : readDocumentScalar(input.rawTasks, 'based_on_plan_hash');
265
294
  const verifyBasedOnTasksHash = input.rawVerify === null ? null : readDocumentScalar(input.rawVerify, 'based_on_tasks_hash');
266
-
267
- const planStale = Boolean(planBasedOnSpecHash && specHash && !documentHashMatches(planBasedOnSpecHash, specHash));
268
- const tasksHashMismatch = Boolean(tasksBasedOnPlanHash && planHash && !documentHashMatches(tasksBasedOnPlanHash, planHash));
269
- const verifyHashMismatch = Boolean(verifyBasedOnTasksHash && tasksHash && !documentHashMatches(verifyBasedOnTasksHash, tasksHash));
295
+ const planBasedOnSpecContractHash = input.rawPlan === null ? null : readDocumentScalar(input.rawPlan, 'based_on_spec_contract_hash');
296
+ const tasksBasedOnPlanContractHash = input.rawTasks === null ? null : readDocumentScalar(input.rawTasks, 'based_on_plan_contract_hash');
297
+ const verifyBasedOnTasksContractHash = input.rawVerify === null ? null : readDocumentScalar(input.rawVerify, 'based_on_tasks_contract_hash');
298
+
299
+ const planStale = Boolean(
300
+ (planBasedOnSpecContractHash && specContractHash && !documentHashMatches(planBasedOnSpecContractHash, specContractHash))
301
+ || (!planBasedOnSpecContractHash && planBasedOnSpecHash && specDocHash && !documentHashMatches(planBasedOnSpecHash, specDocHash))
302
+ );
303
+ const tasksHashMismatch = Boolean(
304
+ (tasksBasedOnPlanContractHash && planContractHash && !documentHashMatches(tasksBasedOnPlanContractHash, planContractHash))
305
+ || (!tasksBasedOnPlanContractHash && tasksBasedOnPlanHash && planDocHash && !documentHashMatches(tasksBasedOnPlanHash, planDocHash))
306
+ );
307
+ const verifyHashMismatch = Boolean(
308
+ input.rawVerify !== null && (
309
+ !verifyBasedOnTasksContractHash
310
+ || (verifyBasedOnTasksContractHash && tasksContractHash && !documentHashMatches(verifyBasedOnTasksContractHash, tasksContractHash))
311
+ )
312
+ );
270
313
 
271
314
  return {
272
315
  specExists: input.specExists,
273
316
  planExists: input.planExists,
274
317
  tasksExists: input.tasksExists,
275
318
  verifyExists: input.verifyExists,
276
- specHash,
277
- planHash,
278
- tasksHash,
279
- verifyHash,
319
+ specHash: specDocHash,
320
+ planHash: planDocHash,
321
+ tasksHash: tasksDocHash,
322
+ verifyHash: verifyDocHash,
323
+ specDocHash,
324
+ planDocHash,
325
+ tasksDocHash,
326
+ verifyDocHash,
327
+ specContractHash,
328
+ planContractHash,
329
+ tasksContractHash,
330
+ verifyContractHash,
280
331
  planBasedOnSpecHash,
281
332
  tasksBasedOnPlanHash,
282
333
  verifyBasedOnTasksHash,
334
+ planBasedOnSpecContractHash,
335
+ tasksBasedOnPlanContractHash,
336
+ verifyBasedOnTasksContractHash,
283
337
  planStale,
284
338
  tasksStale: planStale || tasksHashMismatch,
285
339
  verifyStale: planStale || tasksHashMismatch || verifyHashMismatch
286
340
  };
287
341
  }
288
342
 
289
- function hashDocumentContent(raw: string): string {
290
- return createHash('sha256').update(raw.replace(/\r\n/g, '\n'), 'utf8').digest('hex');
291
- }
292
-
293
343
  function readDocumentScalar(raw: string, key: string): string | null {
294
344
  const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
295
345
  const match = raw.match(new RegExp(`^\\s*(?:-\\s*)?${escapedKey}:\\s*(.+?)\\s*$`, 'm'));
296
346
  return match?.[1]?.trim().replace(/^["'`]|["'`]$/g, '') ?? null;
297
347
  }
298
348
 
299
- function documentHashMatches(expected: string, actual: string): boolean {
300
- return expected.replace(/^sha256:/, '') === actual;
301
- }
302
-
303
349
  async function parseRetainedPhaseTasks(specBranchDir: string): Promise<Pick<SddTaskModel, 'tasks' | 'gaps'>> {
304
350
  const entries = await readdir(specBranchDir, { withFileTypes: true });
305
351
  const taskFiles = entries
@@ -344,6 +390,36 @@ function parseWave(value: string | null): number | null {
344
390
  return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
345
391
  }
346
392
 
393
+ function parseChangeSurface(value: string | null): SddChangeSurface {
394
+ if (value === 'frontend_only' || value === 'backend_only' || value === 'full_stack' || value === 'docs_only' || value === 'config_only' || value === 'unknown') {
395
+ return value;
396
+ }
397
+ return 'unknown';
398
+ }
399
+
400
+ function parseValidationTiming(value: string | null): SddValidationTiming {
401
+ if (value === 'batch_end' || value === 'wave_end') {
402
+ return value;
403
+ }
404
+ return 'task_end';
405
+ }
406
+
407
+ function parseRequiresVerifyBeforeNext(value: string | null): boolean {
408
+ return value === 'false' ? false : true;
409
+ }
410
+
411
+ function isValidChangeSurface(value: string | null): boolean {
412
+ return value === null || value === 'frontend_only' || value === 'backend_only' || value === 'full_stack' || value === 'docs_only' || value === 'config_only' || value === 'unknown';
413
+ }
414
+
415
+ function isValidValidationTiming(value: string | null): boolean {
416
+ return value === null || value === 'task_end' || value === 'batch_end' || value === 'wave_end';
417
+ }
418
+
419
+ function isValidBooleanScalar(value: string | null): boolean {
420
+ return value === null || value === 'true' || value === 'false';
421
+ }
422
+
347
423
  function parseSimpleYamlBlock(raw: string): Record<string, string | string[]> {
348
424
  const result: Record<string, string | string[]> = {};
349
425
  const lines = raw.split(/\r?\n/);
@@ -499,11 +575,29 @@ function validateTask(task: SddTask): SddTaskGap[] {
499
575
  if (task.wave === null) {
500
576
  gaps.push(taskGap(task.id, 'wave', 'Task wave is missing or invalid.', 'Add a positive integer wave value.'));
501
577
  }
578
+ if (!isValidChangeSurface(scalarValue(task.rawMetadata.change_surface))) {
579
+ gaps.push(taskGap(task.id, 'change_surface', `Task ${task.id} has invalid change_surface.`, 'Use one of frontend_only, backend_only, full_stack, docs_only, config_only, unknown.'));
580
+ }
581
+ if (!isValidValidationTiming(scalarValue(task.rawMetadata.validation_timing))) {
582
+ gaps.push(taskGap(task.id, 'validation_timing', `Task ${task.id} has invalid validation_timing.`, 'Use one of task_end, batch_end, wave_end.'));
583
+ }
584
+ if (!isValidBooleanScalar(scalarValue(task.rawMetadata.requires_verify_before_next))) {
585
+ gaps.push(taskGap(task.id, 'requires_verify_before_next', `Task ${task.id} has invalid requires_verify_before_next.`, 'Use true or false.'));
586
+ }
587
+ if ((task.validationTiming === 'batch_end' || task.validationTiming === 'wave_end') && !task.validationBatch) {
588
+ gaps.push(taskGap(task.id, 'validation_batch', `Task ${task.id} uses ${task.validationTiming} but has no validation_batch.`, 'Declare validation_batch so batch/wave validation can group implementation evidence before /sdd:test.'));
589
+ }
590
+ if ((task.validationTiming === 'batch_end' || task.validationTiming === 'wave_end') && task.requiresVerifyBeforeNext) {
591
+ gaps.push(taskGap(task.id, 'requires_verify_before_next', `Task ${task.id} uses ${task.validationTiming} but requires verify before next.`, 'Set requires_verify_before_next: false for batch/wave validation, or use validation_timing: task_end for strict validation.'));
592
+ }
502
593
  for (const [property, field] of requiredLists) {
503
594
  if ((task[property] as unknown[]).length === 0) {
504
595
  gaps.push(taskGap(task.id, field, `Task ${task.id} has no ${field}.`, `Declare ${field} in the sdd-task block before implementation.`));
505
596
  }
506
597
  }
598
+ if ((task.changeSurface === 'frontend_only' || isFrontendOnlyTask(task)) && task.validation.some(isBackendBuildValidationCommand)) {
599
+ gaps.push(taskGap(task.id, 'validation', `Task ${task.id} is frontend-only but declares backend build validation.`, 'For JSP/static frontend-only changes, replace Maven/Gradle validation with frontend-appropriate checks, dev-server/manual page evidence, lint/typecheck, or an explicit unavailable reason.'));
600
+ }
507
601
  if (!task.boundary) {
508
602
  gaps.push(taskGap(task.id, 'Boundary', `Task ${task.id} has no Boundary section.`, 'Add a #### Boundary section describing allowed and forbidden scope.'));
509
603
  }
@@ -513,6 +607,25 @@ function validateTask(task: SddTask): SddTaskGap[] {
513
607
  return gaps;
514
608
  }
515
609
 
610
+ export function isFrontendOnlyTask(task: SddTask): boolean {
611
+ return task.affectedFiles.length > 0 && task.affectedFiles.every(isFrontendOnlyPath);
612
+ }
613
+
614
+ function isFrontendOnlyPath(filePath: string): boolean {
615
+ const normalized = filePath.toLowerCase().replace(/\\/g, '/');
616
+ return /\.(jsp|html|htm|css|scss|sass|less|js|jsx|ts|tsx|vue|svelte|png|jpg|jpeg|gif|svg|webp|ico)$/.test(normalized)
617
+ && !normalized.includes('/src/main/java/')
618
+ && !normalized.includes('/src/test/java/')
619
+ && !normalized.includes('/pom.xml')
620
+ && !normalized.endsWith('pom.xml')
621
+ && !normalized.endsWith('build.gradle')
622
+ && !normalized.endsWith('build.gradle.kts');
623
+ }
624
+
625
+ export function isBackendBuildValidationCommand(command: string): boolean {
626
+ return /(^|\s)(mvn|maven|mvnw|\.\/mvnw|gradle|gradlew|\.\/gradlew)(\s|$)|\b(maven_compile|gradle_build)\b/i.test(command);
627
+ }
628
+
516
629
  function taskGap(taskId: string, field: string, message: string, recommendation: string): SddTaskGap {
517
630
  return {
518
631
  type: 'Task Gap',