gsd-pi 2.44.0 → 2.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/README.md +30 -12
  2. package/dist/resources/extensions/gsd/activity-log.js +7 -0
  3. package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
  4. package/dist/resources/extensions/gsd/auto/phases.js +37 -36
  5. package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
  6. package/dist/resources/extensions/gsd/auto-start.js +31 -2
  7. package/dist/resources/extensions/gsd/auto-timers.js +57 -3
  8. package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
  9. package/dist/resources/extensions/gsd/auto-worktree.js +9 -6
  10. package/dist/resources/extensions/gsd/auto.js +30 -3
  11. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +156 -0
  12. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
  13. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  14. package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
  15. package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
  16. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  17. package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
  18. package/dist/resources/extensions/gsd/db-writer.js +34 -16
  19. package/dist/resources/extensions/gsd/doctor.js +8 -0
  20. package/dist/resources/extensions/gsd/git-service.js +8 -3
  21. package/dist/resources/extensions/gsd/gsd-db.js +12 -1
  22. package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
  23. package/dist/resources/extensions/gsd/preferences.js +9 -1
  24. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  25. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  26. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  27. package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  28. package/dist/resources/extensions/gsd/prompts/rethink.md +78 -0
  29. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  30. package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
  31. package/dist/resources/extensions/gsd/repo-identity.js +45 -7
  32. package/dist/resources/extensions/gsd/rethink.js +115 -0
  33. package/dist/resources/extensions/gsd/state.js +41 -3
  34. package/dist/resources/extensions/gsd/tools/plan-slice.js +1 -0
  35. package/dist/resources/extensions/gsd/tools/plan-task.js +1 -0
  36. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -0
  37. package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
  38. package/dist/resources/extensions/gsd/worktree-manager.js +32 -2
  39. package/dist/resources/extensions/gsd/worktree-resolver.js +6 -0
  40. package/dist/resources/extensions/mcp-client/index.js +14 -0
  41. package/dist/web/standalone/.next/BUILD_ID +1 -1
  42. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  43. package/dist/web/standalone/.next/build-manifest.json +3 -3
  44. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  45. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  46. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  47. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  48. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/_not-found/page.js +1 -1
  56. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  58. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  59. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  60. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  62. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  65. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/index.html +1 -1
  106. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  107. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  108. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  109. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  111. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  112. package/dist/web/standalone/.next/server/app/page.js +1 -1
  113. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  115. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  118. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  119. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  120. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +9 -0
  121. package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
  122. package/dist/web/standalone/.next/static/chunks/app/{page-7e9530a7122506c5.js → page-12dd5ece0df4badc.js} +1 -1
  123. package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
  124. package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
  125. package/package.json +1 -1
  126. package/packages/native/dist/stream-process/index.js +2 -2
  127. package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
  128. package/packages/native/src/stream-process/index.ts +2 -2
  129. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
  130. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  131. package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
  132. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  133. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  134. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  135. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  136. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  137. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  138. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  139. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
  140. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
  141. package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
  142. package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
  143. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +11 -0
  144. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  145. package/packages/pi-coding-agent/dist/core/model-registry.js +20 -1
  146. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  147. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  148. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  149. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  150. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  151. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  152. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  153. package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
  154. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  155. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  156. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  157. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  158. package/packages/pi-coding-agent/dist/main.js +17 -0
  159. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
  161. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
  162. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
  163. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
  164. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  165. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  166. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
  167. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  168. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  169. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  170. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  171. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  172. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
  173. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
  174. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
  175. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
  176. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  177. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
  178. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
  180. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  181. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
  182. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  184. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
  185. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
  188. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  190. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  191. package/packages/pi-coding-agent/package.json +1 -1
  192. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  193. package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
  194. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  195. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  196. package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
  197. package/packages/pi-coding-agent/src/core/model-registry.ts +21 -1
  198. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  199. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  200. package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
  201. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  202. package/packages/pi-coding-agent/src/main.ts +19 -0
  203. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
  204. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
  205. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  206. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
  207. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
  208. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
  209. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
  210. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
  211. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  212. package/pkg/package.json +1 -1
  213. package/src/resources/extensions/gsd/activity-log.ts +1 -0
  214. package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
  215. package/src/resources/extensions/gsd/auto/phases.ts +46 -48
  216. package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
  217. package/src/resources/extensions/gsd/auto-start.ts +39 -2
  218. package/src/resources/extensions/gsd/auto-timers.ts +64 -3
  219. package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
  220. package/src/resources/extensions/gsd/auto-worktree.ts +9 -6
  221. package/src/resources/extensions/gsd/auto.ts +37 -3
  222. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +148 -0
  223. package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
  224. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  225. package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
  226. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  227. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  228. package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
  229. package/src/resources/extensions/gsd/db-writer.ts +39 -17
  230. package/src/resources/extensions/gsd/doctor.ts +7 -1
  231. package/src/resources/extensions/gsd/git-service.ts +6 -2
  232. package/src/resources/extensions/gsd/gsd-db.ts +16 -1
  233. package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
  234. package/src/resources/extensions/gsd/preferences.ts +11 -1
  235. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  236. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  237. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  238. package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  239. package/src/resources/extensions/gsd/prompts/rethink.md +78 -0
  240. package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  241. package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
  242. package/src/resources/extensions/gsd/repo-identity.ts +46 -7
  243. package/src/resources/extensions/gsd/rethink.ts +154 -0
  244. package/src/resources/extensions/gsd/state.ts +41 -1
  245. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  246. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  247. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  248. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
  249. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  250. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  251. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  252. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  253. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  254. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  255. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  256. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  257. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  258. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  259. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  260. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  261. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  262. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  263. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  264. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
  265. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  266. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  267. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  268. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  269. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  270. package/src/resources/extensions/gsd/tests/db-writer.test.ts +465 -416
  271. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  272. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  273. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
  274. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +210 -181
  275. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  276. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  277. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  278. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  279. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  280. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  281. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  282. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  283. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  284. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  285. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  286. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  287. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  288. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  289. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  290. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  291. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  292. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  293. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  294. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
  295. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  296. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  297. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  298. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  299. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  300. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  301. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  302. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  303. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  304. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  305. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  306. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  307. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  308. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  309. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  310. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  311. package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
  312. package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
  313. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  314. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  315. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  316. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  317. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  318. package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
  319. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  320. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
  321. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  322. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  323. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  324. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
  325. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  326. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  327. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  328. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  329. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  330. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  331. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  332. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  333. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  334. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  335. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  336. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  337. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  338. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  339. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  340. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  341. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  342. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  343. package/src/resources/extensions/gsd/tests/preferences.test.ts +27 -0
  344. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -7
  345. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  346. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  347. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  348. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  349. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  350. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  351. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  352. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
  353. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  354. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  355. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  356. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  357. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  358. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  359. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  360. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  361. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  362. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  363. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  364. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  365. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
  366. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
  367. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  368. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
  369. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  370. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  371. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +10 -11
  372. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  373. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  374. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  375. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  376. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  377. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  378. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  379. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  380. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  381. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  382. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  383. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  384. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  385. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  386. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  387. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
  388. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  389. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  390. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  391. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
  392. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -0
  393. package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -0
  394. package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
  395. package/src/resources/extensions/gsd/worktree-manager.ts +43 -2
  396. package/src/resources/extensions/gsd/worktree-resolver.ts +7 -0
  397. package/src/resources/extensions/mcp-client/index.ts +20 -0
  398. package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
  399. package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
  400. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
  401. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → wUzEX1U3CmFcMry2SUDJn}/_buildManifest.js +0 -0
  402. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → wUzEX1U3CmFcMry2SUDJn}/_ssgManifest.js +0 -0
