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
@@ -1,12 +1,15 @@
1
+ import type { AgentCapabilityCatalog, AgentCapabilityCatalogEntry, AgentCapabilityDomain, AgentCapabilityMaterialPack, AgentCapabilityStage } from '../registries/agent-capability-catalog.js';
1
2
  import { TOOL_PERMISSION_SPEC_VERSION } from '../contracts.js';
2
3
  import type { LifecycleAutonomyCeiling } from '../lifecycle/decision-gate.js';
3
4
  import type { SddTask, SddTaskGap } from '../sdd-docs/task-parser.js';
4
5
  import type {
6
+ AgentCapabilityRouteDecision,
5
7
  AgentProfileId,
6
8
  AgentRouterCategory,
7
9
  AgentRouterRejectedProfile,
8
10
  AgentRuntimeAdapterMapping,
9
11
  AgentRuntimeRoutingRule,
12
+ CapabilitySourceCatalogEntry,
10
13
  ModelPolicyContract,
11
14
  RuntimeRegistryEntrySource,
12
15
  ToolPermissionSpec
@@ -79,6 +82,56 @@ export function selectRequiredSkillCapabilities(task: SddTask, profile: AgentPro
79
82
  return [...capabilities];
80
83
  }
81
84
 
85
+ export function buildAgentCapabilityRouteDecision(task: SddTask | null, category: AgentRouterCategory, autonomyCeiling: LifecycleAutonomyCeiling, registry: AgentSkillRuntimeRegistry, catalog: AgentCapabilityCatalog): AgentCapabilityRouteDecision {
86
+ if (!task) {
87
+ return {
88
+ authority: 'advisory_only',
89
+ selectedDomains: [],
90
+ selectedPacks: [],
91
+ rejectedExternalSources: rejectedCapabilitySources(registry.capabilitySources),
92
+ consideredExternalSources: consideredCapabilitySources(registry.capabilitySources),
93
+ evidenceRequirements: ['task metadata must exist before capability routing can select evidence requirements'],
94
+ permissionCeiling: autonomyCeiling
95
+ };
96
+ }
97
+ const stage = routeCapabilityStage(task, category);
98
+ const text = taskSignalText(task);
99
+ const selectedCapabilities = catalog.capabilities.filter((capability) => capability.domainGroup === 'professional' && capabilityStageFits(capability, stage, task, text) && capabilityMatchesTask(capability, task, text));
100
+ const effectiveCapabilities = selectedCapabilities.length > 0 ? selectedCapabilities : fallbackCapabilitiesForTask(catalog.capabilities, task, stage);
101
+ const packById = new Map(catalog.materialPacks.map((pack) => [pack.id, pack]));
102
+ const selectedPackIds = new Set<string>();
103
+ for (const capability of effectiveCapabilities) {
104
+ for (const packId of capability.routing.materialPackIds) {
105
+ const pack = packById.get(packId);
106
+ if (pack && pack.loadPolicy !== 'never_inline' && packFitsRoute(pack, stage, text)) {
107
+ selectedPackIds.add(packId);
108
+ }
109
+ }
110
+ }
111
+ return {
112
+ authority: 'advisory_only',
113
+ selectedDomains: effectiveCapabilities.map((capability) => ({
114
+ domain: capability.domain,
115
+ capabilityId: capability.id,
116
+ authority: capability.authority,
117
+ reason: capabilityReason(capability, task)
118
+ })),
119
+ selectedPacks: [...selectedPackIds].map((packId) => packById.get(packId)).filter((pack): pack is AgentCapabilityMaterialPack => Boolean(pack)).map((pack) => ({
120
+ id: pack.id,
121
+ domains: [...pack.domains],
122
+ loadPolicy: pack.loadPolicy,
123
+ contextBudget: pack.contextBudget,
124
+ sourceKind: pack.sourceKind,
125
+ expectedOutputs: [...pack.expectedOutputs],
126
+ reason: packReason(pack, stage)
127
+ })),
128
+ rejectedExternalSources: rejectedCapabilitySources(registry.capabilitySources),
129
+ consideredExternalSources: consideredCapabilitySources(registry.capabilitySources),
130
+ evidenceRequirements: evidenceRequirementsForCapabilities(effectiveCapabilities),
131
+ permissionCeiling: autonomyCeiling
132
+ };
133
+ }
134
+
82
135
  export function routeRegistrySources(registry: AgentSkillRuntimeRegistry, profile: AgentProfileId | null, capabilityIds: string[]): RuntimeRegistryEntrySource[] {
83
136
  const selected: RuntimeRegistryEntrySource[] = [];
84
137
  const seen = new Set<string>();
@@ -144,3 +197,161 @@ export function buildRejectedProfiles(allowedProfiles: AgentProfileId[], blocked
144
197
  .filter((profile) => !allowed.has(profile.id))
145
198
  .map((profile) => ({ profile: profile.id, reason: blockedReason ?? 'Profile is outside task metadata allowed_agents/agent_fit, routing rules, or router risk category.' }));
146
199
  }
200
+
201
+ function routeCapabilityStage(task: SddTask, category: AgentRouterCategory): AgentCapabilityStage {
202
+ if (category === 'planning') {
203
+ return 'plan';
204
+ }
205
+ if (category === 'validation' || task.status === 'completed') {
206
+ return 'test';
207
+ }
208
+ return 'do';
209
+ }
210
+
211
+ function taskSignalText(task: SddTask): string {
212
+ return [
213
+ task.id,
214
+ task.title ?? '',
215
+ task.boundary ?? '',
216
+ task.implementationNotes ?? '',
217
+ ...task.risk,
218
+ ...task.affectedFiles,
219
+ ...task.validation,
220
+ ...task.acceptance,
221
+ ...task.allowedAgents,
222
+ ...task.agentFit
223
+ ].join('\n').toLowerCase();
224
+ }
225
+
226
+ function capabilityMatchesTask(capability: AgentCapabilityCatalogEntry, task: SddTask, text: string): boolean {
227
+ return capability.routing.riskTags.some((tag) => text.includes(tag.toLowerCase())) || capability.routing.projectStackTags.some((tag) => projectStackMatches(tag, task, text)) || capability.routing.materialPackIds.some((packId) => text.includes(packId.replace(/^baseline-/, '').replace(/-/g, ' '))) || domainFileSignal(capability.domain, task.affectedFiles);
228
+ }
229
+
230
+ function fallbackCapabilitiesForTask(capabilities: AgentCapabilityCatalogEntry[], task: SddTask, stage: AgentCapabilityStage): AgentCapabilityCatalogEntry[] {
231
+ const codeFile = task.affectedFiles.some((file) => /\.(ts|js|java|go|py|rs|cs|php|rb)$/i.test(file));
232
+ const fallbackDomain: AgentCapabilityDomain = codeFile ? 'backend-engineering' : 'solution-design';
233
+ const fallback = capabilities.find((capability) => capability.domain === fallbackDomain && capabilityStageFits(capability, stage, task, taskSignalText(task)));
234
+ return fallback ? [fallback] : [];
235
+ }
236
+
237
+ function packFitsRoute(pack: AgentCapabilityMaterialPack, stage: AgentCapabilityStage, text: string): boolean {
238
+ const keywordTriggered = pack.triggerKeywords.some((keyword) => text.includes(keyword.toLowerCase()));
239
+ if (pack.sourceKind === 'sdd_native_baseline') {
240
+ return pack.triggerStages.includes(stage) || keywordTriggered;
241
+ }
242
+ return pack.triggerStages.includes(stage) && keywordTriggered;
243
+ }
244
+
245
+ function domainFileSignal(domain: AgentCapabilityDomain, affectedFiles: string[]): boolean {
246
+ const files = affectedFiles.map((file) => file.toLowerCase());
247
+ if (domain === 'frontend-engineering') {
248
+ return files.some((file) => /\.(tsx|jsx|vue|svelte|css|scss|less)$/.test(file) || file.includes('/components/') || file.includes('/pages/'));
249
+ }
250
+ if (domain === 'db-data-engineering') {
251
+ return files.some((file) => /\.(sql|prisma)$/.test(file) || file.includes('migration') || file.includes('schema') || file.includes('database'));
252
+ }
253
+ if (domain === 'backend-engineering') {
254
+ return files.some((file) => /\.(ts|js|java|go|py|rs|cs|php|rb)$/.test(file)) && !domainFileSignal('frontend-engineering', affectedFiles);
255
+ }
256
+ return false;
257
+ }
258
+
259
+ function capabilityStageFits(capability: AgentCapabilityCatalogEntry, stage: AgentCapabilityStage, task: SddTask, text: string): boolean {
260
+ if (capability.stages.includes(stage)) {
261
+ return true;
262
+ }
263
+ if (capability.domain === 'testing-quality-engineering' && stage === 'do') {
264
+ return testingQualityTaskSignal(task);
265
+ }
266
+ return capability.domain === 'release-engineering' && /release|ship|deploy|rollback|ci|发布/.test(text);
267
+ }
268
+
269
+ function testingQualityTaskSignal(task: SddTask): boolean {
270
+ const taskText = [task.id, task.title ?? '', task.boundary ?? '', task.implementationNotes ?? '', ...task.risk, ...task.affectedFiles, ...task.acceptance].join('\n').toLowerCase();
271
+ return /quality|coverage|acceptance|验证|测试/.test(taskText) || task.affectedFiles.some((file) => /\.(test|spec)\.[tj]sx?$/i.test(file));
272
+ }
273
+
274
+ function capabilityReason(capability: AgentCapabilityCatalogEntry, task: SddTask): string {
275
+ const fileSignal = domainFileSignal(capability.domain, task.affectedFiles) ? 'affected file evidence' : 'task risk, validation, or text evidence';
276
+ return `${capability.domain} selected from ${fileSignal}; authority remains ${capability.authority}.`;
277
+ }
278
+
279
+ function packReason(pack: AgentCapabilityMaterialPack, stage: AgentCapabilityStage): string {
280
+ return `${pack.id} is route_when_triggered for ${stage} and stays ${pack.contextBudget} context.`;
281
+ }
282
+
283
+ function evidenceRequirementsForCapabilities(capabilities: AgentCapabilityCatalogEntry[]): string[] {
284
+ const requirements = new Set<string>();
285
+ for (const capability of capabilities) {
286
+ for (const output of capability.outputs) {
287
+ requirements.add(`${capability.domain}: ${output}`);
288
+ }
289
+ }
290
+ return [...requirements];
291
+ }
292
+
293
+ function consideredCapabilitySources(sources: CapabilitySourceCatalogEntry[]): AgentCapabilityRouteDecision['consideredExternalSources'] {
294
+ return sources
295
+ .filter((source) => source.kind !== 'native_host')
296
+ .map((source) => ({
297
+ sourceId: source.id,
298
+ kind: source.kind,
299
+ quarantineStatus: source.quarantineStatus,
300
+ reuseDecision: source.reuseDecision,
301
+ allowedEvidenceTypes: [...source.allowedEvidenceTypes],
302
+ consideredUse: source.allowedUse,
303
+ reason: rejectedSourceReason(source)
304
+ }));
305
+ }
306
+
307
+
308
+ function rejectedCapabilitySources(sources: CapabilitySourceCatalogEntry[]): AgentCapabilityRouteDecision['rejectedExternalSources'] {
309
+ return sources
310
+ .filter((source) => source.kind !== 'native_host' && (source.quarantineRequired || source.reuseDecision !== 'reuse_direct' || source.kind === 'future_adapter'))
311
+ .map((source) => ({
312
+ sourceId: source.id,
313
+ quarantineStatus: source.quarantineStatus,
314
+ reuseDecision: source.reuseDecision,
315
+ allowedEvidenceTypes: [...source.allowedEvidenceTypes],
316
+ reason: rejectedSourceReason(source)
317
+ }));
318
+ }
319
+
320
+ function projectStackMatches(tag: string, task: SddTask, text: string): boolean {
321
+ if (tag === 'generic') {
322
+ return false;
323
+ }
324
+ if (text.includes(tag.toLowerCase())) {
325
+ return true;
326
+ }
327
+ const files = task.affectedFiles.map((file) => file.toLowerCase());
328
+ if (tag === 'typescript') {
329
+ return files.some((file) => /\.(ts|tsx)$/.test(file));
330
+ }
331
+ if (tag === 'javascript') {
332
+ return files.some((file) => /\.(js|jsx)$/.test(file));
333
+ }
334
+ if (tag === 'java') {
335
+ return files.some((file) => file.endsWith('.java'));
336
+ }
337
+ if (tag === 'sql') {
338
+ return files.some((file) => /\.(sql|prisma)$/.test(file));
339
+ }
340
+ return files.some((file) => file.includes(tag.toLowerCase()));
341
+ }
342
+
343
+ function rejectedSourceReason(source: CapabilitySourceCatalogEntry): string {
344
+ if (source.quarantineStatus === 'denied') {
345
+ return 'Source is denied or unsupported and cannot participate in routing.';
346
+ }
347
+ if (source.kind === 'future_adapter') {
348
+ return 'Future adapter is recorded as metadata only until host behavior is validated.';
349
+ }
350
+ if (source.quarantineStatus === 'quarantined' || source.quarantineStatus === 'required') {
351
+ return 'Source requires quarantine/provenance review and is not invoked by capability routing.';
352
+ }
353
+ if (source.reuseDecision === 'avoid') {
354
+ return 'Reuse policy avoids this source.';
355
+ }
356
+ return 'External source is considered but not loaded during progressive disclosure.';
357
+ }
@@ -14,6 +14,9 @@ import {
14
14
  validTaskMarkdown,
15
15
  writeBranchDocs
16
16
  } from '../test-support/fixtures.js';
17
+ import { writeVerifyContract } from '../verification/verify-contract.js';
18
+ import { createRun, readRunState, writeRunState } from '../run-state/run-state.js';
19
+ import { bindTestRunState } from '../test-support/run-state.js';
17
20
  import {
18
21
  inspectAgentSkillTeamRuntime,
19
22
  inspectCapabilitySource,
@@ -38,12 +41,18 @@ test('Phase 6 agent skill team runtime exposes reusable contracts and router dec
38
41
  const sourceCatalog = await listCapabilitySources(root);
39
42
  const agencySource = await inspectCapabilitySource(root, 'agency_agents_material');
40
43
  const agencyImport = await inspectExternalAgentPackImport(root, 'agency_agents_material');
44
+ const codexSource = await inspectCapabilitySource(root, 'codex_host_future');
45
+ const codexImport = await inspectExternalAgentPackImport(root, 'codex_host_future');
46
+ const figmaSource = await inspectCapabilitySource(root, 'figma_design_future');
41
47
  const teamDefault = await inspectTeamModePolicy(root);
42
48
  const teamEnabled = await inspectTeamModePolicy(root, { taskId: 'ONBOARDING-1', branch: 'master', enabled: true });
43
49
  const route = await routeSddTask(root, { taskId: 'ONBOARDING-1', branch: 'master', teamModeEnabled: true });
44
50
 
45
51
  assert.equal(runtime.version, 'phase-6.0-agent-skill-team-runtime-v1');
46
52
  assert.equal(runtime.teamMode.decision, 'disabled');
53
+ assert.equal(runtime.hostAdapter.workflowProjectionPolicy.includes('host-neutral canonical CLI commands'), true);
54
+ assert.deepEqual(runtime.hostAdapter.workflowProjections.map((projection) => `${projection.host}:${projection.support}`), ['claude_code:active', 'codex:future', 'opencode:active']);
55
+ assert.equal(runtime.hostAdapter.workflowProjections.find((projection) => projection.host === 'codex')?.unsupportedReason?.includes('not marked active'), true);
47
56
  assert.equal(runtime.profiles.some((profile) => profile.id === 'orchestrator'), true);
48
57
  assert.equal(runtime.profiles.some((profile) => profile.id === 'security'), true);
49
58
  assert.equal(runtime.skillCapabilities.some((capability) => capability.id === 'claude.subagent.researcher'), true);
@@ -52,8 +61,19 @@ test('Phase 6 agent skill team runtime exposes reusable contracts and router dec
52
61
  assert.ok(hashlineCapability);
53
62
  assert.equal(hashlineCapability.reuseDecision, 'reuse_direct');
54
63
  assert.equal(sourceCatalog.sources.some((source) => source.id === 'ohmy_team_mode'), true);
64
+ assert.ok(codexSource);
65
+ assert.equal(codexSource.quarantineStatus, 'denied');
66
+ assert.equal(codexSource.hostCompatibility.includes('codex:unsupported'), true);
67
+ assert.equal(codexImport.status, 'denied');
68
+ assert.equal(codexImport.allowedProfiles.length, 0);
69
+ assert.ok(figmaSource);
70
+ assert.equal(figmaSource.allowedEvidenceTypes.includes('design_context'), true);
71
+ assert.equal(figmaSource.reuseDecision, 'adapt_via_host_adapter');
55
72
  assert.ok(agencySource);
56
73
  assert.equal(agencySource.quarantineRequired, true);
74
+ assert.equal(agencySource.quarantineStatus, 'quarantined');
75
+ assert.equal(agencySource.permissionModel.length > 0, true);
76
+ assert.equal(agencySource.provenanceRequirements.length > 0, true);
57
77
  assert.equal(agencyImport.status, 'quarantined');
58
78
  assert.equal(agencyImport.checks.some((check) => check.check === 'dangerous_command_scan'), true);
59
79
  assert.equal(teamDefault.decision, 'disabled');
@@ -80,6 +100,7 @@ test('Phase 6 adaptive team-mode routes choose cost-bounded agent teams automati
80
100
  try {
81
101
  await initProject(root);
82
102
  await writeBranchDocs(root, 'master', `# Tasks\n\n${adaptiveTeamTaskMarkdown('LOW', { allowedAgents: ['implementer'], affectedFiles: ['docs/low.md'] })}\n${adaptiveTeamTaskMarkdown('REVIEW', { allowedAgents: ['reviewer'], requiredArtifacts: ['artifacts/review-REVIEW.md'], affectedFiles: ['docs/review.md'] })}\n${adaptiveTeamTaskMarkdown('SOURCE', { allowedAgents: ['implementer'] })}\n${adaptiveTeamTaskMarkdown('HIGH', { allowedAgents: ['implementer'], risk: ['database'] })}\n${adaptiveTeamTaskMarkdown('SECURITY', { allowedAgents: ['security'], risk: ['security'] })}`);
103
+ await writeVerifyContract(root, { branch: 'master', branchSource: 'cli_option', force: true });
83
104
 
84
105
  const low = await routeSddTask(root, { taskId: 'LOW', branch: 'master' });
85
106
  const review = await routeSddTask(root, { taskId: 'REVIEW', branch: 'master' });
@@ -156,6 +177,7 @@ test('routeSddTask uses derived route cache and opt-in profiling only', async ()
156
177
  try {
157
178
  await initProject(root);
158
179
  await writeBranchDocs(root, 'master', `# Tasks\n\n${adaptiveTeamTaskMarkdown('CACHE', { allowedAgents: ['reviewer'], requiredArtifacts: ['artifacts/review-CACHE.md'], affectedFiles: ['docs/cache.md'] })}`);
180
+ await writeVerifyContract(root, { branch: 'master', branchSource: 'cli_option', force: true });
159
181
 
160
182
  const uncached = await routeSddTask(root, { taskId: 'CACHE', branch: 'master' });
161
183
  const first = await routeSddTask(root, { taskId: 'CACHE', branch: 'master', cache: true, profile: true });
@@ -181,6 +203,7 @@ test('routeSddTask uses derived route cache and opt-in profiling only', async ()
181
203
  assert.equal(third.profile.some((span) => span.name === 'route_compute'), false);
182
204
 
183
205
  await writeBranchDocs(root, 'master', `# Tasks\n\n${adaptiveTeamTaskMarkdown('CACHE', { allowedAgents: ['reviewer'], requiredArtifacts: ['artifacts/review-CACHE.md'], affectedFiles: ['docs/cache.md'] })}\n\nCache key invalidation fixture.`);
206
+ await writeVerifyContract(root, { branch: 'master', branchSource: 'cli_option', force: true });
184
207
  const invalidated = await routeSddTask(root, { taskId: 'CACHE', branch: 'master', cache: true });
185
208
 
186
209
  assert.equal(invalidated.cache?.status, 'stored');
@@ -197,6 +220,7 @@ test('Phase 6.3 project agent runtime merges project config and routes by alias
197
220
  await initProject(root);
198
221
  await appendProjectRuntimeConfig(root, phase63ProjectRuntimeConfig());
199
222
  await writeBranchDocs(root, 'master', phase63FrontendTaskMarkdown('FRONTEND-1'));
223
+ await writeVerifyContract(root, { branch: 'master', branchSource: 'cli_option', force: true });
200
224
 
201
225
  const runtime = await inspectAgentSkillTeamRuntime(root);
202
226
  const validation = await validateAgentSkillTeamRuntime(root);
@@ -249,6 +273,12 @@ test('Phase 6.3 invalid agent runtime declarations fail closed', async () => {
249
273
  assert.match(issueText, /project\.skill\.bad\.evidenceType/);
250
274
  assert.match(issueText, /unknown source missing_source/);
251
275
  assert.match(issueText, /unsafe_source\.attribution/);
276
+ assert.match(issueText, /unsafe_source\.permissionModel/);
277
+ assert.match(issueText, /unsafe_source\.provenanceRequirements/);
278
+ assert.match(issueText, /unsafe_source\.hostCompatibility/);
279
+ assert.match(issueText, /unsafe_source\.allowedEvidenceTypes/);
280
+ assert.match(issueText, /unsafe_source\.forbiddenAuthority/);
281
+ assert.match(issueText, /Quarantined source is missing active quarantine status/);
252
282
  assert.match(issueText, /Quarantined source cannot be reused directly/);
253
283
  assert.match(issueText, /Quarantined source requests prompt import, direct execution, or lifecycle authority/);
254
284
  } finally {
@@ -256,6 +286,57 @@ test('Phase 6.3 invalid agent runtime declarations fail closed', async () => {
256
286
  }
257
287
  });
258
288
 
289
+ test('Phase 8.6 capability routing selects narrow domains, packs, and rejected external sources', async () => {
290
+ const root = await mkdtemp(path.join(tmpdir(), 'sdd-phase86-capability-routing-'));
291
+ try {
292
+ await initProject(root);
293
+ await writeBranchDocs(root, 'master', `# Tasks
294
+
295
+ ${capabilityRouteTaskMarkdown('SIMPLE', 'Simple backend parser fix', ['packages/core/src/parser.ts'], [], ['npm test'])}
296
+ ${capabilityRouteTaskMarkdown('UI', 'UI UX frontend interaction update', ['src/components/Button.tsx'], ['ui-ux', 'accessibility'], ['browser Playwright validation'])}
297
+ ${capabilityRouteTaskMarkdown('SECURITY', 'Security permission boundary update', ['packages/core/src/auth.ts'], ['security'], ['npm test'])}
298
+ ${capabilityRouteTaskMarkdown('DB', 'Database migration data safety update', ['db/migrations/001.sql'], ['database', 'data-loss'], ['npm test'])}
299
+ ${capabilityRouteTaskMarkdown('RELEASE', 'Release deploy rollback readiness', ['.github/workflows/release.yml'], ['release', 'ci-build'], ['npm test'])}
300
+ ${capabilityRouteTaskMarkdown('TESTING', 'Testing quality coverage update', ['packages/core/src/parser.test.ts'], ['validation'], ['coverage acceptance test'])}`);
301
+
302
+ const simple = await routeSddTask(root, { taskId: 'SIMPLE', branch: 'master' });
303
+ const ui = await routeSddTask(root, { taskId: 'UI', branch: 'master' });
304
+ const security = await routeSddTask(root, { taskId: 'SECURITY', branch: 'master', approved: true });
305
+ const db = await routeSddTask(root, { taskId: 'DB', branch: 'master', approved: true });
306
+ const release = await routeSddTask(root, { taskId: 'RELEASE', branch: 'master', approved: true });
307
+ const testing = await routeSddTask(root, { taskId: 'TESTING', branch: 'master' });
308
+ const figmaConsidered = ui.capabilityDecision.consideredExternalSources.find((source) => source.sourceId === 'figma_design_future');
309
+ const uiUxProMaxConsidered = ui.capabilityDecision.consideredExternalSources.find((source) => source.sourceId === 'ui_ux_pro_max_external');
310
+
311
+
312
+ assert.deepEqual(simple.capabilityDecision.selectedDomains.map((item) => item.domain), ['backend-engineering']);
313
+ assert.equal(simple.capabilityDecision.selectedPacks.length <= 2, true);
314
+ assert.equal(simple.capabilityDecision.authority, 'advisory_only');
315
+ assert.equal(simple.capabilityDecision.permissionCeiling, simple.autonomyCeiling);
316
+ assert.equal(ui.capabilityDecision.selectedDomains.some((item) => item.domain === 'frontend-engineering'), true);
317
+ assert.equal(ui.capabilityDecision.selectedDomains.some((item) => item.domain === 'ui-ux-product-design'), true);
318
+ assert.equal(ui.capabilityDecision.selectedPacks.some((pack) => pack.id === 'baseline-ui-ux-product-design'), true);
319
+ assert.equal(ui.capabilityDecision.rejectedExternalSources.some((source) => source.sourceId === 'figma_design_future' && /Future adapter|quarantine/.test(source.reason)), true);
320
+ assert.equal(ui.capabilityDecision.rejectedExternalSources.some((source) => source.sourceId === 'ui_ux_pro_max_external' && /quarantine/i.test(source.reason)), true);
321
+ assert.ok(figmaConsidered);
322
+ assert.equal(figmaConsidered.kind, 'future_adapter');
323
+ assert.equal(figmaConsidered.consideredUse.length > 0, true);
324
+ assert.ok(uiUxProMaxConsidered);
325
+ assert.equal(uiUxProMaxConsidered.kind, 'open_source_material');
326
+ assert.equal(uiUxProMaxConsidered.quarantineStatus, 'quarantined');
327
+ assert.equal(security.capabilityDecision.selectedDomains.some((item) => item.domain === 'security-engineering'), true);
328
+ assert.equal(db.capabilityDecision.selectedDomains.some((item) => item.domain === 'db-data-engineering'), true);
329
+ assert.equal(release.capabilityDecision.selectedDomains.some((item) => item.domain === 'release-engineering'), true);
330
+ assert.equal(release.capabilityDecision.selectedPacks.some((pack) => pack.id === 'baseline-release-engineering'), true);
331
+ assert.equal(testing.capabilityDecision.selectedDomains.some((item) => item.domain === 'testing-quality-engineering'), true);
332
+ assert.equal(testing.capabilityDecision.evidenceRequirements.some((item) => item.includes('evidence requirement')), true);
333
+ assert.equal(ui.requiredCapabilities.includes('figma_design_future'), false);
334
+ } finally {
335
+ await rm(root, { recursive: true, force: true });
336
+ }
337
+ });
338
+
339
+
259
340
  test('routeSddTask blocks downstream tasks until dependencies are completed', async () => {
260
341
  const root = await mkdtemp(path.join(tmpdir(), 'sdd-route-dependencies-'));
261
342
  try {
@@ -266,8 +347,8 @@ test('routeSddTask blocks downstream tasks until dependencies are completed', as
266
347
 
267
348
  assert.equal(blocked.category, 'blocked');
268
349
  assert.equal(blocked.recommendedProfile, null);
269
- assert.match(blocked.blockedReason ?? '', /DEP2 depends on DEP1, but DEP1 status is pending/);
270
- assert.match(blocked.nextAction, /Complete and sync-back DEP1 before routing DEP2/);
350
+ assert.match(blocked.blockedReason ?? '', /DEP2 depends on DEP1, but DEP1 has not passed required verification/);
351
+ assert.match(blocked.nextAction, /sdd test task DEP1/);
271
352
 
272
353
  await writeBranchDocs(root, 'feature', `# Tasks\n\n${validTaskMarkdown('DEP1', []).replace('status: pending', 'status: completed')}\n${validTaskMarkdown('DEP2', ['DEP1']).replace('packages/core/src/index.ts', 'docs/dep2.md')}`);
273
354
  const ready = await routeSddTask(root, { taskId: 'DEP2', branch: 'feature' });
@@ -278,4 +359,71 @@ test('routeSddTask blocks downstream tasks until dependencies are completed', as
278
359
  } finally {
279
360
  await rm(root, { recursive: true, force: true });
280
361
  }
281
- });
362
+ });
363
+
364
+ test('routeSddTask uses latest eligible runtime dependency readiness', async () => {
365
+ const root = await mkdtemp(path.join(tmpdir(), 'sdd-route-runtime-dependencies-'));
366
+ try {
367
+ await initProject(root);
368
+ await writeBranchDocs(root, 'feature', `# Tasks
369
+
370
+ ${validTaskMarkdown('DEP1', [])
371
+ .replace('packages/core/src/index.ts', 'docs/dep1.md')
372
+ .replace('validation:\n - npm test', 'validation_batch: dep-batch\nvalidation_timing: batch_end\nrequires_verify_before_next: false\nvalidation:\n - npm test')}
373
+ ${validTaskMarkdown('DEP2', ['DEP1']).replace('packages/core/src/index.ts', 'docs/dep2.md')}`);
374
+ const run = await createRun(root, { runId: 'run-dep1-implemented' });
375
+ await bindTestRunState(root, run.runId, 'feature', 'DEP1');
376
+ const bound = await readRunState(root, run.runId);
377
+ await writeRunState(root, {
378
+ ...bound,
379
+ status: 'completed',
380
+ tasks: {
381
+ ...bound.tasks,
382
+ DEP1: {
383
+ status: 'implemented_pending_validation',
384
+ implementationStatus: 'implemented',
385
+ verificationStatus: 'pending_batch',
386
+ validationBatch: 'dep-batch',
387
+ validationTiming: 'batch_end',
388
+ requiresVerifyBeforeNext: false,
389
+ gaps: [],
390
+ artifacts: []
391
+ }
392
+ }
393
+ });
394
+
395
+ const decision = await routeSddTask(root, { taskId: 'DEP2', branch: 'feature' });
396
+
397
+ assert.notEqual(decision.category, 'blocked');
398
+ assert.equal(decision.blockedReason, null);
399
+ assert.ok(decision.recommendedProfile);
400
+ } finally {
401
+ await rm(root, { recursive: true, force: true });
402
+ }
403
+ });
404
+
405
+ function capabilityRouteTaskMarkdown(taskId: string, title: string, affectedFiles: string[], risk: string[], validation: string[]): string {
406
+ const affectedFilesBlock = affectedFiles.length === 0 ? 'affected_files: []' : `affected_files:\n${affectedFiles.map((file) => ` - ${file}`).join('\n')}`;
407
+ const riskBlock = risk.length === 0 ? 'risk: []' : `risk:\n${risk.map((item) => ` - ${item}`).join('\n')}`;
408
+ const validationBlock = validation.length === 0 ? 'validation: []' : `validation:\n${validation.map((item) => ` - ${item}`).join('\n')}`;
409
+ return `### ${taskId}: ${title}
410
+
411
+ \`\`\`sdd-task
412
+ id: ${taskId}
413
+ status: pending
414
+ wave: 1
415
+ depends_on: []
416
+ acceptance_refs:
417
+ - AC-1
418
+ ${affectedFilesBlock}
419
+ ${validationBlock}
420
+ ${riskBlock}
421
+ allowed_agents:
422
+ - implementer
423
+ \`\`\`
424
+
425
+ #### Acceptance
426
+
427
+ - ${title}.
428
+ `;
429
+ }
@@ -11,11 +11,15 @@ import { buildAgentSkillRuntimeRegistry } from './runtime-registry.js';
11
11
  import { buildTeamModePolicy, resolveTeamModeActivation } from './team-mode.js';
12
12
  import { matchRoutingRules } from './routing-rules.js';
13
13
  import { chooseRecommendedProfile, deriveAllowedProfiles, toAgentProfileId } from './profile-resolution.js';
14
- import { adapterMappingForProfile, buildRejectedProfiles, buildToolPermissionSpec, modelPolicyForProfile, quarantineWarningsForSources, routeCategory, routeRegistrySources, selectRequiredSkillCapabilities } from './route-projection.js';
14
+ import { adapterMappingForProfile, buildAgentCapabilityRouteDecision, buildRejectedProfiles, buildToolPermissionSpec, modelPolicyForProfile, quarantineWarningsForSources, routeCategory, routeRegistrySources, selectRequiredSkillCapabilities } from './route-projection.js';
15
15
  import { lifecycleAutonomyCeilingFromDecision, ensureLifecycleRiskDecision } from '../orchestration/runtime.js';
16
16
  import { taskAutonomyCeiling } from './risk-policy.js';
17
17
  import { evaluateTaskWorkflowGate } from '../risk.js';
18
18
  import { nextDependencyTaskId, resolveTaskDependencyReadiness } from '../workflow-state/dependencies.js';
19
+ import { selectLatestEligibleRunsByTask, type LatestEligibleRunSelection } from '../workflow-state/latest-eligible-run.js';
20
+ import { readAllRunStates } from '../run-state/run-state.js';
21
+ import type { RunState, RunStateTaskRuntime } from '../run-state/model.js';
22
+ import { inspectAgentCapabilityCatalog } from '../registries/agent-capability-catalog.js';
19
23
  import type {
20
24
  AgentRouterDecision,
21
25
  TeamModePolicy
@@ -46,10 +50,14 @@ export async function routeSddTask(projectRoot: string, options: { taskId: strin
46
50
  const routeStart = Date.now();
47
51
  const routeStartedAt = new Date(routeStart).toISOString();
48
52
  const registry = await buildAgentSkillRuntimeRegistry(projectRoot);
53
+ const capabilityCatalog = await inspectAgentCapabilityCatalog(projectRoot);
49
54
  profileSpans.push(runtimeProfileSpan('agent_runtime_registry', routeStart));
50
55
  const branchStart = Date.now();
51
- const branch = options.branch ?? (await resolveSddContext(projectRoot)).branch;
56
+ const context = await resolveSddContext(projectRoot, { branch: options.branch, branchSource: options.branch ? 'cli_option' : undefined });
57
+ const branch = context.partition;
52
58
  const model = await parseSddBranch(projectRoot, branch);
59
+ const states = await readAllRunStates(projectRoot);
60
+ const runtimeByTask = latestRuntimeTaskStates(selectLatestEligibleRunsByTask({ states, model, partition: branch, currentGitBranch: context.currentGitBranch }), states);
53
61
  profileSpans.push(runtimeProfileSpan('document_parse', branchStart));
54
62
  const cacheKey = routeCacheKey({ taskId: options.taskId, branch, agent: options.agent ?? null, teamModeActivation: resolveTeamModeActivation(options, 'auto'), approved: options.approved, documents: model.documents });
55
63
  const cachedDecision = options.cache ? await readRouteCache<AgentRouterDecision>(projectRoot, cacheKey) : null;
@@ -73,9 +81,9 @@ export async function routeSddTask(projectRoot: string, options: { taskId: strin
73
81
  const lifecycleBlockedReason = workflowGate.blocksRoute
74
82
  ? workflowGate.primaryReason
75
83
  : null;
76
- const dependencyReadiness = task ? resolveTaskDependencyReadiness(model, options.taskId) : null;
84
+ const dependencyReadiness = task ? resolveTaskDependencyReadiness(model, options.taskId, { runtimeByTask }) : null;
77
85
  const dependencyBlockedReason = dependencyReadiness?.blockingReasons[0] ?? null;
78
- const dependencyTaskId = task ? nextDependencyTaskId(model, options.taskId) : null;
86
+ const dependencyTaskId = task ? nextDependencyTaskId(model, options.taskId, { runtimeByTask }) : null;
79
87
  const taskRecommendedProfile = task && !blockingGap && !dependencyBlockedReason && !lifecycleBlockedReason ? chooseRecommendedProfile(task, allowedProfiles, registry, matchedRules) : null;
80
88
  const recommendedProfile = dependencyBlockedReason || lifecycleBlockedReason ? null : delegatedProfile ?? taskRecommendedProfile;
81
89
  const category = task ? routeCategory(task, blockingGap, allowedProfiles, matchedRules) : 'blocked';
@@ -87,6 +95,7 @@ export async function routeSddTask(projectRoot: string, options: { taskId: strin
87
95
  const routedCategory = blockedReason ? 'blocked' : category;
88
96
  const registrySources = routeRegistrySources(registry, recommendedProfile, requiredCapabilities);
89
97
  const adapterMapping = recommendedProfile ? adapterMappingForProfile(registry, recommendedProfile) : null;
98
+ const capabilityDecision = buildAgentCapabilityRouteDecision(task ?? null, routedCategory, autonomyCeiling, registry, capabilityCatalog);
90
99
  const decision: AgentRouterDecision = {
91
100
  version: AGENT_ROUTER_CONTRACT_VERSION,
92
101
  taskId: options.taskId,
@@ -116,7 +125,8 @@ export async function routeSddTask(projectRoot: string, options: { taskId: strin
116
125
  primaryReason: workflowGate.primaryReason,
117
126
  requiredArtifacts: task?.requiredArtifacts ?? [],
118
127
  blockedReason,
119
- nextAction: routeNextAction({ taskId: options.taskId, taskExists: Boolean(task), hasBlockingGap: Boolean(blockingGap), dependencyTaskId, workflowGateNextAction: workflowGate.nextAction, recommendedProfile, requiredCapabilities }),
128
+ nextAction: routeNextAction({ taskId: options.taskId, taskExists: Boolean(task), hasBlockingGap: Boolean(blockingGap), dependencyTaskId, blockedReason, workflowGateNextAction: workflowGate.nextAction, recommendedProfile, requiredCapabilities }),
129
+ capabilityDecision,
120
130
  registrySources,
121
131
  resolvedAliases: profileSelection.resolvedAliases,
122
132
  routingRuleHits: matchedRules.map((rule) => rule.id),
@@ -135,11 +145,28 @@ export async function routeSddTask(projectRoot: string, options: { taskId: strin
135
145
  return decision;
136
146
  }
137
147
 
148
+ function latestRuntimeTaskStates(selections: LatestEligibleRunSelection[], states: RunState[]): Map<string, RunStateTaskRuntime> {
149
+ const stateByRunId = new Map(states.map((state) => [state.runId, state]));
150
+ const result = new Map<string, RunStateTaskRuntime>();
151
+ for (const selection of selections) {
152
+ const selected = selection.selected;
153
+ if (!selected) {
154
+ continue;
155
+ }
156
+ const taskState = stateByRunId.get(selected.runId)?.tasks[selected.taskId];
157
+ if (taskState) {
158
+ result.set(selected.taskId, taskState);
159
+ }
160
+ }
161
+ return result;
162
+ }
163
+
138
164
  function routeNextAction(input: {
139
165
  taskId: string;
140
166
  taskExists: boolean;
141
167
  hasBlockingGap: boolean;
142
168
  dependencyTaskId: string | null;
169
+ blockedReason: string | null;
143
170
  workflowGateNextAction: string;
144
171
  recommendedProfile: string | null;
145
172
  requiredCapabilities: string[];
@@ -151,7 +178,9 @@ function routeNextAction(input: {
151
178
  return `Fix task gaps before routing ${input.taskId}.`;
152
179
  }
153
180
  if (input.dependencyTaskId) {
154
- return `Complete and sync-back ${input.dependencyTaskId} before routing ${input.taskId}.`;
181
+ return input.blockedReason?.includes('has not passed required verification')
182
+ ? `Run sdd test task ${input.dependencyTaskId} before routing ${input.taskId}.`
183
+ : `Run sdd do task ${input.dependencyTaskId} before routing ${input.taskId}.`;
155
184
  }
156
185
  if (input.workflowGateNextAction) {
157
186
  return input.workflowGateNextAction;
@@ -80,13 +80,17 @@ export async function inspectExternalAgentPackImport(projectRoot: string, source
80
80
  reason: 'Unknown external source cannot be routed.'
81
81
  };
82
82
  }
83
- if (source.reuseDecision === 'avoid') {
83
+ if (source.reuseDecision === 'avoid' || source.quarantineStatus === 'denied') {
84
84
  return {
85
85
  version: EXTERNAL_AGENT_PACK_IMPORT_POLICY_VERSION,
86
86
  sourceId,
87
87
  status: 'denied',
88
- checks: [{ check: 'reuse_decision', status: 'fail', evidence: `${source.id} is marked avoid for Phase 6 core runtime.` }],
89
- mappingResult: 'future adapter only',
88
+ checks: [
89
+ { check: 'reuse_decision', status: source.reuseDecision === 'avoid' ? 'fail' : 'warn', evidence: `${source.id} reuse=${source.reuseDecision}.` },
90
+ { check: 'quarantine_status', status: source.quarantineStatus === 'denied' ? 'fail' : 'warn', evidence: `${source.id} quarantine_status=${source.quarantineStatus}.` },
91
+ { check: 'host_compatibility', status: source.hostCompatibility.some((item) => item.includes('unsupported')) ? 'fail' : 'warn', evidence: source.hostCompatibility.join(',') || 'not declared' }
92
+ ],
93
+ mappingResult: 'future adapter or unsupported source only',
90
94
  allowedProfiles: [],
91
95
  riskCeiling: 'research_before_implementation',
92
96
  reason: source.rationale
@@ -98,11 +102,14 @@ export async function inspectExternalAgentPackImport(projectRoot: string, source
98
102
  { check: 'hidden_unicode_scan', status: 'not_run', evidence: 'External material has not been scanned for hidden Unicode.' },
99
103
  { check: 'secret_scan', status: 'not_run', evidence: 'External material has not been scanned for secrets.' },
100
104
  { check: 'dangerous_command_scan', status: 'not_run', evidence: 'External material has not been scanned for dangerous commands.' },
105
+ { check: 'permission_model', status: source.permissionModel.length > 0 ? 'pass' : 'fail', evidence: source.permissionModel.join(',') || 'No permission model declared.' },
106
+ { check: 'provenance_requirements', status: source.provenanceRequirements.length > 0 ? 'pass' : 'fail', evidence: source.provenanceRequirements.join(',') || 'No provenance requirements declared.' },
101
107
  { check: 'sdd_frontmatter_mapping', status: 'not_run', evidence: 'External material has not been mapped to SDD capability/profile fields.' }
102
108
  ]
103
109
  : [
104
110
  { check: 'source_catalog', status: 'pass', evidence: `${source.id} is cataloged as ${source.reuseDecision}.` },
105
- { check: 'quarantine_required', status: 'pass', evidence: 'This source is a native capability or mechanism reference, not an imported prompt pack.' }
111
+ { check: 'quarantine_required', status: 'pass', evidence: 'This source is a native capability or mechanism reference, not an imported prompt pack.' },
112
+ { check: 'provenance_requirements', status: source.provenanceRequirements.length > 0 ? 'pass' : 'fail', evidence: source.provenanceRequirements.join(',') || 'No provenance requirements declared.' }
106
113
  ];
107
114
  return {
108
115
  version: EXTERNAL_AGENT_PACK_IMPORT_POLICY_VERSION,