@opengsd/gsd-pi 1.2.0-dev.e8563f58 → 1.2.0-dev.fbdca60b

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 (432) hide show
  1. package/dist/cli-model-override.d.ts +15 -0
  2. package/dist/cli-model-override.js +21 -0
  3. package/dist/cli.js +1 -18
  4. package/dist/loader.js +6 -4
  5. package/dist/register-agent-bundles.d.ts +11 -2
  6. package/dist/register-agent-bundles.js +18 -4
  7. package/dist/resource-loader.d.ts +10 -5
  8. package/dist/resource-loader.js +121 -6
  9. package/dist/resources/.managed-resources-content-hash +1 -1
  10. package/dist/resources/extensions/ask-user-questions.js +3 -2
  11. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
  12. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
  13. package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
  14. package/dist/resources/extensions/gsd/auto/dispatch-history.js +21 -6
  15. package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
  16. package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
  17. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  18. package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
  19. package/dist/resources/extensions/gsd/auto/orchestrator.js +85 -15
  20. package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
  21. package/dist/resources/extensions/gsd/auto/phases.js +17 -2329
  22. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
  23. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  24. package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
  25. package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
  26. package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
  27. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +3 -2
  28. package/dist/resources/extensions/gsd/auto-dispatch.js +11 -2
  29. package/dist/resources/extensions/gsd/auto-post-unit.js +18 -6
  30. package/dist/resources/extensions/gsd/auto-start.js +23 -3
  31. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  32. package/dist/resources/extensions/gsd/auto-verification.js +14 -2
  33. package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
  34. package/dist/resources/extensions/gsd/auto.js +45 -2
  35. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
  36. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  37. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
  38. package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
  39. package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
  40. package/dist/resources/extensions/gsd/db/engine.js +24 -6
  41. package/dist/resources/extensions/gsd/db/queries.js +30 -0
  42. package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
  43. package/dist/resources/extensions/gsd/db-transaction.js +27 -23
  44. package/dist/resources/extensions/gsd/db-writer.js +8 -17
  45. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  46. package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
  47. package/dist/resources/extensions/gsd/gsd-db.js +15 -20
  48. package/dist/resources/extensions/gsd/guided-flow.js +93 -4
  49. package/dist/resources/extensions/gsd/health-widget.js +87 -28
  50. package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
  51. package/dist/resources/extensions/gsd/memory-relations.js +1 -1
  52. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  53. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  54. package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
  55. package/dist/resources/extensions/gsd/notifications.js +12 -7
  56. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  57. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  58. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
  59. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  60. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  61. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  62. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  63. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  64. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  66. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  68. package/dist/resources/extensions/gsd/prompts/run-uat.md +3 -1
  69. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  72. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  73. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  74. package/dist/resources/extensions/gsd/skill-activation.js +3 -6
  75. package/dist/resources/extensions/gsd/state.js +6 -2
  76. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  77. package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
  78. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  79. package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
  80. package/dist/resources/extensions/gsd/tools/complete-task.js +65 -2
  81. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
  82. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  83. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  84. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  85. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
  86. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  87. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  88. package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
  89. package/dist/resources/extensions/gsd/unit-registry.js +34 -4
  90. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  91. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  92. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  93. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  94. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
  95. package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
  96. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  97. package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
  98. package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
  99. package/dist/resources/extensions/gsd/worktree.js +8 -1
  100. package/dist/resources/extensions/mcp-client/manager.js +6 -1
  101. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  102. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  103. package/dist/runtime-checks.d.ts +10 -0
  104. package/dist/runtime-checks.js +27 -0
  105. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  106. package/dist/web/standalone/.next/BUILD_ID +1 -1
  107. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  108. package/dist/web/standalone/.next/build-manifest.json +2 -2
  109. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  110. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  130. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  131. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  132. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  134. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  136. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  138. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  140. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  142. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  146. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  156. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  158. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/index.html +1 -1
  161. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  162. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  163. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  164. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  165. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  166. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  167. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  168. package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
  169. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  170. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  172. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  173. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  174. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  175. package/package.json +3 -3
  176. package/packages/cloud-mcp-gateway/package.json +2 -2
  177. package/packages/contracts/package.json +1 -1
  178. package/packages/daemon/package.json +4 -4
  179. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  180. package/packages/gsd-agent-core/dist/sdk.js +6 -4
  181. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  182. package/packages/gsd-agent-core/package.json +5 -5
  183. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  186. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  187. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  188. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +50 -6
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +2 -0
  192. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
  194. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
  196. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  197. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +17 -0
  198. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  199. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
  201. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  202. package/packages/gsd-agent-modes/package.json +7 -7
  203. package/packages/mcp-server/README.md +12 -3
  204. package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
  205. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
  206. package/packages/mcp-server/dist/cli-runner.js +137 -0
  207. package/packages/mcp-server/dist/cli-runner.js.map +1 -0
  208. package/packages/mcp-server/dist/cli.js +2 -53
  209. package/packages/mcp-server/dist/cli.js.map +1 -1
  210. package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
  211. package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
  212. package/packages/mcp-server/dist/pid-registry.js +459 -0
  213. package/packages/mcp-server/dist/pid-registry.js.map +1 -0
  214. package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
  215. package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
  216. package/packages/mcp-server/dist/probe-mode.js +10 -0
  217. package/packages/mcp-server/dist/probe-mode.js.map +1 -0
  218. package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
  219. package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
  220. package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
  221. package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
  222. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  223. package/packages/mcp-server/dist/workflow-tools.js +62 -43
  224. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  225. package/packages/mcp-server/package.json +5 -5
  226. package/packages/native/package.json +1 -1
  227. package/packages/pi-agent-core/dist/agent-loop.js +43 -2
  228. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  229. package/packages/pi-agent-core/package.json +1 -1
  230. package/packages/pi-ai/package.json +1 -1
  231. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  232. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  234. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  236. package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
  237. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  238. package/packages/pi-coding-agent/package.json +7 -7
  239. package/packages/pi-tui/README.md +15 -0
  240. package/packages/pi-tui/dist/index.d.ts +2 -2
  241. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  242. package/packages/pi-tui/dist/index.js +2 -2
  243. package/packages/pi-tui/dist/index.js.map +1 -1
  244. package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
  245. package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
  246. package/packages/pi-tui/dist/terminal-image.js +54 -2
  247. package/packages/pi-tui/dist/terminal-image.js.map +1 -1
  248. package/packages/pi-tui/dist/terminal.d.ts +12 -0
  249. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  250. package/packages/pi-tui/dist/terminal.js +70 -25
  251. package/packages/pi-tui/dist/terminal.js.map +1 -1
  252. package/packages/pi-tui/dist/tui.d.ts +15 -0
  253. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  254. package/packages/pi-tui/dist/tui.js +106 -21
  255. package/packages/pi-tui/dist/tui.js.map +1 -1
  256. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  257. package/packages/pi-tui/dist/utils.js +110 -36
  258. package/packages/pi-tui/dist/utils.js.map +1 -1
  259. package/packages/pi-tui/package.json +2 -2
  260. package/packages/rpc-client/package.json +2 -2
  261. package/pkg/dist/theme/theme.d.ts.map +1 -1
  262. package/pkg/dist/theme/theme.js +45 -17
  263. package/pkg/dist/theme/theme.js.map +1 -1
  264. package/pkg/package.json +1 -1
  265. package/src/resources/extensions/ask-user-questions.ts +7 -2
  266. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
  267. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
  268. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
  269. package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
  270. package/src/resources/extensions/gsd/auto/dispatch-history.ts +22 -6
  271. package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
  272. package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
  273. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  274. package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
  275. package/src/resources/extensions/gsd/auto/orchestrator.ts +95 -15
  276. package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
  277. package/src/resources/extensions/gsd/auto/phases.ts +58 -3022
  278. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
  279. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  280. package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
  281. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
  282. package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
  283. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +10 -16
  284. package/src/resources/extensions/gsd/auto-dispatch.ts +11 -10
  285. package/src/resources/extensions/gsd/auto-post-unit.ts +21 -6
  286. package/src/resources/extensions/gsd/auto-start.ts +24 -4
  287. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  288. package/src/resources/extensions/gsd/auto-verification.ts +18 -2
  289. package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
  290. package/src/resources/extensions/gsd/auto.ts +56 -2
  291. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
  292. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  293. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
  294. package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
  295. package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
  296. package/src/resources/extensions/gsd/db/engine.ts +26 -6
  297. package/src/resources/extensions/gsd/db/queries.ts +29 -0
  298. package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
  299. package/src/resources/extensions/gsd/db-transaction.ts +37 -20
  300. package/src/resources/extensions/gsd/db-writer.ts +11 -19
  301. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  302. package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
  303. package/src/resources/extensions/gsd/gsd-db.ts +15 -19
  304. package/src/resources/extensions/gsd/guided-flow.ts +145 -24
  305. package/src/resources/extensions/gsd/health-widget.ts +91 -27
  306. package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
  307. package/src/resources/extensions/gsd/memory-relations.ts +1 -1
  308. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  309. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  310. package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
  311. package/src/resources/extensions/gsd/notifications.ts +13 -6
  312. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  313. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  314. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
  315. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  316. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  317. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  318. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  319. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  320. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  321. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  322. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  323. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  324. package/src/resources/extensions/gsd/prompts/run-uat.md +3 -1
  325. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  326. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  327. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  328. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  329. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  330. package/src/resources/extensions/gsd/skill-activation.ts +3 -6
  331. package/src/resources/extensions/gsd/state.ts +7 -1
  332. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
  333. package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
  334. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
  335. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +6 -1
  336. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +76 -12
  337. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
  338. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
  339. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
  340. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  341. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
  342. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
  343. package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
  344. package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
  345. package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
  346. package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
  347. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +2 -1
  348. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +62 -0
  349. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  350. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +55 -0
  351. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
  352. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
  353. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
  354. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +19 -0
  355. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
  356. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
  357. package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
  358. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +18 -0
  359. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
  360. package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
  361. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
  362. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
  363. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
  364. package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
  365. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
  366. package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
  367. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
  368. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +5 -0
  369. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
  370. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  371. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
  372. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  373. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
  374. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
  375. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
  376. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  377. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +26 -2
  378. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
  379. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
  380. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
  381. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
  382. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  383. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
  384. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
  385. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  386. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  387. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  388. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  389. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  390. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  391. package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
  392. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
  393. package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
  394. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  395. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
  396. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
  397. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
  398. package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
  399. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
  400. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  401. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  402. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  403. package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
  404. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  405. package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
  406. package/src/resources/extensions/gsd/tools/complete-task.ts +90 -2
  407. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
  408. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  409. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  410. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  411. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
  412. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  413. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  414. package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
  415. package/src/resources/extensions/gsd/unit-registry.ts +34 -4
  416. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  417. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  418. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  419. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  420. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
  421. package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
  422. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  423. package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
  424. package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
  425. package/src/resources/extensions/gsd/worktree.ts +7 -1
  426. package/src/resources/extensions/mcp-client/manager.ts +7 -1
  427. package/src/resources/skills/create-skill/SKILL.md +3 -0
  428. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  429. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  430. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  431. /package/dist/web/standalone/.next/static/{LDHRKiRBIVZmiuMjrL1Vy → 2T9IOdiiM3o3gZ4UbPi8E}/_buildManifest.js +0 -0
  432. /package/dist/web/standalone/.next/static/{LDHRKiRBIVZmiuMjrL1Vy → 2T9IOdiiM3o3gZ4UbPi8E}/_ssgManifest.js +0 -0