@@ -1,5 +1,6 @@
1
1
  import { Type } from "@sinclair/typebox";
2
2
  import type { ExtensionAPI } from "@gsd/pi-coding-agent";
3
+ import { Text } from "@gsd/pi-tui";
3
4
 
4
5
  import { findMilestoneIds, nextMilestoneId, claimReservedId, getReservedMilestoneIds } from "../guided-flow.js";
5
6
  import { loadEffectiveGSDPreferences } from "../preferences.js";
@@ -87,6 +88,22 @@ export function registerDbTools(pi: ExtensionAPI): void {
87
88
  ], { description: "Who made this decision: 'human' (user directed), 'agent' (LLM decided autonomously), or 'collaborative' (discussed and agreed). Default: 'agent'" })),
88
89
  }),
89
90
  execute: decisionSaveExecute,
91
+ renderCall(args: any, theme: any) {
92
+ let text = theme.fg("toolTitle", theme.bold("decision_save "));
93
+ if (args.scope) text += theme.fg("accent", `[${args.scope}] `);
94
+ if (args.decision) text += theme.fg("muted", args.decision);
95
+ if (args.choice) text += theme.fg("dim", ` — ${args.choice}`);
96
+ return new Text(text, 0, 0);
97
+ },
98
+ renderResult(result: any, _options: any, theme: any) {
99
+ const d = result.details;
100
+ if (result.isError || d?.error) {
101
+ return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
102
+ }
103
+ let text = theme.fg("success", `Decision ${d?.id ?? ""} saved`);
104
+ if (d?.id) text += theme.fg("dim", ` → DECISIONS.md`);
105
+ return new Text(text, 0, 0);
106
+ },
90
107
  };
