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
@@ -9,6 +9,7 @@ import type { SddTask, SddTaskModel, SddTaskStatus } from '../sdd-docs/task-pars
9
9
  import { inspectSyncBack } from './inspect.js';
10
10
  import type { SyncBackInspection } from './inspect.js';
11
11
  import { writeVerifyContract } from '../verification/verify-contract.js';
12
+ import { readRuntimeSyncBackDecision, recordRuntimeSyncBackDecision, runtimeScopedId } from '../storage/runtime-store.js';
12
13
 
13
14
  export interface SyncBackApplyResult {
14
15
  runId: string;
@@ -74,6 +75,22 @@ export async function applySyncBack(projectRoot: string, options: { runId?: stri
74
75
  status: 'applied'
75
76
  }
76
77
  });
78
+ const existingDecision = await readRuntimeSyncBackDecision(projectRoot, state.runId, inspection.taskId);
79
+ const decisionTime = new Date().toISOString();
80
+ await recordRuntimeSyncBackDecision(projectRoot, {
81
+ decisionId: existingDecision?.decisionId ?? runtimeScopedId(state.runId, inspection.taskId, 'sync-back'),
82
+ runId: state.runId,
83
+ branch: inspection.branch,
84
+ taskId: inspection.taskId,
85
+ status: 'applied',
86
+ proposalPath: inspection.proposalPath,
87
+ proposalDigest: inspection.proposalDigest,
88
+ proposalPayloadId: existingDecision?.proposalPayloadId ?? null,
89
+ reasons: [],
90
+ createdAt: existingDecision?.createdAt ?? decisionTime,
91
+ updatedAt: decisionTime,
92
+ payload: { previousStatus: existingDecision?.status ?? state.syncBack.status, tasksPath: path.relative(projectRoot, tasksPath) }
93
+ });
77
94
  await appendEvent(projectRoot, state.runId, {
78
95
  event: 'sync_back_applied',
79
96
  runId: state.runId,
@@ -109,8 +126,13 @@ function documentSnapshotFromModel(model: SddTaskModel): RunDocumentSnapshot {
109
126
  specHash: model.documents.specHash ?? null,
110
127
  planHash: model.documents.planHash ?? null,
111
128
  tasksHash: model.documents.tasksHash ?? null,
129
+ specContractHash: model.documents.specContractHash ?? null,
130
+ planContractHash: model.documents.planContractHash ?? null,
131
+ tasksContractHash: model.documents.tasksContractHash ?? null,
112
132
  planBasedOnSpecHash: model.documents.planBasedOnSpecHash ?? null,
113
- tasksBasedOnPlanHash: model.documents.tasksBasedOnPlanHash ?? null
133
+ tasksBasedOnPlanHash: model.documents.tasksBasedOnPlanHash ?? null,
134
+ planBasedOnSpecContractHash: model.documents.planBasedOnSpecContractHash ?? null,
135
+ tasksBasedOnPlanContractHash: model.documents.tasksBasedOnPlanContractHash ?? null
114
136
  };
115
137
  }
116
138
 
@@ -18,6 +18,10 @@ import { buildTaskRiskProfile } from '../task-risk-profile.js';
18
18
  import { inspectVerifyContract, type VerifyContractIssue, type VerifyContractStatus } from '../verification/verify-contract.js';
19
19
  import { evaluateLifecycleRiskDecisionForModel, inspectLifecycleRiskDecisionForModel, type LifecycleRiskConsumerDiagnostic } from '../risk.js';
20
20
  import { dependencyBlockingReasonsForTask } from '../workflow-state/dependencies.js';
21
+ import { listRuntimeTestRuns, readRuntimeSyncBackDecision } from '../storage/runtime-store.js';
22
+ import { readTaskEvidenceView, type TaskEvidenceView } from '../run-state/task-evidence.js';
23
+ import type { CapabilityEvidenceClassification } from '../evidence-runtime.js';
24
+ import { evaluateAndRecordWorkflowGateDecision } from '../workflow-gate/evidence-packet.js';
21
25
 
22
26
  export interface ResolvedTaskRun {
23
27
  runId: string;
@@ -28,6 +32,7 @@ export interface ResolvedTaskRun {
28
32
  explicitRunId: boolean;
29
33
  staleReasons: string[];
30
34
  affectedFileConflicts: WorkflowAffectedFileConflict[];
35
+ selectorRejectionReasons: string[];
31
36
  }
32
37
 
33
38
  export type SyncBackInspectionStatus = 'ready' | 'blocked' | 'applied';
@@ -38,6 +43,20 @@ export interface SyncBackApplyPolicy {
38
43
  reasons: string[];
39
44
  }
40
45
 
46
+ export type SyncBackCapabilityReadinessStatus = 'not_recorded' | 'runtime_evidence_ready' | 'candidate_only' | 'blocked';
47
+
48
+ export interface SyncBackCapabilityReadiness {
49
+ status: SyncBackCapabilityReadinessStatus;
50
+ authoritativeForApply: false;
51
+ requiredDomains: string[];
52
+ accepted: string[];
53
+ candidate: string[];
54
+ quarantined: string[];
55
+ diagnostic: string[];
56
+ blocked: string[];
57
+ reason: string;
58
+ }
59
+
41
60
  export interface SyncBackApprovalCard {
42
61
  contract: 'sdd-sync-back-approval-card-v1';
43
62
  scope: {
@@ -54,6 +73,7 @@ export interface SyncBackApprovalCard {
54
73
  digestValid: boolean | null;
55
74
  };
56
75
  approval: SyncBackApplyPolicy;
76
+ capabilityReadiness: SyncBackCapabilityReadiness;
57
77
  blockers: string[];
58
78
  staleReasons: string[];
59
79
  affectedFileConflicts: Array<{
@@ -69,6 +89,7 @@ export interface SyncBackApprovalCard {
69
89
  verifyContractIssues: VerifyContractIssue[];
70
90
  staleVerifyRecoveryCommand: string | null;
71
91
  lifecycleRisk: LifecycleRiskConsumerDiagnostic;
92
+ workflowGateDecision: TaskEvidenceView['workflowGate']['latestDecision'];
72
93
  }
73
94
 
74
95
  export interface SyncBackInspection {
@@ -89,12 +110,15 @@ export interface SyncBackInspection {
89
110
  gaps: SddTaskGap[];
90
111
  applyPolicy: SyncBackApplyPolicy;
91
112
  approvalCard: SyncBackApprovalCard;
113
+ capabilityReadiness: SyncBackCapabilityReadiness;
92
114
  staleReasons: string[];
93
115
  affectedFileConflicts: WorkflowAffectedFileConflict[];
94
116
  verifyContractStatus: VerifyContractStatus;
95
117
  verifyContractIssues: VerifyContractIssue[];
96
118
  staleVerifyRecoveryCommand: string | null;
97
119
  lifecycleRisk: LifecycleRiskConsumerDiagnostic;
120
+ workflowGateDecision: TaskEvidenceView['workflowGate']['latestDecision'];
121
+ taskEvidenceView: TaskEvidenceView;
98
122
  }
99
123
 
100
124
  export async function resolveTaskRun(projectRoot: string, options: { runId?: string; branch?: string; taskId: string }): Promise<ResolvedTaskRun> {
@@ -119,7 +143,8 @@ export async function resolveTaskRun(projectRoot: string, options: { runId?: str
119
143
  task: inspected.task,
120
144
  explicitRunId: true,
121
145
  staleReasons: await runDocumentStaleReasons(projectRoot, state, model),
122
- affectedFileConflicts: await affectedFileConflictsForRun(projectRoot, state)
146
+ affectedFileConflicts: await affectedFileConflictsForRun(projectRoot, state),
147
+ selectorRejectionReasons: []
123
148
  };
124
149
  }
125
150
 
@@ -129,19 +154,27 @@ export async function resolveTaskRun(projectRoot: string, options: { runId?: str
129
154
  taskId: options.taskId
130
155
  });
131
156
  const inspected = inspectSddTask(workflow.model, options.taskId);
132
- const candidate = workflow.latestRunsByTask.find((entry) => entry.taskId === options.taskId);
133
- if (!candidate || !workflow.latestRunState) {
157
+ const selection = workflow.latestEligibleRunsByTask.find((entry) => entry.taskId === options.taskId);
158
+ const candidate = selection?.selected ?? selection?.rejected[0] ?? null;
159
+ if (!candidate) {
134
160
  throw new Error(`No eligible run found for ${workflow.context.partition}/${options.taskId}. Run sdd do task ${options.taskId} first, or pass --run <run_id>.`);
135
161
  }
162
+ const state = selection?.selected && workflow.latestRunState && selection.selected.runId === workflow.latestRunState.runId
163
+ ? workflow.latestRunState
164
+ : await readRunState(projectRoot, candidate.runId);
165
+ if (!state) {
166
+ throw new Error(`Run state ${candidate.runId} is unavailable for ${workflow.context.partition}/${options.taskId}. Pass --run <run_id> or rerun the task.`);
167
+ }
136
168
  return {
137
- runId: workflow.latestRunState.runId,
138
- state: workflow.latestRunState,
169
+ runId: state.runId,
170
+ state,
139
171
  context: workflow.context,
140
172
  model: workflow.model,
141
173
  task: inspected.task,
142
174
  explicitRunId: false,
143
- staleReasons: await runDocumentStaleReasons(projectRoot, workflow.latestRunState, workflow.model),
144
- affectedFileConflicts: workflow.affectedFileConflicts
175
+ staleReasons: await runDocumentStaleReasons(projectRoot, state, workflow.model),
176
+ affectedFileConflicts: workflow.affectedFileConflicts,
177
+ selectorRejectionReasons: selection?.selected ? [] : candidate.reasons
145
178
  };
146
179
  }
147
180
 
@@ -155,8 +188,17 @@ export async function inspectSyncBack(projectRoot: string, options: { runId?: st
155
188
  const branch = resolved.context.partition;
156
189
  const state = resolved.state;
157
190
  const model = resolved.model;
191
+ const syncBackDecision = await readRuntimeSyncBackDecision(projectRoot, state.runId, taskId);
192
+ const taskEvidenceView = await readTaskEvidenceView(projectRoot, { branch, taskId });
193
+ const workflowGateDecision = (await evaluateAndRecordWorkflowGateDecision(projectRoot, { branch, taskId, runId: state.runId, decisionKind: 'sync_back' })).decision;
158
194
  const inspected = inspectSddTask(model, taskId);
159
195
  const reasons: string[] = [];
196
+ if (workflowGateDecision.status === 'BLOCKED') {
197
+ reasons.push(...syncBackWorkflowGateReasons(workflowGateDecision, resolved.explicitRunId));
198
+ }
199
+ if (workflowGateDecision.status === 'HUMAN_REQUIRED') {
200
+ reasons.push(...workflowGateDecision.reasons.map((reason) => `Workflow gate requires human decision before sync-back: ${reason}`));
201
+ }
160
202
  const markdownTask = inspected.task;
161
203
  const taskGaps = inspected.gaps;
162
204
  if (!inspected.task) {
@@ -168,6 +210,9 @@ export async function inspectSyncBack(projectRoot: string, options: { runId?: st
168
210
  for (const reason of resolved.staleReasons) {
169
211
  reasons.push(reason);
170
212
  }
213
+ for (const reason of resolved.selectorRejectionReasons) {
214
+ reasons.push(reason);
215
+ }
171
216
  for (const conflict of resolved.affectedFileConflicts) {
172
217
  reasons.push(`Affected file ${conflict.file} is active in run ${conflict.runId} for ${conflict.partition}/${conflict.taskId}.`);
173
218
  }
@@ -175,8 +220,8 @@ export async function inspectSyncBack(projectRoot: string, options: { runId?: st
175
220
  const verifyContract = await inspectVerifyContract(projectRoot, { branch, branchSource: 'cli_option' });
176
221
  const blockingVerifyIssues = verifyContract.status === 'PASS' ? [] : verifyContract.issues;
177
222
  const staleVerifyRecoveryCommand = verifyContract.status === 'PASS' ? null : `sdd verifies write --branch ${branch} --force && sdd sync-back inspect ${state.runId} --branch ${branch} --task ${taskId}`;
178
- const proposalPath = state.syncBack.proposalPath;
179
- const expectedProposalDigest = state.syncBack.proposalDigest ?? null;
223
+ const proposalPath = syncBackDecision?.proposalPath ?? state.syncBack.proposalPath;
224
+ const expectedProposalDigest = syncBackDecision?.proposalDigest ?? state.syncBack.proposalDigest ?? null;
180
225
  let proposal: string | null = null;
181
226
  let proposalDigestValid: boolean | null = null;
182
227
  if (!proposalPath) {
@@ -215,7 +260,10 @@ export async function inspectSyncBack(projectRoot: string, options: { runId?: st
215
260
  applyPolicy = requireSyncBackApproval(applyPolicy, `Current Git branch is ${resolved.context.currentGitBranch}, but run ${state.runId} belongs to ${state.gitBranch}.`);
216
261
  }
217
262
 
218
- const status: SyncBackInspectionStatus = state.syncBack.status === 'applied' ? 'applied' : reasons.length === 0 ? 'ready' : 'blocked';
263
+ const capabilityReadiness = await inspectSyncBackCapabilityReadiness(projectRoot, state.runId, taskId, state.validation.status);
264
+ const capabilityReadinessReasons = syncBackCapabilityReadinessReasons(capabilityReadiness);
265
+ reasons.push(...capabilityReadinessReasons);
266
+ const status: SyncBackInspectionStatus = (syncBackDecision?.status ?? state.syncBack.status) === 'applied' ? 'applied' : reasons.length === 0 ? 'ready' : 'blocked';
219
267
  const artifacts = state.validation.evidence.length > 0 ? state.validation.evidence : state.artifacts.map((artifact) => artifact.path);
220
268
  const gaps = [...taskGaps, ...runtimeGaps];
221
269
 
@@ -236,6 +284,7 @@ export async function inspectSyncBack(projectRoot: string, options: { runId?: st
236
284
  artifacts,
237
285
  gaps,
238
286
  applyPolicy,
287
+ capabilityReadiness,
239
288
  approvalCard: buildSyncBackApprovalCard({
240
289
  runId: state.runId,
241
290
  branch,
@@ -252,14 +301,18 @@ export async function inspectSyncBack(projectRoot: string, options: { runId?: st
252
301
  verifyContractStatus: verifyContract.status,
253
302
  verifyContractIssues: blockingVerifyIssues,
254
303
  staleVerifyRecoveryCommand,
255
- lifecycleRisk
304
+ lifecycleRisk,
305
+ capabilityReadiness,
306
+ workflowGateDecision
256
307
  }),
257
308
  staleReasons: resolved.staleReasons,
258
309
  affectedFileConflicts: resolved.affectedFileConflicts,
259
310
  verifyContractStatus: verifyContract.status,
260
311
  verifyContractIssues: blockingVerifyIssues,
261
312
  staleVerifyRecoveryCommand,
262
- lifecycleRisk
313
+ lifecycleRisk,
314
+ workflowGateDecision,
315
+ taskEvidenceView
263
316
  };
264
317
  }
265
318
 
@@ -280,6 +333,8 @@ function buildSyncBackApprovalCard(input: {
280
333
  verifyContractIssues: VerifyContractIssue[];
281
334
  staleVerifyRecoveryCommand: string | null;
282
335
  lifecycleRisk: LifecycleRiskConsumerDiagnostic;
336
+ capabilityReadiness: SyncBackCapabilityReadiness;
337
+ workflowGateDecision: TaskEvidenceView['workflowGate']['latestDecision'];
283
338
  }): SyncBackApprovalCard {
284
339
  return {
285
340
  contract: 'sdd-sync-back-approval-card-v1',
@@ -297,6 +352,7 @@ function buildSyncBackApprovalCard(input: {
297
352
  digestValid: input.proposalDigestValid
298
353
  },
299
354
  approval: input.applyPolicy,
355
+ capabilityReadiness: input.capabilityReadiness,
300
356
  blockers: input.reasons,
301
357
  staleReasons: input.staleReasons,
302
358
  affectedFileConflicts: input.affectedFileConflicts.map((conflict) => ({
@@ -311,10 +367,18 @@ function buildSyncBackApprovalCard(input: {
311
367
  verifyContractIssues: input.verifyContractIssues,
312
368
  staleVerifyRecoveryCommand: input.staleVerifyRecoveryCommand,
313
369
  lifecycleRisk: input.lifecycleRisk,
370
+ workflowGateDecision: input.workflowGateDecision,
314
371
  nextAction: syncBackApprovalNextAction(input.status, input.applyPolicy, input.runId, input.branch, input.taskId, input.staleVerifyRecoveryCommand, input.proposalPath)
315
372
  };
316
373
  }
317
374
 
375
+ function syncBackWorkflowGateReasons(decision: NonNullable<TaskEvidenceView['workflowGate']['latestDecision']>, explicitRunId: boolean): string[] {
376
+ return decision.hardBlocks
377
+ .filter((check) => check.code !== 'stale_documents' && check.code !== 'contract_hash_mismatch')
378
+ .filter((check) => !(explicitRunId && check.code === 'run_rejected'))
379
+ .map((check) => `Workflow gate blocked sync-back: ${check.code}: ${check.message}`);
380
+ }
381
+
318
382
  function syncBackApprovalRisk(status: SyncBackInspectionStatus, applyPolicy: SyncBackApplyPolicy): SyncBackApprovalCard['risk'] {
319
383
  if (status === 'blocked') {
320
384
  return 'blocked';
@@ -424,6 +488,75 @@ function syncBackTaskLifecycleRiskReasons(branch: string, model: SddTaskModel, t
424
488
  return [];
425
489
  }
426
490
 
491
+ async function inspectSyncBackCapabilityReadiness(projectRoot: string, runId: string, taskId: string, validationStatus: string): Promise<SyncBackCapabilityReadiness> {
492
+ const testRuns = await listRuntimeTestRuns(projectRoot, runId);
493
+ const latest = testRuns.find((run) => run.taskId === taskId);
494
+ const evidence = capabilityEvidenceFromPayload(latest?.payload);
495
+ if (evidence.length === 0) {
496
+ return {
497
+ status: 'not_recorded',
498
+ authoritativeForApply: false,
499
+ requiredDomains: [],
500
+ accepted: [],
501
+ candidate: [],
502
+ quarantined: [],
503
+ diagnostic: [],
504
+ blocked: [],
505
+ reason: 'No capability evidence classification was recorded for this sync-back candidate; apply readiness still depends on accepted runtime validation evidence.'
506
+ };
507
+ }
508
+ const professional = evidence.filter((item) => item.source === 'professional_capability');
509
+ const blockingEvidence = evidence.filter(isSyncBackBlockingCapabilityEvidence);
510
+ const readiness: SyncBackCapabilityReadiness = {
511
+ status: 'candidate_only',
512
+ authoritativeForApply: false,
513
+ requiredDomains: uniqueStrings(professional.map((item) => item.domainOrSourceId)),
514
+ accepted: evidenceNames(evidence, 'accepted'),
515
+ candidate: evidenceNames(evidence, 'candidate'),
516
+ quarantined: evidenceNames(evidence, 'quarantined'),
517
+ diagnostic: evidenceNames(evidence, 'diagnostic'),
518
+ blocked: evidenceNames(blockingEvidence, 'blocked'),
519
+ reason: 'Capability evidence is advisory for sync-back; task completion writeback is governed by accepted runtime validation evidence and apply policy.'
520
+ };
521
+ if (readiness.blocked.length > 0) {
522
+ return { ...readiness, status: 'blocked', reason: 'Blocked capability sources cannot authorize sync-back apply.' };
523
+ }
524
+ if (validationStatus === 'pass') {
525
+ return { ...readiness, status: 'runtime_evidence_ready', reason: 'Runtime validation evidence is accepted; capability evidence remains advisory and cannot mark completion by itself.' };
526
+ }
527
+ return readiness;
528
+ }
529
+
530
+ function syncBackCapabilityReadinessReasons(readiness: SyncBackCapabilityReadiness): string[] {
531
+ return readiness.status === 'blocked' ? [readiness.reason] : [];
532
+ }
533
+
534
+ function isSyncBackBlockingCapabilityEvidence(item: CapabilityEvidenceClassification): boolean {
535
+ return item.class === 'blocked' && (item.source === 'professional_capability' || item.acceptanceRefs.length > 0);
536
+ }
537
+
538
+ function capabilityEvidenceFromPayload(payload: unknown): CapabilityEvidenceClassification[] {
539
+ if (!isRecord(payload) || !Array.isArray(payload.capabilityEvidence)) {
540
+ return [];
541
+ }
542
+ return payload.capabilityEvidence.filter(isCapabilityEvidenceClassification);
543
+ }
544
+
545
+ function isCapabilityEvidenceClassification(value: unknown): value is CapabilityEvidenceClassification {
546
+ return isRecord(value)
547
+ && (value.class === 'accepted' || value.class === 'candidate' || value.class === 'quarantined' || value.class === 'diagnostic' || value.class === 'blocked')
548
+ && (value.source === 'professional_capability' || value.source === 'external_source' || value.source === 'runtime_diagnostic')
549
+ && typeof value.domainOrSourceId === 'string';
550
+ }
551
+
552
+ function evidenceNames(evidence: CapabilityEvidenceClassification[], evidenceClass: CapabilityEvidenceClassification['class']): string[] {
553
+ return uniqueStrings(evidence.filter((item) => item.class === evidenceClass).map((item) => `${item.source}:${item.domainOrSourceId}`));
554
+ }
555
+
556
+ function uniqueStrings(values: string[]): string[] {
557
+ return [...new Set(values)].sort((left, right) => left.localeCompare(right));
558
+ }
559
+
427
560
  function deriveSyncBackApplyPolicy(state: RunState, task: SddTask | null): SyncBackApplyPolicy {
428
561
  const reasons: string[] = [];
429
562
  const decision = state.lifecycleDecision?.decision;
@@ -18,12 +18,46 @@ import { bindTestRunState, markTestRunReadyForSyncBack } from '../test-support/r
18
18
  import { runGoalVerify } from '../verification/goal-verify.js';
19
19
  import { inspectVerifyContract, writeVerifyContract } from '../verification/verify-contract.js';
20
20
  import { runSingleTaskLoop } from '../verification/single-task-loop.js';
21
+ import { runSddTest } from '../verification/test-runtime.js';
21
22
  import { createDelegationRecord } from '../delegation/validation.js';
23
+ import { recordRuntimeTestRun } from '../storage/runtime-store.js';
22
24
  import { applySyncBack } from './apply.js';
23
25
  import { inspectSyncBack } from './inspect.js';
24
26
 
25
27
  const execFileAsync = promisify(execFile);
26
28
 
29
+ function capabilitySyncBackTaskMarkdown(taskId: string, command: string): string {
30
+ return `# Tasks
31
+
32
+ ### ${taskId}: Mapped validation task
33
+
34
+ \`\`\`sdd-task
35
+ id: ${taskId}
36
+ status: pending
37
+ wave: 1
38
+ depends_on: []
39
+ acceptance_refs:
40
+ - AC-1
41
+ plan_refs:
42
+ - "§4 Target Design Overview"
43
+ affected_files:
44
+ - docs/${taskId.toLowerCase()}.md
45
+ validation:
46
+ - ${command} => AC-1
47
+ risk:
48
+ - security
49
+ \`\`\`
50
+
51
+ #### Boundary
52
+
53
+ Stay in validation runtime fixtures only.
54
+
55
+ #### Acceptance
56
+
57
+ - AC-1: Parser behavior is covered.
58
+ `;
59
+ }
60
+
27
61
  test('sync-back inspect blocks modified proposal digest', async () => {
28
62
  const root = await mkdtemp(path.join(tmpdir(), 'sdd-syncback-digest-'));
29
63
  try {
@@ -96,6 +130,89 @@ test('sync-back apply requires approval for risky complex tasks', async () => {
96
130
  }
97
131
  });
98
132
 
133
+ test('sync-back inspect surfaces capability readiness without making capability evidence authoritative', async () => {
134
+ const root = await mkdtemp(path.join(tmpdir(), 'sdd-syncback-capability-readiness-'));
135
+ try {
136
+ await initProject(root);
137
+ await writeBranchDocs(root, 'feature', capabilitySyncBackTaskMarkdown('CAPABILITY', 'node -e "process.stdout.write(\'ok\')"'));
138
+ await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
139
+
140
+ const tested = await runSddTest(root, {
141
+ branch: 'feature',
142
+ taskId: 'CAPABILITY',
143
+ approved: true,
144
+ commands: ['node -e "process.stdout.write(\'ok\')"']
145
+ });
146
+ const testState = await readRunState(root, tested.runId);
147
+ assert.equal(tested.status, 'PASS');
148
+ assert.equal(tested.syncBackReady, false);
149
+ assert.equal(testState.syncBack.status, 'not_created');
150
+ await markTestRunReadyForSyncBack(root, tested.runId, 'CAPABILITY');
151
+ const syncBack = await inspectSyncBack(root, { runId: tested.runId, branch: 'feature', taskId: 'CAPABILITY' });
152
+
153
+ assert.equal(syncBack.status, 'ready');
154
+ assert.equal(syncBack.capabilityReadiness.status, 'runtime_evidence_ready');
155
+ assert.equal(syncBack.capabilityReadiness.authoritativeForApply, false);
156
+ assert.deepEqual(syncBack.capabilityReadiness.requiredDomains, ['security-engineering']);
157
+ assert.equal(syncBack.capabilityReadiness.candidate.some((item) => item.includes('security-engineering')), true);
158
+ assert.equal(syncBack.capabilityReadiness.quarantined.length > 0, true);
159
+ assert.deepEqual(syncBack.capabilityReadiness.accepted, []);
160
+ assert.deepEqual(syncBack.approvalCard.capabilityReadiness, syncBack.capabilityReadiness);
161
+ await assert.rejects(
162
+ () => applySyncBack(root, { runId: tested.runId, branch: 'feature', taskId: 'CAPABILITY' }),
163
+ /--approved/
164
+ );
165
+ } finally {
166
+ await rm(root, { recursive: true, force: true });
167
+ }
168
+ });
169
+
170
+ test('sync-back inspect blocks explicitly blocked capability readiness', async () => {
171
+ const root = await mkdtemp(path.join(tmpdir(), 'sdd-syncback-blocked-capability-readiness-'));
172
+ try {
173
+ await initProject(root);
174
+ await writeBranchDocs(root, 'feature', capabilitySyncBackTaskMarkdown('CAPABILITY', 'node -e "process.stdout.write(\'ok\')"'));
175
+ await writeVerifyContract(root, { branch: 'feature', branchSource: 'cli_option' });
176
+ const state = await createRun(root, { runId: 'run-1' });
177
+ await bindTestRunState(root, state.runId, 'feature', 'CAPABILITY');
178
+ await markTestRunReadyForSyncBack(root, state.runId, 'CAPABILITY');
179
+ const now = new Date().toISOString();
180
+ await recordRuntimeTestRun(root, {
181
+ testRunId: 'blocked-capability-test',
182
+ runId: state.runId,
183
+ partition: 'feature',
184
+ taskId: 'CAPABILITY',
185
+ status: 'PASS',
186
+ startedAt: now,
187
+ completedAt: now,
188
+ payload: {
189
+ capabilityEvidence: [{
190
+ class: 'blocked',
191
+ source: 'external_source',
192
+ domainOrSourceId: 'denied-source',
193
+ evidenceRefs: [],
194
+ acceptanceRefs: ['AC-1'],
195
+ provenanceRefs: [],
196
+ reason: 'Denied external capability source must not be used for sync-back.'
197
+ }]
198
+ }
199
+ });
200
+
201
+ const syncBack = await inspectSyncBack(root, { runId: state.runId, branch: 'feature', taskId: 'CAPABILITY' });
202
+
203
+ assert.equal(syncBack.status, 'blocked');
204
+ assert.equal(syncBack.capabilityReadiness.status, 'blocked');
205
+ assert.equal(syncBack.capabilityReadiness.blocked.includes('external_source:denied-source'), true);
206
+ assert.equal(syncBack.reasons.some((reason) => reason.includes('Blocked capability sources')), true);
207
+ await assert.rejects(
208
+ () => applySyncBack(root, { runId: state.runId, branch: 'feature', taskId: 'CAPABILITY' }),
209
+ /Blocked capability sources/
210
+ );
211
+ } finally {
212
+ await rm(root, { recursive: true, force: true });
213
+ }
214
+ });
215
+
99
216
  test('sync-back gates direct-safe task by task scope instead of branch lifecycle risk', async () => {
100
217
  const root = await mkdtemp(path.join(tmpdir(), 'sdd-syncback-task-scope-'));
101
218
  try {
@@ -234,7 +351,7 @@ test('sync-back inspect reports stale verify contract as diagnostic without bloc
234
351
  }
235
352
  });
236
353
 
237
- test('sync-back inspect reports missing verify contract as diagnostic without blocking ready task', async () => {
354
+ test('sync-back inspect blocks missing verify contract instead of treating it as ready', async () => {
238
355
  const root = await mkdtemp(path.join(tmpdir(), 'sdd-syncback-missing-verify-'));
239
356
  try {
240
357
  await initProject(root);
@@ -245,11 +362,11 @@ test('sync-back inspect reports missing verify contract as diagnostic without bl
245
362
 
246
363
  const syncBack = await inspectSyncBack(root, { runId: state.runId, branch: 'feature', taskId: 'T1' });
247
364
 
248
- assert.equal(syncBack.status, 'ready');
249
- assert.equal(syncBack.verifyContractStatus, 'WARN');
365
+ assert.equal(syncBack.status, 'blocked');
366
+ assert.equal(syncBack.verifyContractStatus, 'BLOCKED');
250
367
  assert.equal(syncBack.verifyContractIssues.some((issue) => issue.field === 'verify.md'), true);
251
368
  assert.match(syncBack.staleVerifyRecoveryCommand ?? '', /sdd verifies write --branch feature --force/);
252
- assert.equal(syncBack.reasons.some((reason) => reason.includes('Verification contract document is missing.')), false);
369
+ assert.equal(syncBack.reasons.some((reason) => reason.includes('Workflow gate blocked sync-back: missing_documents')), true);
253
370
  } finally {
254
371
  await rm(root, { recursive: true, force: true });
255
372
  }
@@ -302,7 +419,7 @@ test('sync-back apply refreshes verify contract after tasks writeback', async ()
302
419
  }
303
420
  });
304
421
 
305
- test('Phase 6.5 requires approval before sync-back apply on the wrong Git branch', async () => {
422
+ test('Phase 8.12 requires approval for sync-back on the wrong Git branch and allows explicit approved run', async () => {
306
423
  const root = await mkdtemp(path.join(tmpdir(), 'sdd-phase65-wrong-branch-'));
307
424
  try {
308
425
  await initProject(root);
@@ -315,15 +432,19 @@ test('Phase 6.5 requires approval before sync-back apply on the wrong Git branch
315
432
  await markTestRunReadyForSyncBack(root, state.runId, 'T1');
316
433
 
317
434
  const syncBack = await inspectSyncBack(root, { branch: 'feature', taskId: 'T1' });
435
+ const explicitSyncBack = await inspectSyncBack(root, { runId: state.runId, branch: 'feature', taskId: 'T1' });
318
436
 
319
437
  assert.equal(syncBack.status, 'ready');
320
438
  assert.equal(syncBack.applyPolicy.requiresApproval, true);
321
439
  assert.equal(syncBack.applyPolicy.reasons.some((reason) => reason.includes('Current Git branch is other')), true);
440
+ assert.equal(explicitSyncBack.status, 'ready');
441
+ assert.equal(explicitSyncBack.applyPolicy.requiresApproval, true);
442
+ assert.equal(explicitSyncBack.applyPolicy.reasons.some((reason) => reason.includes('Current Git branch is other')), true);
322
443
  await assert.rejects(
323
444
  () => applySyncBack(root, { branch: 'feature', taskId: 'T1' }),
324
- /--approved/
445
+ /Current Git branch is other/
325
446
  );
326
- const applied = await applySyncBack(root, { branch: 'feature', taskId: 'T1', approved: true });
447
+ const applied = await applySyncBack(root, { runId: state.runId, branch: 'feature', taskId: 'T1', approved: true });
327
448
  assert.equal(applied.applied, true);
328
449
  } finally {
329
450
  await rm(root, { recursive: true, force: true });
@@ -340,7 +461,9 @@ test('Phase 6.5 reports active affected file conflicts', async () => {
340
461
  await markTestRunReadyForSyncBack(root, runA.runId, 'T1');
341
462
  const runB = await createRun(root, { runId: 'run-b' });
342
463
  await bindTestRunState(root, runB.runId, 'feature', 'T2');
343
- await markTestRunReadyForSyncBack(root, runB.runId, 'T2');
464
+ const runC = await createRun(root, { runId: 'run-c' });
465
+ await bindTestRunState(root, runC.runId, 'feature', 'T2');
466
+ await markTestRunReadyForSyncBack(root, runC.runId, 'T2');
344
467
 
345
468
  const syncBack = await inspectSyncBack(root, { runId: runA.runId, branch: 'feature', taskId: 'T1' });
346
469
  const status = await getProjectStatus(root, { branch: 'feature' });
@@ -435,7 +558,7 @@ test('sync-back blocks downstream apply until dependencies are completed', async
435
558
  const syncBack = await inspectSyncBack(root, { runId: state.runId, branch: 'feature', taskId: 'DEP2' });
436
559
 
437
560
  assert.equal(syncBack.status, 'blocked');
438
- assert.equal(syncBack.reasons.some((reason) => reason.includes('DEP2 depends on DEP1, but DEP1 status is pending')), true);
561
+ assert.equal(syncBack.reasons.some((reason) => reason.includes('DEP2 depends on DEP1, but DEP1 has not passed required verification')), true);
439
562
  await assert.rejects(
440
563
  () => applySyncBack(root, { runId: state.runId, branch: 'feature', taskId: 'DEP2', approved: true }),
441
564
  /DEP2 depends on DEP1/
@@ -17,6 +17,26 @@ export function phase63ProjectRuntimeConfig(): string {
17
17
  source_ref: docs/external/frontend-agent-manifest.yml
18
18
  reuse_decision: adapt_via_host_adapter
19
19
  quarantine_required: true
20
+ quarantine_status: quarantined
21
+ permission_model:
22
+ - project-scoped read/search only before quarantine pass
23
+ - no direct prompt import
24
+ provenance_requirements:
25
+ - project manifest path
26
+ - source attribution
27
+ - quarantine scan result
28
+ host_compatibility:
29
+ - claude-code:future_adapter
30
+ - host-neutral:future_adapter
31
+ allowed_evidence_types:
32
+ - candidate_evidence
33
+ - external_reference
34
+ forbidden_authority:
35
+ - lifecycle gate authority
36
+ - stage completion decision
37
+ - sync-back apply decision
38
+ - ship readiness pass
39
+ - permission escalation
20
40
  allowed_use: declarative taxonomy and capability mapping only
21
41
  attribution: project frontend manifest
22
42
  rationale: project-provided agent metadata for validated contracts only
@@ -94,6 +114,7 @@ export function phase63InvalidProjectRuntimeConfig(): string {
94
114
  source_ref: docs/external/unsafe-agent-pack.yml
95
115
  reuse_decision: reuse_direct
96
116
  quarantine_required: true
117
+ quarantine_status: not_required
97
118
  allowed_use: direct execution and prompt import
98
119
  attribution: ""
99
120
  rationale: lifecycle authority request
@@ -19,8 +19,13 @@ export async function bindTestRunState(root: string, runId: string, branch: stri
19
19
  specHash: model.documents.specHash ?? null,
20
20
  planHash: model.documents.planHash ?? null,
21
21
  tasksHash: model.documents.tasksHash ?? null,
22
+ specContractHash: model.documents.specContractHash ?? null,
23
+ planContractHash: model.documents.planContractHash ?? null,
24
+ tasksContractHash: model.documents.tasksContractHash ?? null,
22
25
  planBasedOnSpecHash: model.documents.planBasedOnSpecHash ?? null,
23
- tasksBasedOnPlanHash: model.documents.tasksBasedOnPlanHash ?? null
26
+ tasksBasedOnPlanHash: model.documents.tasksBasedOnPlanHash ?? null,
27
+ planBasedOnSpecContractHash: model.documents.planBasedOnSpecContractHash ?? null,
28
+ tasksBasedOnPlanContractHash: model.documents.tasksBasedOnPlanContractHash ?? null
24
29
  }
25
30
  });
26
31
  }
@@ -34,7 +39,16 @@ export async function markTestRunReadyForSyncBack(root: string, runId: string, t
34
39
  status: 'completed',
35
40
  tasks: {
36
41
  ...state.tasks,
37
- [taskId]: { status: 'verified', gaps: [], artifacts: ['artifacts/sync-back-proposal.md'] }
42
+ [taskId]: {
43
+ status: 'implemented_verified',
44
+ implementationStatus: 'implemented',
45
+ verificationStatus: 'pass',
46
+ validationBatch: null,
47
+ validationTiming: 'task_end',
48
+ requiresVerifyBeforeNext: true,
49
+ gaps: [],
50
+ artifacts: ['artifacts/sync-back-proposal.md']
51
+ }
38
52
  },
39
53
  validation: {
40
54
  status: 'pass',
@@ -255,7 +255,7 @@ test('runGoalVerify maps validation evidence to acceptance and writes sync-back
255
255
  assert.equal(inspection.taskRunEvidence.invocationLedger.some((entry) => entry.kind === 'artifact_hash' && entry.ref === 'artifacts/sync-back-proposal.md'), true);
256
256
  assert.equal(status.latestRun?.runId, state.runId);
257
257
  assert.equal(status.tasks.pending, 1);
258
- assert.equal(status.recommendedNextCommand, 'sdd sync-back inspect --branch feature --task T1');
258
+ assert.equal(status.recommendedNextCommand, 'sdd ship --branch feature --dry-run');
259
259
  assert.equal(syncBack.status, 'ready');
260
260
  assert.equal(syncBack.markdownStatus, 'pending');
261
261
  assert.match(syncBack.proposal ?? '', /status: verified/);