@@ -0,0 +1,119 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Tests for shared workflow MCP probe cache.
3
+
4
+ import { describe, test } from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
7
+ import { createRequire } from "node:module";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { pathToFileURL } from "node:url";
11
+
12
+ import {
13
+ cachedWorkflowMcpCoversRequired,
14
+ clearWorkflowMcpProbeCache,
15
+ getCachedWorkflowMcpProbe,
16
+ probeAndCacheWorkflowMcp,
17
+ recordWorkflowMcpProbe,
18
+ beginWorkflowMcpSdkSession,
19
+ endWorkflowMcpSdkSession,
20
+ warmWorkflowMcpProbeInBackground,
21
+ } from "../workflow-mcp-readiness-cache.ts";
22
+
23
+ describe("workflow-mcp-readiness-cache", () => {
24
+ test("returns cached probe without reconnecting", async () => {
25
+ clearWorkflowMcpProbeCache();
26
+ const projectRoot = "/tmp/gsd-cache-project";
27
+ recordWorkflowMcpProbe(projectRoot, "gsd-workflow", ["gsd_status", "gsd_plan_slice"]);
28
+
29
+ const result = await probeAndCacheWorkflowMcp(projectRoot, { timeoutMs: 1000 });
30
+ assert.equal(result.ok, true);
31
+ assert.deepEqual(result.tools, ["gsd_status", "gsd_plan_slice"]);
32
+ assert.equal(result.serverName, "gsd-workflow");
33
+ });
34
+
35
+ test("cachedWorkflowMcpCoversRequired matches required workflow tools", () => {
36
+ clearWorkflowMcpProbeCache();
37
+ const projectRoot = "/tmp/gsd-cache-required";
38
+ recordWorkflowMcpProbe(projectRoot, "gsd-workflow", ["gsd_plan_slice", "gsd_milestone_status"]);
39
+
40
+ assert.equal(
41
+ cachedWorkflowMcpCoversRequired(projectRoot, "gsd-workflow", ["gsd_plan_slice"]),
42
+ true,
43
+ );
44
+ assert.equal(
45
+ cachedWorkflowMcpCoversRequired(projectRoot, "gsd-workflow", ["gsd_uat_exec"]),
46
+ false,
47
+ );
48
+ assert.equal(getCachedWorkflowMcpProbe(projectRoot)?.serverName, "gsd-workflow");
49
+ });
50
+
51
+ test("warmWorkflowMcpProbeInBackground is suppressed during active SDK sessions", async () => {
52
+ clearWorkflowMcpProbeCache();
53
+ beginWorkflowMcpSdkSession();
54
+ try {
55
+ const projectRoot = "/tmp/gsd-sdk-session-guard";
56
+ warmWorkflowMcpProbeInBackground(projectRoot);
57
+ await new Promise((resolve) => setTimeout(resolve, 10));
58
+ assert.equal(getCachedWorkflowMcpProbe(projectRoot), null);
59
+ } finally {
60
+ endWorkflowMcpSdkSession();
61
+ }
62
+ });
63
+
64
+ test("warmWorkflowMcpProbeInBackground uses project root without double cache-keying", async () => {
65
+ clearWorkflowMcpProbeCache();
66
+ const projectRoot = "/tmp/gsd-warm-cache-key";
67
+ recordWorkflowMcpProbe(projectRoot, "gsd-workflow", ["gsd_status", "gsd_plan_slice"]);
68
+ warmWorkflowMcpProbeInBackground(projectRoot);
69
+ await new Promise((resolve) => setTimeout(resolve, 10));
70
+ assert.equal(getCachedWorkflowMcpProbe(projectRoot)?.serverName, "gsd-workflow");
71
+ });
72
+
73
+ test("probeAndCacheWorkflowMcp reads project .mcp.json when no env launch config exists", async () => {
74
+ clearWorkflowMcpProbeCache();
75
+ const previousGsdHome = process.env.GSD_HOME;
76
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-cache-project-"));
77
+ const gsdHomeDir = mkdtempSync(join(tmpdir(), "gsd-mcp-cache-home-"));
78
+ try {
79
+ process.env.GSD_HOME = gsdHomeDir;
80
+ mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
81
+
82
+ const require = createRequire(import.meta.url);
83
+ const mcpModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/mcp.js")).href;
84
+ const stdioModuleUrl = pathToFileURL(require.resolve("@modelcontextprotocol/sdk/server/stdio.js")).href;
85
+ const serverPath = join(projectRoot, "fake-workflow-mcp-server.mjs");
86
+ writeFileSync(
87
+ serverPath,
88
+ [
89
+ `const { McpServer } = await import(${JSON.stringify(mcpModuleUrl)});`,
90
+ `const { StdioServerTransport } = await import(${JSON.stringify(stdioModuleUrl)});`,
91
+ 'const server = new McpServer({ name: "fake", version: "1.0.0" }, { capabilities: { tools: {} } });',
92
+ 'server.tool("ask_user_questions", "Ask questions", {}, async () => ({ content: [{ type: "text", text: "ok" }] }));',
93
+ 'await server.connect(new StdioServerTransport());',
94
+ ].join("\n"),
95
+ "utf-8",
96
+ );
97
+ writeFileSync(
98
+ join(projectRoot, ".mcp.json"),
99
+ JSON.stringify({ mcpServers: { "gsd-workflow": { command: process.execPath, args: [serverPath] } } }),
100
+ "utf-8",
101
+ );
102
+
103
+ const result = await probeAndCacheWorkflowMcp(projectRoot, { timeoutMs: 5_000 });
104
+
105
+ assert.equal(result.ok, true);
106
+ assert.equal(result.serverName, "gsd-workflow");
107
+ assert.deepEqual(result.tools, ["ask_user_questions"]);
108
+ assert.deepEqual(getCachedWorkflowMcpProbe(projectRoot)?.tools, ["ask_user_questions"]);
109
+ } finally {
110
+ if (previousGsdHome === undefined) {
111
+ delete process.env.GSD_HOME;
112
+ } else {
113
+ process.env.GSD_HOME = previousGsdHome;
114
+ }
115
+ rmSync(projectRoot, { recursive: true, force: true });
116
+ rmSync(gsdHomeDir, { recursive: true, force: true });
117
+ }
118
+ });
119
+ });
@@ -22,6 +22,7 @@ import {
22
22
  usesWorkflowMcpTransport,
23
23
  } from "../workflow-mcp.ts";