91
108
 
92
109
  pi.registerTool(decisionSaveTool);
@@ -157,6 +174,22 @@ export function registerDbTools(pi: ExtensionAPI): void {
157
174
  supporting_slices: Type.Optional(Type.String({ description: "Supporting slices" })),
158
175
  }),
159
176
  execute: requirementUpdateExecute,
177
+ renderCall(args: any, theme: any) {
178
+ let text = theme.fg("toolTitle", theme.bold("requirement_update "));
179
+ if (args.id) text += theme.fg("accent", args.id);
180
+ const fields = ["status", "validation", "notes", "description"].filter((f) => args[f]);
181
+ if (fields.length > 0) text += theme.fg("dim", ` (${fields.join(", ")})`);
182
+ return new Text(text, 0, 0);
183
+ },
184
+ renderResult(result: any, _options: any, theme: any) {
185
+ const d = result.details;
186
+ if (result.isError || d?.error) {
187
+ return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
188
+ }
189
+ let text = theme.fg("success", `Requirement ${d?.id ?? ""} updated`);
190
+ text += theme.fg("dim", ` → REQUIREMENTS.md`);
191
+ return new Text(text, 0, 0);
192
+ },
160
193
  };
161
194
 
162
195
  pi.registerTool(requirementUpdateTool);
@@ -235,6 +268,22 @@ export function registerDbTools(pi: ExtensionAPI): void {
235
268
  content: Type.String({ description: "The full markdown content of the artifact" }),
236
269
  }),
237
270
  execute: summarySaveExecute,
271
+ renderCall(args: any, theme: any) {
272
+ let text = theme.fg("toolTitle", theme.bold("summary_save "));
273
+ if (args.artifact_type) text += theme.fg("accent", args.artifact_type);
274
+ const path = [args.milestone_id, args.slice_id, args.task_id].filter(Boolean).join("/");
275
+ if (path) text += theme.fg("dim", ` ${path}`);
276
+ return new Text(text, 0, 0);
277
+ },
278
+ renderResult(result: any, _options: any, theme: any) {
279
+ const d = result.details;
280
+ if (result.isError || d?.error) {
281
+ return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
282
+ }
283
+ let text = theme.fg("success", `${d?.artifact_type ?? "Artifact"} saved`);
284
+ if (d?.path) text += theme.fg("dim", ` → ${d.path}`);
285
+ return new Text(text, 0, 0);
286
+ },
238
287
  };
239
288
 
240
289
  pi.registerTool(summarySaveTool);
@@ -248,6 +297,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
248
297
  // This guarantees the ID shown in the UI matches the one materialised on disk.
249
298
  const reserved = claimReservedId();