24
24
  import { DB_WORKFLOW_TOOL_NAMES } from "../workflow-tool-surface.ts";
25
+ import { UNIT_TOOL_CONTRACTS } from "../unit-tool-contracts.ts";
25
26
 
26
27
  const MCP_STDIO_TIMEOUT_MS = 90_000;
27
28
 
@@ -43,11 +44,25 @@ test("resolveWorkflowMcpProjectRoot maps milestone worktree cwd to project root"
43
44
  });
44
45
 
45
46
  test("guided execute-task requires canonical task completion tool", () => {
46
- assert.deepEqual(getRequiredWorkflowToolsForGuidedUnit("execute-task"), ["gsd_task_complete"]);
47
+ const expected = [
48
+ "gsd_task_complete",
49
+ "gsd_exec",
50
+ "gsd_exec_search",
51
+ "gsd_resume",
52
+ "gsd_capture_thought",
53
+ ];
54
+ assert.deepEqual(getRequiredWorkflowToolsForGuidedUnit("execute-task"), expected);
47
55
  });
48
56
 
49
57
  test("auto execute-task requires canonical task completion tool", () => {
50
- assert.deepEqual(getRequiredWorkflowToolsForAutoUnit("execute-task"), ["gsd_task_complete"]);
58
+ const expected = [
59
+ "gsd_task_complete",
60
+ "gsd_exec",
61
+ "gsd_exec_search",
62
+ "gsd_resume",
63
+ "gsd_capture_thought",
64
+ ];
65
+ assert.deepEqual(getRequiredWorkflowToolsForAutoUnit("execute-task"), expected);
51
66
  });
52
67
 
53
68
  test("plan-slice requires planning and roadmap reassessment tools", () => {
@@ -69,6 +84,8 @@ test("refine-slice requires canonical slice planning tool", () => {
69
84
 
70
85
  test("complete-slice requires closeout and execution handoff tools", () => {
71
86
  const expected = [
87
+ "gsd_exec",
88
+ "gsd_capture_thought",
72
89
  "gsd_slice_complete",
73
90
  "gsd_task_reopen",
74
91
  "gsd_replan_slice",
@@ -526,6 +543,52 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
526
543
  }
527
544
  });
528
545
 
546
+ test("workflow MCP stdio surface exposes every unit's required workflow tool", async () => {
547
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-workflow-all-unit-tools-"));
548
+ const isolatedGsdHome = mkdtempSync(join(tmpdir(), "gsd-workflow-all-unit-home-"));
549
+ mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
550
+
551
+ const launch = detectWorkflowMcpLaunchConfig(projectRoot, {});
552
+ assert.ok(launch, "expected a workflow MCP launch config");
553
+
554
+ const client = new Client({ name: "workflow-mcp-contract-test", version: "1.0.0" });
555
+ const transport = new StdioClientTransport({
556
+ command: launch.command,
557
+ args: launch.args,
558
+ env: {
559
+ ...process.env,
560
+ ...launch.env,
561
+ GSD_HOME: isolatedGsdHome,
562
+ DISCORD_BOT_TOKEN: "",
563
+ SLACK_BOT_TOKEN: "",
564
+ TELEGRAM_BOT_TOKEN: "",
565
+ } as Record<string, string>,
566
+ cwd: launch.cwd,
567
+ stderr: "pipe",
568
+ });
569
+
570
+ try {
571
+ await client.connect(transport, { timeout: MCP_STDIO_TIMEOUT_MS });
572
+ const listed = await client.listTools(undefined, { timeout: MCP_STDIO_TIMEOUT_MS });
573
+ const exposedTools = new Set((listed.tools ?? []).map((tool) => tool.name));
574
+
575
+ for (const [unitType, contract] of Object.entries(UNIT_TOOL_CONTRACTS)) {
576
+ for (const toolName of contract.requiredWorkflowTools) {
577
+ if (!toolName.startsWith("gsd_") && toolName !== "ask_user_questions") continue;
578
+ assert.ok(
579
+ exposedTools.has(toolName),
580
+ `${unitType} requires ${toolName}, but workflow MCP exposed ${JSON.stringify([...exposedTools].sort())}`,
581
+ );
582
+ }
583
+ }
584
+ } finally {
585
+ await client.close().catch(() => undefined);
586
+ await transport.close().catch(() => undefined);
587
+ rmSync(projectRoot, { recursive: true, force: true });
588
+ rmSync(isolatedGsdHome, { recursive: true, force: true });
589
+ }
590
+ });
591
+
529
592
  test("workflow MCP ask_user_questions uses stdio elicitation round-trip", async () => {
530
593
  const projectRoot = mkdtempSync(join(tmpdir(), "gsd-workflow-elicit-"));
531
594
  mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
@@ -0,0 +1,332 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Cross-walk matrix — every unit phase, workflow tool contract, transport
3
+ // registration, availability gate, and forbidden-tool boundary.
4
+
5
+ import test from "node:test";
6
+ import assert from "node:assert/strict";
7
+
8
+ import { WORKFLOW_TOOL_CONTRACTS } from "@opengsd/contracts";
9
+ import { registerDbTools } from "../bootstrap/db-tools.ts";
10
+ import { registerExecTools } from "../bootstrap/exec-tools.ts";
11
+ import { registerJournalTools } from "../bootstrap/journal-tools.ts";
12
+ import { registerMemoryTools } from "../bootstrap/memory-tools.ts";
13
+ import { registerQueryTools } from "../bootstrap/query-tools.ts";
14
+ import {
15
+ buildMinimalAutoGsdToolSet,
16
+ MINIMAL_AUTO_BASE_TOOL_NAMES,
17
+ MINIMAL_GSD_TOOL_NAMES,
18
+ } from "../bootstrap/register-hooks.ts";
19
+ import { shouldBlockAutoUnitToolCall } from "../auto-unit-tool-scope.ts";
20
+ import { canonicalWorkflowToolName } from "../engine-hook-contract.ts";
21
+ import { resolveToolPresentationPlan } from "../tool-presentation-plan.ts";
22
+ import { getToolSurfaceReadinessError } from "../tool-surface-readiness.ts";
23
+ import {
24
+ compileUnitContextContract,
25
+ compileUnitToolContract,
26
+ getUnitWorkflowDispatchReadinessError,
27
+ } from "../tool-contract.ts";
28
+ import {
29
+ getRequiredWorkflowToolsForUnit,
30
+ getUnitToolSurfaceContract,
31
+ UNIT_TOOL_CONTRACTS,
32
+ } from "../unit-tool-contracts.ts";
33
+ import { UNIT_MANIFESTS } from "../unit-context-manifest.ts";
34
+ import { UNIT_REGISTRY, type UnitTypeOrVariant } from "../unit-registry.ts";
35
+ import {
36
+ isWorkflowToolSurfaceName,
37
+ WORKFLOW_MCP_ADAPTER_TOOL_NAMES,
38
+ WORKFLOW_TOOL_SURFACE_NAMES,
39
+ } from "../workflow-tool-surface.ts";
40
+
41
+ const WORKFLOW_SERVER = "gsd-workflow";
42
+
43
+ const MCP_TRANSPORT = {
44
+ provider: "claude-code-cli",
45
+ projectRoot: "/tmp/gsd-matrix-project",
46
+ env: { GSD_WORKFLOW_MCP_COMMAND: "node" } as NodeJS.ProcessEnv,
47
+ surface: "contract-matrix",
48
+ authMode: "externalCli" as const,
49
+ baseUrl: "local://claude-code",
50
+ };
51
+
52
+ /** Native Pi registers some contract names under legacy aliases. */
53
+ const NATIVE_TOOL_EQUIVALENTS: Readonly<Record<string, readonly string[]>> = {
54
+ gsd_capture_thought: ["capture_thought", "gsd_capture_thought"],
55
+ gsd_memory_query: ["memory_query", "gsd_memory_query"],
56
+ gsd_memory_graph: ["gsd_graph", "gsd_memory_graph"],
57
+ };
58
+
59
+ const REGISTERED_SURFACE_TOOL_NAMES = [
60
+ ...new Set([
61
+ ...MINIMAL_AUTO_BASE_TOOL_NAMES,
62
+ ...MINIMAL_GSD_TOOL_NAMES,
63
+ ...Object.values(UNIT_TOOL_CONTRACTS).flatMap((contract) => contract.allowedGsdTools),
64
+ ...WORKFLOW_TOOL_SURFACE_NAMES,
65
+ ]),
66
+ ];
67
+
68
+ function makeMockPi() {
69
+ const tools: Array<{ name: string }> = [];
70
+ return {
71
+ registerTool(tool: { name: string }) {
72
+ tools.push(tool);
73
+ },
74
+ tools,
75
+ } as const;
76
+ }
77
+
78
+ function collectNativeRegisteredToolNames(): Set<string> {
79
+ const pi = makeMockPi();
80
+ registerDbTools(pi as never);
81
+ registerExecTools(pi as never);
82
+ registerQueryTools(pi as never);
83
+ registerJournalTools(pi as never);
84
+ registerMemoryTools(pi as never);
85
+ return new Set(pi.tools.map((tool) => tool.name));
86
+ }
87
+
88
+ function workflowToolsForUnit(unitType: string): string[] {
89
+ return getRequiredWorkflowToolsForUnit(unitType).filter(
90
+ (tool) => tool.startsWith("gsd_") || tool === "ask_user_questions",
91
+ );
92
+ }
93
+
94
+ function mockConnectedObservation(requiredTools: readonly string[]) {
95
+ return {
96
+ tools: requiredTools.map((tool) => `mcp__${WORKFLOW_SERVER}__${tool}`),
97
+ mcpServers: [{ name: WORKFLOW_SERVER, status: "connected" }],
98
+ };
99
+ }
100
+
101
+ function assertNativeToolRegistered(
102
+ registered: Set<string>,
103
+ contractName: string,
104
+ label: string,
105
+ ): void {
106
+ const candidates = [contractName, ...(NATIVE_TOOL_EQUIVALENTS[contractName] ?? [])];
107
+ assert.ok(
108
+ candidates.some((name) => registered.has(name)),
109
+ `${label}: native transport missing ${contractName} (candidates: ${candidates.join(", ")})`,
110
+ );
111
+ }
112
+
113
+ function unitHasManifest(unitType: string): boolean {
114
+ return unitType in UNIT_MANIFESTS;
115
+ }
116
+
117
+ function unitTypesWithContracts(): Array<[UnitTypeOrVariant, (typeof UNIT_REGISTRY)[UnitTypeOrVariant]]> {
118
+ return Object.entries(UNIT_REGISTRY).filter(
119
+ (entry): entry is [UnitTypeOrVariant, (typeof UNIT_REGISTRY)[UnitTypeOrVariant]] =>
120
+ entry[1].toolContract !== null,
121
+ );
122
+ }
123
+
124
+ // ─── Unit phase × contract integrity ───────────────────────────────────────
125
+
126
+ test("every manifest-backed unit with a tool contract compiles Tool Contract and Context Contract", () => {
127
+ for (const [unitType] of unitTypesWithContracts()) {
128
+ if (!unitHasManifest(unitType)) continue;
129
+ const toolResult = compileUnitToolContract(unitType);
130
+ assert.equal(toolResult.ok, true, `${unitType} must compile Tool Contract`);
131
+
132
+ const contextResult = compileUnitContextContract(unitType);
133
+ assert.equal(contextResult.ok, true, `${unitType} must compile Context Contract`);
134
+ }
135
+ });
136
+
137
+ for (const [unitType, descriptor] of unitTypesWithContracts()) {
138
+ test(`${unitType}: required workflow tools are declared, on-surface, and allowed`, () => {
139
+ const contract = descriptor.toolContract!;
140
+ const allowed = new Set(contract.allowedGsdTools.map((tool) => String(tool)));
141
+
142
+ for (const required of contract.requiredWorkflowTools) {
143
+ const name = String(required);
144
+ if (name === "subagent") {
145
+ assert.ok(allowed.has("subagent"), `${unitType}: subagent required but not allowed`);
146
+ continue;
147
+ }
148
+ assert.ok(
149
+ allowed.has(name) || name === "ask_user_questions",
150
+ `${unitType}: required ${name} must be allowed or be ask_user_questions`,
151
+ );
152
+ if (name.startsWith("gsd_")) {
153
+ assert.ok(
154
+ isWorkflowToolSurfaceName(name),
155
+ `${unitType}: required ${name} must be on WORKFLOW_TOOL_SURFACE_NAMES`,
156
+ );
157
+ } else if (name === "ask_user_questions") {
158
+ assert.ok(
159
+ (WORKFLOW_MCP_ADAPTER_TOOL_NAMES as readonly string[]).includes(name),
160
+ `${unitType}: ask_user_questions must be on the MCP adapter surface`,
161
+ );
162
+ }
163
+ }
164
+ });
165
+ }
166
+
167
+ for (const [unitType, descriptor] of unitTypesWithContracts()) {
168
+ const requiredTools = workflowToolsForUnit(unitType);
169
+ if (requiredTools.length === 0) continue;
170
+
171
+ test(`${unitType}: static dispatch gate passes when workflow MCP is configured`, () => {
172
+ const error = getUnitWorkflowDispatchReadinessError({
173
+ ...MCP_TRANSPORT,
174
+ unitType,
175
+ activeTools: REGISTERED_SURFACE_TOOL_NAMES,
176
+ });
177
+ assert.equal(error, null, `${unitType} static gate: ${error ?? "ok"}`);
178
+ });
179
+
180
+ test(`${unitType}: runtime tool-surface readiness passes when MCP tools are connected`, () => {
181
+ const error = getToolSurfaceReadinessError({
182
+ unitType,
183
+ workflowServerName: WORKFLOW_SERVER,
184
+ observation: mockConnectedObservation(requiredTools),
185
+ });
186
+ assert.equal(error, null, `${unitType} runtime readiness: ${error ?? "ok"}`);
187
+ });
188
+
189
+ test(`${unitType}: runtime readiness fails when a required workflow tool is missing`, () => {
190
+ if (requiredTools.length === 0) return;
191
+ const missing = requiredTools[0];
192
+ const partial = requiredTools.filter((tool) => tool !== missing);
193
+ const error = getToolSurfaceReadinessError({
194
+ unitType,
195
+ workflowServerName: WORKFLOW_SERVER,
196
+ observation: mockConnectedObservation(partial),
197
+ });
198
+ assert.ok(error, `${unitType} should fail readiness when ${missing} is absent`);
199
+ assert.match(error!, new RegExp(missing.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
200
+ });
201
+
202
+ test(`${unitType}: native auto scoping exposes every required workflow tool`, () => {
203
+ const scoped = buildMinimalAutoGsdToolSet(
204
+ REGISTERED_SURFACE_TOOL_NAMES,
205
+ unitType,
206
+ REGISTERED_SURFACE_TOOL_NAMES,
207
+ );
208
+ for (const required of contractRequiredNames(unitType)) {
209
+ const canonical = canonicalWorkflowToolName(required);
210
+ const nativeCandidates = NATIVE_TOOL_EQUIVALENTS[canonical] ?? [canonical];
211
+ assert.ok(
212
+ scoped.some((tool) => nativeCandidates.includes(tool) || tool === canonical),
213
+ `${unitType}: scoped tools missing ${required}; got ${scoped.join(", ")}`,
214
+ );
215
+ }
216
+ });
217
+
218
+ test(`${unitType}: MCP presentation plan exposes every required workflow tool`, () => {
219
+ const requested = [
220
+ ...new Set([
221
+ ...(descriptor.toolContract?.allowedGsdTools ?? []),
222
+ ...requiredTools,
223
+ ]),
224
+ ].filter((tool) => String(tool).startsWith("gsd_") || tool === "ask_user_questions");
225
+ const plan = resolveToolPresentationPlan({
226
+ phase: unitType,
227
+ surface: "claude-code-sdk",
228
+ workflowMcpServerName: WORKFLOW_SERVER,
229
+ requestedToolNames: requested.map(String),
230
+ availableToolNames: REGISTERED_SURFACE_TOOL_NAMES,
231
+ });
232
+ for (const required of requiredTools) {
233
+ const presented = `mcp__${WORKFLOW_SERVER}__${required}`;
234
+ assert.ok(
235
+ plan.presentedToolNames.includes(presented),
236
+ `${unitType}: presentation plan missing ${presented}; got ${plan.presentedToolNames.join(", ")}`,
237
+ );
238
+ }
239
+ });
240
+ }
241
+
242
+ function contractRequiredNames(unitType: string): string[] {
243
+ return getRequiredWorkflowToolsForUnit(unitType).filter((tool) => tool !== "ask_user_questions");
244
+ }
245
+
246
+ for (const [unitType, descriptor] of unitTypesWithContracts()) {
247
+ const contract = descriptor.toolContract;
248
+ if (!contract || !("forbiddenGsdTools" in contract) || !contract.forbiddenGsdTools) continue;
249
+ const forbidden = Object.entries(contract.forbiddenGsdTools);
250
+
251
+ for (const [toolName, reason] of forbidden) {
252
+ test(`${unitType}: forbids ${toolName} — ${reason}`, () => {
253
+ const block = shouldBlockAutoUnitToolCall(unitType, toolName);
254
+ assert.equal(block.block, true, `${unitType} must block ${toolName}`);
255
+ assert.ok(block.reason, `${unitType} block reason for ${toolName}`);
256
+ });
257
+ }
258
+ }
259
+
260
+ // ─── Workflow tool contract × transports ───────────────────────────────────
261
+
262
+ test("every canonical workflow contract tool is on the compiled MCP surface list", () => {
263
+ for (const contract of WORKFLOW_TOOL_CONTRACTS) {
264
+ assert.ok(
265
+ isWorkflowToolSurfaceName(contract.canonicalName),
266
+ `${contract.canonicalName} missing from WORKFLOW_TOOL_SURFACE_NAMES`,
267
+ );
268
+ for (const alias of contract.aliases) {
269
+ assert.ok(
270
+ isWorkflowToolSurfaceName(alias),
271
+ `alias ${alias} for ${contract.canonicalName} missing from surface`,
272
+ );
273
+ }
274
+ }
275
+ });
276
+
277
+ test("every unit-required workflow tool resolves to a registered contract canonical name", () => {
278
+ const canonicalNames = new Set<string>(WORKFLOW_TOOL_CONTRACTS.map((tool) => tool.canonicalName));
279
+ const adapterNames = new Set(WORKFLOW_MCP_ADAPTER_TOOL_NAMES as readonly string[]);
280
+
281
+ for (const [unitType] of unitTypesWithContracts()) {
282
+ for (const required of getRequiredWorkflowToolsForUnit(unitType)) {
283
+ const name = String(required);
284
+ if (name === "ask_user_questions") {
285
+ assert.ok(adapterNames.has(name), `${unitType}: ${name} must be adapter-registered`);
286
+ continue;
287
+ }
288
+ if (name === "subagent") continue;
289
+ const canonical = canonicalWorkflowToolName(name);
290
+ assert.ok(
291
+ canonicalNames.has(canonical),
292
+ `${unitType}: required ${name} canonicalizes to unknown contract ${canonical}`,
293
+ );
294
+ }
295
+ }
296
+ });
297
+
298
+ test("native bootstrap registers every contract canonical tool (or documented equivalent)", () => {
299
+ const registered = collectNativeRegisteredToolNames();
300
+ for (const contract of WORKFLOW_TOOL_CONTRACTS) {
301
+ assertNativeToolRegistered(registered, contract.canonicalName, "native bootstrap");
302
+ }
303
+ });
304
+
305
+ test("every write-policy workflow contract declares schema and audit metadata", () => {
306
+ for (const contract of WORKFLOW_TOOL_CONTRACTS) {
307
+ assert.match(contract.schemaId, /^workflow\./, `${contract.canonicalName} schemaId`);
308
+ assert.match(contract.auditEvent, /^workflow\./, `${contract.canonicalName} auditEvent`);
309
+ assert.ok(contract.executorId.length > 0, `${contract.canonicalName} executorId`);
310
+ if (contract.writePolicy === "write") {
311
+ assert.notEqual(
312
+ contract.executorId,
313
+ "executeMilestoneStatus",
314
+ `${contract.canonicalName} write tool must not use read executor`,
315
+ );
316
+ }
317
+ }
318
+ });
319
+
320
+ test("registry tool contracts stay aligned with UNIT_TOOL_CONTRACTS view", () => {
321
+ for (const [unitType, descriptor] of Object.entries(UNIT_REGISTRY)) {
322
+ if (!descriptor.toolContract) {
323
+ assert.equal(getUnitToolSurfaceContract(unitType), undefined);
324
+ continue;
325
+ }
326
+ assert.deepEqual(
327
+ getUnitToolSurfaceContract(unitType),
328
+ descriptor.toolContract,
329
+ `${unitType} derived contract drift`,
330
+ );
331
+ }
332
+ });
@@ -89,3 +89,23 @@ test("resolveConflict(pick=main) rewrites the worktree log durably", () => {
89
89
  const second = reconcileWorktreeLogs(main, worktree);
90
90
  assert.equal(second.conflicts.length, 0, "reconcile should stay clean after choosing main");
91
91
  });
92
+
93
+ test("reconcileWorktreeLogs treats canonical worktree project-ledger appends as already durable", () => {
94
+ const root = mkdtempSync(join(tmpdir(), "workflow-reconcile-canonical-"));
95
+ const main = join(root, "main");
96
+ const worktree = join(main, ".gsd-worktrees", "M001");
97
+ mkdirSync(worktree, { recursive: true });
98
+ tmpDirs.push(root);
99
+
100
+ appendEvent(worktree, {
101
+ cmd: "complete-task",
102
+ params: { milestoneId: "M001", sliceId: "S01", taskId: "T01" },
103
+ ts: "2026-01-01T00:00:00.000Z",
104
+ actor: "agent",
105
+ });
106
+
107
+ const result = reconcileWorktreeLogs(main, worktree);
108
+
109
+ assert.equal(result.autoMerged, 0, "project-ledger append should not replay the root log");
110
+ assert.equal(result.conflicts.length, 0, "missing worktree shard is not a conflict");
111
+ });
@@ -7,6 +7,9 @@
7
7
 
8
8
  import { test } from 'node:test';
9
9
  import assert from 'node:assert/strict';
10
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import { join } from 'node:path';
10
13
  import {
11
14
  loadRegistry,
12
15
  resolveByName,
@@ -16,6 +19,11 @@ import {
16
19
  getTemplateInfo,
17
20
  loadWorkflowTemplate,
18
21
  } from '../workflow-templates.ts';
22
+ import {
23
+ findInProgressWorkflows,
24
+ isWorkflowStateComplete,
25
+ type WorkflowState,
26
+ } from '../commands-workflow-templates.ts';
19
27
 
20
28
 
21
29
  // ═══════════════════════════════════════════════════════════════════════════
@@ -196,3 +204,87 @@ console.log('\n── Load Workflow Template ──');
196
204
  }
197
205
 
198
206
  // ═══════════════════════════════════════════════════════════════════════════
207
+
208
+ console.log('\n── Workflow Resume State ──');
209
+
210
+ {
211
+ const started: WorkflowState = {
212
+ template: 'bugfix',
213
+ templateName: 'Bug Fix',
214
+ description: 'fix resume drift',
215
+ branch: 'gsd/bugfix/fix-resume-drift',
216
+ phases: [
217
+ { name: 'triage', index: 0, status: 'completed' },
218
+ { name: 'fix', index: 1, status: 'active' },
219
+ { name: 'verify', index: 2, status: 'pending' },
220
+ ],
221
+ currentPhase: 1,
222
+ startedAt: '2026-06-15T00:00:00.000Z',
223
+ updatedAt: '2026-06-15T00:01:00.000Z',
224
+ artifactDir: 'workflows/bugfixes/260615-1-fix-resume-drift',
225
+ };
226
+
227
+ assert.equal(isWorkflowStateComplete(started), false, 'active phase should be resumable');
228
+ assert.equal(
229
+ isWorkflowStateComplete({
230
+ ...started,
231
+ phases: started.phases.map((phase) => ({ ...phase, status: 'completed' })),
232
+ currentPhase: 2,
233
+ updatedAt: '2026-06-15T00:02:00.000Z',
234
+ }),
235
+ true,
236
+ 'all completed phases should be treated as complete even when completedAt is absent',
237
+ );
238
+ assert.equal(
239
+ isWorkflowStateComplete({ ...started, completedAt: '2026-06-15T00:03:00.000Z' }),
240
+ true,
241
+ 'completedAt should mark the workflow complete',
242
+ );
243
+ }
244
+
245
+ test('findInProgressWorkflows ignores completed phase-only STATE files', (t) => {
246
+ const base = mkdtempSync(join(tmpdir(), 'gsd-workflow-resume-'));
247
+ t.after(() => rmSync(base, { recursive: true, force: true }));
248
+
249
+ const workflowsRoot = join(base, '.gsd', 'workflows', 'bugfixes');
250
+ mkdirSync(join(workflowsRoot, '260615-1-complete'), { recursive: true });
251
+ mkdirSync(join(workflowsRoot, '260615-2-active'), { recursive: true });
252
+
253
+ const common = {
254
+ template: 'bugfix',
255
+ templateName: 'Bug Fix',
256
+ description: 'fix resume drift',
257
+ branch: 'gsd/bugfix/fix-resume-drift',
258
+ startedAt: '2026-06-15T00:00:00.000Z',
259
+ artifactDir: 'workflows/bugfixes/260615-1-complete',
260
+ };
261
+
262
+ writeFileSync(join(workflowsRoot, '260615-1-complete', 'STATE.json'), JSON.stringify({
263
+ ...common,
264
+ phases: [
265
+ { name: 'triage', index: 0, status: 'completed' },
266
+ { name: 'fix', index: 1, status: 'completed' },
267
+ { name: 'verify', index: 2, status: 'completed' },
268
+ ],
269
+ currentPhase: 2,
270
+ updatedAt: '2026-06-15T00:02:00.000Z',
271
+ }), 'utf-8');
272
+
273
+ writeFileSync(join(workflowsRoot, '260615-2-active', 'STATE.json'), JSON.stringify({
274
+ ...common,
275
+ artifactDir: 'workflows/bugfixes/260615-2-active',
276
+ phases: [
277
+ { name: 'triage', index: 0, status: 'completed' },
278
+ { name: 'fix', index: 1, status: 'active' },
279
+ { name: 'verify', index: 2, status: 'pending' },
280
+ ],
281
+ currentPhase: 1,
282
+ updatedAt: '2026-06-15T00:03:00.000Z',
283
+ }), 'utf-8');
284
+
285
+ const inProgress = findInProgressWorkflows(base);
286
+ assert.equal(inProgress.length, 1);
287
+ assert.equal(inProgress[0]?.artifactDir, 'workflows/bugfixes/260615-2-active');
288
+ });
289
+
290
+ // ═══════════════════════════════════════════════════════════════════════════