250
299
  if (reserved) {
300
+ await ensureMilestoneDbRow(reserved);
251
301
  return {
252
302
  content: [{ type: "text" as const, text: reserved }],
253
303
  details: { operation: "generate_milestone_id", id: reserved, source: "reserved" } as any,
@@ -259,6 +309,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
259
309
  const uniqueEnabled = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
260
310
  const allIds = [...new Set([...existingIds, ...getReservedMilestoneIds()])];
261
311
  const newId = nextMilestoneId(allIds, uniqueEnabled);
312
+ await ensureMilestoneDbRow(newId);
262
313
  return {
263
314
  content: [{ type: "text" as const, text: newId }],
264
315
  details: { operation: "generate_milestone_id", id: newId, existingCount: existingIds.length, uniqueEnabled } as any,
@@ -272,6 +323,23 @@ export function registerDbTools(pi: ExtensionAPI): void {
272
323
  }
273
324
  };
274
325
 
326
+ /**
327
+ * Insert a minimal DB row for a milestone ID so it's visible to the state
328
+ * machine. Uses INSERT OR IGNORE — safe to call even if gsd_plan_milestone
329
+ * later writes the full row. Silently skips if the DB isn't available yet
330
+ * (pre-migration).
331
+ */
332
+ async function ensureMilestoneDbRow(milestoneId: string): Promise<void> {
333
+ const dbAvailable = await ensureDbOpen();
334
+ if (!dbAvailable) return;
335
+ try {
336
+ const { insertMilestone } = await import("../gsd-db.js");
337
+ insertMilestone({ id: milestoneId, status: "queued" });
338
+ } catch {
339
+ // Non-fatal — the safety-net in deriveStateFromDb will catch this
340
+ }
341
+ }
342
+
275
343
  const milestoneGenerateIdTool = {
276
344
  name: "gsd_milestone_generate_id",
277
345
  label: "Generate Milestone ID",
@@ -288,6 +356,18 @@ export function registerDbTools(pi: ExtensionAPI): void {
288
356
  ],
289
357
  parameters: Type.Object({}),
290
358
  execute: milestoneGenerateIdExecute,
359
+ renderCall(_args: any, theme: any) {
360
+ return new Text(theme.fg("toolTitle", theme.bold("milestone_generate_id")), 0, 0);
361
+ },
362
+ renderResult(result: any, _options: any, theme: any) {
363
+ const d = result.details;
364
+ if (result.isError || d?.error) {
365
+ return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
366
+ }
367
+ let text = theme.fg("success", `Generated ${d?.id ?? "ID"}`);
368
+ if (d?.source === "reserved") text += theme.fg("dim", " (reserved)");
369
+ return new Text(text, 0, 0);
370
+ },
291
371
  };
292
372
 
293
373
  pi.registerTool(milestoneGenerateIdTool);
@@ -794,6 +874,74 @@ export function registerDbTools(pi: ExtensionAPI): void {
794
874
  pi.registerTool(milestoneCompleteTool);
795
875
  registerAlias(pi, milestoneCompleteTool, "gsd_milestone_complete", "gsd_complete_milestone");
796
876
 
877
+ // ─── gsd_validate_milestone (gsd_milestone_validate alias) ─────────────
878
+
879
+ const milestoneValidateExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
880
+ const dbAvailable = await ensureDbOpen();
881
+ if (!dbAvailable) {
882
+ return {
883
+ content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot validate milestone." }],
884
+ details: { operation: "validate_milestone", error: "db_unavailable" } as any,
885
+ };
886
+ }
887
+ try {
888
+ const { handleValidateMilestone } = await import("../tools/validate-milestone.js");
889
+ const result = await handleValidateMilestone(params, process.cwd());
890
+ if ("error" in result) {
891
+ return {
892
+ content: [{ type: "text" as const, text: `Error validating milestone: ${result.error}` }],
893
+ details: { operation: "validate_milestone", error: result.error } as any,
894
+ };
895
+ }
896
+ return {
897
+ content: [{ type: "text" as const, text: `Validated milestone ${result.milestoneId} — verdict: ${result.verdict}. Written to ${result.validationPath}` }],
898
+ details: {
899
+ operation: "validate_milestone",
900
+ milestoneId: result.milestoneId,
901
+ verdict: result.verdict,
902
+ validationPath: result.validationPath,
903
+ } as any,
904
+ };
905
+ } catch (err) {
906
+ const msg = err instanceof Error ? err.message : String(err);
907
+ process.stderr.write(`gsd-db: validate_milestone tool failed: ${msg}\n`);
908
+ return {
909
+ content: [{ type: "text" as const, text: `Error validating milestone: ${msg}` }],
910
+ details: { operation: "validate_milestone", error: msg } as any,
911
+ };
912
+ }
913
+ };
914
+
915
+ const milestoneValidateTool = {
916
+ name: "gsd_validate_milestone",
917
+ label: "Validate Milestone",
918
+ description:
919
+ "Validate a milestone before completion — persist validation results to the DB, render VALIDATION.md to disk. " +
920
+ "Records verdict (pass/needs-attention/needs-remediation) and rationale.",
921
+ promptSnippet: "Validate a GSD milestone (DB write + VALIDATION.md render)",
922
+ promptGuidelines: [
923
+ "Use gsd_validate_milestone when all slices are done and the milestone needs validation before completion.",
924
+ "Parameters: milestoneId, verdict, remediationRound, successCriteriaChecklist, sliceDeliveryAudit, crossSliceIntegration, requirementCoverage, verdictRationale, remediationPlan (optional).",
925
+ "If verdict is 'needs-remediation', also provide remediationPlan and use gsd_reassess_roadmap to add remediation slices to the roadmap.",
926
+ "On success, returns validationPath where VALIDATION.md was written.",
927
+ ],
928
+ parameters: Type.Object({
929
+ milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
930
+ verdict: StringEnum(["pass", "needs-attention", "needs-remediation"], { description: "Validation verdict" }),
931
+ remediationRound: Type.Number({ description: "Remediation round (0 for first validation)" }),
932
+ successCriteriaChecklist: Type.String({ description: "Markdown checklist of success criteria with pass/fail and evidence" }),
933
+ sliceDeliveryAudit: Type.String({ description: "Markdown table auditing each slice's claimed vs delivered output" }),
934
+ crossSliceIntegration: Type.String({ description: "Markdown describing any cross-slice boundary mismatches" }),
935
+ requirementCoverage: Type.String({ description: "Markdown describing any unaddressed requirements" }),
936
+ verdictRationale: Type.String({ description: "Why this verdict was chosen" }),
937
+ remediationPlan: Type.Optional(Type.String({ description: "Remediation plan (required if verdict is needs-remediation)" })),
938
+ }),
939
+ execute: milestoneValidateExecute,
940
+ };
941
+
942
+ pi.registerTool(milestoneValidateTool);
943
+ registerAlias(pi, milestoneValidateTool, "gsd_milestone_validate", "gsd_validate_milestone");
944
+
797
945
  // ─── gsd_replan_slice (gsd_slice_replan alias) ─────────────────────────
798
946
 
799
947
  const replanSliceExecute = async (_toolCallId: string, params: any, _signal: AbortSignal | undefined, _onUpdate: unknown, _ctx: unknown) => {
@@ -64,17 +64,12 @@ export async function buildBeforeAgentStartResult(
64
64
  }
65
65
  }
66
66
 
67
- let knowledgeBlock = "";
68
- const knowledgePath = resolveGsdRootFile(process.cwd(), "KNOWLEDGE");
69
- if (existsSync(knowledgePath)) {
70
- try {
71
- const content = readFileSync(knowledgePath, "utf-8").trim();
72
- if (content) {
73
- knowledgeBlock = `\n\n[PROJECT KNOWLEDGE — Rules, patterns, and lessons learned]\n\n${content}`;
74
- }
75
- } catch {
76
- // skip
77
- }
67
+ const { block: knowledgeBlock, globalSizeKb } = loadKnowledgeBlock(gsdHome, process.cwd());
68
+ if (globalSizeKb > 4) {
69
+ ctx.ui.notify(
70
+ `GSD: ~/.gsd/agent/KNOWLEDGE.md is ${globalSizeKb.toFixed(1)}KB — consider trimming to keep system prompt lean.`,
71
+ "warning",
72
+ );
78
73
  }
79
74
 
80
75
  let memoryBlock = "";
@@ -126,6 +121,48 @@ export async function buildBeforeAgentStartResult(
126
121
  };
127
122
  }
128
123
 
124
+ export function loadKnowledgeBlock(gsdHomeDir: string, cwd: string): { block: string; globalSizeKb: number } {
125
+ // 1. Global knowledge (~/.gsd/agent/KNOWLEDGE.md) — cross-project, user-maintained
126
+ let globalKnowledge = "";
127
+ let globalSizeKb = 0;
128
+ const globalKnowledgePath = join(gsdHomeDir, "agent", "KNOWLEDGE.md");
129
+ if (existsSync(globalKnowledgePath)) {
130
+ try {
131
+ const content = readFileSync(globalKnowledgePath, "utf-8").trim();
132
+ if (content) {
133
+ globalSizeKb = Buffer.byteLength(content, "utf-8") / 1024;
134
+ globalKnowledge = content;
135
+ }
136
+ } catch {
137
+ // skip
138
+ }
139
+ }
140
+
141
+ // 2. Project knowledge (.gsd/KNOWLEDGE.md) — project-specific
142
+ let projectKnowledge = "";
143
+ const knowledgePath = resolveGsdRootFile(cwd, "KNOWLEDGE");
144
+ if (existsSync(knowledgePath)) {
145
+ try {
146
+ const content = readFileSync(knowledgePath, "utf-8").trim();
147
+ if (content) projectKnowledge = content;
148
+ } catch {
149
+ // skip
150
+ }
151
+ }
152
+
153
+ if (!globalKnowledge && !projectKnowledge) {
154
+ return { block: "", globalSizeKb: 0 };
155
+ }
156
+
157
+ const parts: string[] = [];
158
+ if (globalKnowledge) parts.push(`## Global Knowledge\n\n${globalKnowledge}`);
159
+ if (projectKnowledge) parts.push(`## Project Knowledge\n\n${projectKnowledge}`);
160
+ return {
161
+ block: `\n\n[KNOWLEDGE — Rules, patterns, and lessons learned]\n\n${parts.join("\n\n")}`,
162
+ globalSizeKb,
163
+ };
164
+ }
165
+
129
166
  function buildWorktreeContextBlock(): string {
130
167
  const worktreeName = getActiveWorktreeName();
131
168
  const worktreeMainCwd = getWorktreeOriginalCwd();
@@ -15,7 +15,7 @@ export interface GsdCommandDefinition {
15
15
  type CompletionMap = Record<string, readonly GsdCommandDefinition[]>;
16
16
 
17
17
  export const GSD_COMMAND_DESCRIPTION =
18
- "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|park|unpark|init|setup|inspect|extensions|update|fast";
18
+ "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|park|unpark|init|setup|inspect|extensions|update|fast|mcp|rethink";
19
19
 
20
20
  export const TOP_LEVEL_SUBCOMMANDS: readonly GsdCommandDefinition[] = [
21
21
  { cmd: "help", desc: "Categorized command reference with descriptions" },
@@ -68,6 +68,8 @@ export const TOP_LEVEL_SUBCOMMANDS: readonly GsdCommandDefinition[] = [
68
68
  { cmd: "templates", desc: "List available workflow templates" },
69
69
  { cmd: "extensions", desc: "Manage extensions (list, enable, disable, info)" },
70
70
  { cmd: "fast", desc: "Toggle OpenAI service tier (on/off/flex/status)" },
71
+ { cmd: "mcp", desc: "MCP server status and connectivity check (status, check <server>)" },
72
+ { cmd: "rethink", desc: "Conversational project reorganization — reorder, park, discard, add milestones" },
71
73
  { cmd: "workflow", desc: "Custom workflow lifecycle (new, run, list, validate, pause, resume)" },
72
74
  ];
73
75
 
@@ -187,6 +189,10 @@ const NESTED_COMPLETIONS: CompletionMap = {
187
189
  { cmd: "flex", desc: "Flex tier (0.5x cost, slower)" },
188
190
  { cmd: "status", desc: "Show current service tier setting" },
189
191
  ],
192
+ mcp: [
193
+ { cmd: "status", desc: "Show all MCP server statuses (default)" },
194
+ { cmd: "check", desc: "Detailed status for a specific server" },
195
+ ],
190
196
  doctor: [
191
197
  { cmd: "fix", desc: "Auto-fix detected issues" },
192
198
  { cmd: "heal", desc: "AI-driven deep healing" },
@@ -36,6 +36,7 @@ export function showHelp(ctx: ExtensionCommandContext): void {
36
36
  " /gsd triage Classify and route pending captures",
37
37
  " /gsd skip <unit> Prevent a unit from auto-mode dispatch",
38
38
  " /gsd undo Revert last completed unit [--force]",
39
+ " /gsd rethink Conversational project reorganization — reorder, park, discard, add milestones",
39
40
  " /gsd park [id] Park a milestone — skip without deleting [reason]",
40
41
  " /gsd unpark [id] Reactivate a parked milestone",
41
42
  "",
@@ -53,6 +54,7 @@ export function showHelp(ctx: ExtensionCommandContext): void {
53
54
  " /gsd hooks Show post-unit hook configuration",
54
55
  " /gsd extensions Manage extensions [list|enable|disable|info]",
55
56
  " /gsd fast Toggle OpenAI service tier [on|off|flex|status]",
57
+ " /gsd mcp MCP server status and connectivity [status|check <server>]",
56
58
  "",
57
59
  "MAINTENANCE",
58
60
  " /gsd doctor Diagnose and repair .gsd/ state [audit|fix|heal] [scope]",
@@ -191,10 +191,20 @@ Examples:
191
191
  await handleFast(trimmed.replace(/^fast\s*/, "").trim(), ctx);
192
192
  return true;
193
193
  }
194
+ if (trimmed === "mcp" || trimmed.startsWith("mcp ")) {
195
+ const { handleMcpStatus } = await import("../../commands-mcp-status.js");
196
+ await handleMcpStatus(trimmed.replace(/^mcp\s*/, "").trim(), ctx);
197
+ return true;
198
+ }
194
199
  if (trimmed === "extensions" || trimmed.startsWith("extensions ")) {
195
200
  const { handleExtensions } = await import("../../commands-extensions.js");
196
201
  await handleExtensions(trimmed.replace(/^extensions\s*/, "").trim(), ctx);
197
202
  return true;
198
203
  }
204
+ if (trimmed === "rethink") {
205
+ const { handleRethink } = await import("../../rethink.js");
206
+ await handleRethink(trimmed, ctx, pi);
207
+ return true;
208
+ }
199
209
  return false;
200
210
  }
@@ -188,6 +188,14 @@ export async function handleWorkflowCommand(trimmed: string, ctx: ExtensionComma
188
188
  return true;
189
189
  }
190
190
  if (trimmed === "quick" || trimmed.startsWith("quick ")) {
191
+ if (isAutoActive()) {
192
+ ctx.ui.notify(
193
+ "/gsd quick cannot run while auto-mode is active.\n" +
194
+ "Stop auto-mode first with /gsd stop, then run /gsd quick.",
195
+ "error",
196
+ );
197
+ return true;
198
+ }
191
199
  await handleQuick(trimmed.replace(/^quick\s*/, "").trim(), ctx, pi);
192
200
  return true;
193
201
  }
@@ -0,0 +1,247 @@
1
+ /**
2
+ * MCP Status — `/gsd mcp` command handler.
3
+ *
4
+ * Shows configured MCP servers, their connection status, and available tools.
5
+ *
6
+ * Subcommands:
7
+ * /gsd mcp — Overview of all servers (alias: /gsd mcp status)
8
+ * /gsd mcp status — Same as bare /gsd mcp
9
+ * /gsd mcp check <srv> — Detailed status for a specific server
10
+ */
11
+
12
+ import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
13
+
14
+ import { existsSync, readFileSync } from "node:fs";
15
+ import { join } from "node:path";
16
+
17
+ // ─── Types ──────────────────────────────────────────────────────────────────
18
+
19
+ export interface McpServerStatus {
20
+ name: string;
21
+ transport: "stdio" | "http" | "unknown";
22
+ connected: boolean;
23
+ toolCount: number;
24
+ error: string | undefined;
25
+ }
26
+
27
+ export interface McpServerDetail extends McpServerStatus {
28
+ tools: string[];
29
+ }
30
+
31
+ // ─── Config reader (standalone — does not import mcp-client internals) ──────
32
+
33
+ interface McpServerRawConfig {
34
+ name: string;
35
+ transport: "stdio" | "http" | "unknown";
36
+ command?: string;
37
+ args?: string[];
38
+ url?: string;
39
+ }
40
+
41
+ function readMcpConfigs(): McpServerRawConfig[] {
42
+ const servers: McpServerRawConfig[] = [];
43
+ const seen = new Set<string>();
44
+ const configPaths = [
45
+ join(process.cwd(), ".mcp.json"),
46
+ join(process.cwd(), ".gsd", "mcp.json"),
47
+ ];
48
+
49
+ for (const configPath of configPaths) {
50
+ try {
51
+ if (!existsSync(configPath)) continue;
52
+ const raw = readFileSync(configPath, "utf-8");
53
+ const data = JSON.parse(raw) as Record<string, unknown>;
54
+ const mcpServers = (data.mcpServers ?? data.servers) as
55
+ | Record<string, Record<string, unknown>>
56
+ | undefined;
57
+ if (!mcpServers || typeof mcpServers !== "object") continue;
58
+
59
+ for (const [name, config] of Object.entries(mcpServers)) {
60
+ if (seen.has(name)) continue;
61
+ seen.add(name);
62
+
63
+ const hasCommand = typeof config.command === "string";
64
+ const hasUrl = typeof config.url === "string";
65
+ const transport: McpServerRawConfig["transport"] = hasCommand
66
+ ? "stdio"
67
+ : hasUrl
68
+ ? "http"
69
+ : "unknown";
70
+
71
+ servers.push({
72
+ name,
73
+ transport,
74
+ ...(hasCommand && {
75
+ command: config.command as string,
76
+ args: Array.isArray(config.args) ? (config.args as string[]) : undefined,
77
+ }),
78
+ ...(hasUrl && { url: config.url as string }),
79
+ });
80
+ }
81
+ } catch {
82
+ // Non-fatal — config file may not exist or be malformed
83
+ }
84
+ }
85
+
86
+ return servers;
87
+ }
88
+
89
+ // ─── Formatters (exported for testing) ──────────────────────────────────────
90
+
91
+ export function formatMcpStatusReport(servers: McpServerStatus[]): string {
92
+ if (servers.length === 0) {
93
+ return [
94
+ "No MCP servers configured.",
95
+ "",
96
+ "Add servers to .mcp.json or .gsd/mcp.json to enable MCP integrations.",
97
+ "See: https://modelcontextprotocol.io/quickstart",
98
+ ].join("\n");
99
+ }
100
+
101
+ const lines: string[] = [`MCP Server Status — ${servers.length} server(s)\n`];
102
+
103
+ for (const s of servers) {
104
+ const icon = s.error ? "✗" : s.connected ? "✓" : "○";
105
+ const status = s.error
106
+ ? `error: ${s.error}`
107
+ : s.connected
108
+ ? `connected — ${s.toolCount} tools`
109
+ : "disconnected";
110
+ lines.push(` ${icon} ${s.name} (${s.transport}) — ${status}`);
111
+ }
112
+
113
+ lines.push("");
114
+ lines.push("Use /gsd mcp check <server> for details on a specific server.");
115
+ lines.push("Use mcp_discover to connect and list tools for a server.");
116
+
117
+ return lines.join("\n");
118
+ }
119
+
120
+ export function formatMcpServerDetail(server: McpServerDetail): string {
121
+ const lines: string[] = [`MCP Server: ${server.name}\n`];
122
+
123
+ lines.push(` Transport: ${server.transport}`);
124
+
125
+ if (server.error) {
126
+ lines.push(` Status: error`);
127
+ lines.push(` Error: ${server.error}`);
128
+ } else if (server.connected) {
129
+ lines.push(` Status: connected`);
130
+ lines.push(` Tools: ${server.toolCount}`);
131
+ if (server.tools.length > 0) {
132
+ lines.push("");
133
+ lines.push(" Available tools:");
134
+ for (const tool of server.tools) {
135
+ lines.push(` - ${tool}`);
136
+ }
137
+ }
138
+ } else {
139
+ lines.push(` Status: disconnected`);
140
+ lines.push("");
141
+ lines.push(` Run mcp_discover("${server.name}") to connect and list tools.`);
142
+ }
143
+
144
+ return lines.join("\n");
145
+ }
146
+
147
+ // ─── Command handler ────────────────────────────────────────────────────────
148
+
149
+ /**
150
+ * Handle `/gsd mcp [status|check <server>]`.
151
+ */
152
+ export async function handleMcpStatus(
153
+ args: string,
154
+ ctx: ExtensionCommandContext,
155
+ ): Promise<void> {
156
+ const trimmed = args.trim().toLowerCase();
157
+ const configs = readMcpConfigs();
158
+
159
+ // /gsd mcp check <server>
160
+ if (trimmed.startsWith("check ")) {
161
+ const serverName = args.trim().slice("check ".length).trim();
162
+ const config = configs.find((c) => c.name === serverName);
163
+ if (!config) {
164
+ const available = configs.map((c) => c.name).join(", ") || "(none)";
165
+ ctx.ui.notify(
166
+ `Unknown MCP server: "${serverName}"\n\nAvailable: ${available}`,
167
+ "warning",
168
+ );
169
+ return;
170
+ }
171
+
172
+ // Try to get connection/tool info from the mcp-client module if available
173
+ let connected = false;
174
+ let toolNames: string[] = [];
175
+ let error: string | undefined;
176
+ try {
177
+ const mcpClient = await import("../mcp-client/index.js");
178
+ // Access the module's connection state if exported; fall back gracefully
179
+ const mod = mcpClient as Record<string, unknown>;
180
+ if (typeof mod.getConnectionStatus === "function") {
181
+ const status = (mod.getConnectionStatus as (name: string) => { connected: boolean; tools: string[]; error?: string })(serverName);
182
+ connected = status.connected;
183
+ toolNames = status.tools;
184
+ error = status.error;
185
+ }
186
+ } catch {
187
+ // mcp-client may not expose status helpers — that's fine
188
+ }
189
+
190
+ ctx.ui.notify(
191
+ formatMcpServerDetail({
192
+ name: config.name,
193
+ transport: config.transport,
194
+ connected,
195
+ toolCount: toolNames.length,
196
+ tools: toolNames,
197
+ error,
198
+ }),
199
+ "info",
200
+ );
201
+ return;
202
+ }
203
+
204
+ // /gsd mcp or /gsd mcp status
205
+ if (!trimmed || trimmed === "status") {
206
+ // Build status for each server
207
+ const statuses: McpServerStatus[] = [];
208
+
209
+ for (const config of configs) {
210
+ let connected = false;
211
+ let toolCount = 0;
212
+ let error: string | undefined;
213
+
214
+ try {
215
+ const mcpClient = await import("../mcp-client/index.js");
216
+ const mod = mcpClient as Record<string, unknown>;
217
+ if (typeof mod.getConnectionStatus === "function") {
218
+ const status = (mod.getConnectionStatus as (name: string) => { connected: boolean; tools: string[]; error?: string })(config.name);
219
+ connected = status.connected;
220
+ toolCount = status.tools.length;
221
+ error = status.error;
222
+ }
223
+ } catch {
224
+ // Fall back to unknown state
225
+ }
226
+
227
+ statuses.push({
228
+ name: config.name,
229
+ transport: config.transport,
230
+ connected,
231
+ toolCount,
232
+ error,
233
+ });
234
+ }
235
+
236
+ ctx.ui.notify(formatMcpStatusReport(statuses), "info");
237
+ return;
238
+ }
239
+
240
+ // Unknown subcommand
241
+ ctx.ui.notify(
242
+ "Usage: /gsd mcp [status|check <server>]\n\n" +
243
+ " status Show all MCP server statuses (default)\n" +
244
+ " check <server> Detailed status for a specific server",
245
+ "warning",
246
+ );
247
+ }