gsd-pi 2.43.0-next.8 → 2.44.0-dev.0b97ffd

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 (399) hide show
  1. package/README.md +30 -12
  2. package/dist/cli.js +13 -1
  3. package/dist/help-text.js +24 -0
  4. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +21 -8
  5. package/dist/resources/extensions/gsd/auto-prompts.js +130 -51
  6. package/dist/resources/extensions/gsd/auto-start.js +10 -0
  7. package/dist/resources/extensions/gsd/auto-worktree.js +16 -2
  8. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  9. package/dist/resources/extensions/gsd/dispatch-guard.js +34 -10
  10. package/dist/resources/extensions/gsd/markdown-renderer.js +7 -5
  11. package/dist/resources/extensions/gsd/reactive-graph.js +13 -2
  12. package/dist/resources/extensions/gsd/skill-health.js +3 -1
  13. package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -11
  14. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -10
  15. package/dist/resources/extensions/gsd/visualizer-data.js +45 -13
  16. package/dist/resources/extensions/gsd/workspace-index.js +46 -15
  17. package/dist/web/standalone/.next/BUILD_ID +1 -1
  18. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
  19. package/dist/web/standalone/.next/build-manifest.json +3 -3
  20. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  21. package/dist/web/standalone/.next/required-server-files.json +4 -4
  22. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  23. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  25. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  33. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  34. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  35. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  37. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  39. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  49. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  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.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  93. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  109. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  111. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  113. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/index.html +1 -1
  123. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  124. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  125. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  126. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  128. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/page.js +2 -2
  130. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
  132. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  133. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  134. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/middleware.js +2 -2
  136. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  138. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  139. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  140. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  141. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  142. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  143. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  144. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  145. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  146. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  147. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  148. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  149. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  150. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  151. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  152. package/dist/web/standalone/server.js +1 -1
  153. package/package.json +4 -4
  154. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +3 -3
  155. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -34
  157. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  159. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
  161. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  162. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
  164. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
  167. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  168. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  169. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  170. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  171. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  172. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  173. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  174. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  175. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  176. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
  177. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  178. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
  180. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
  181. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
  183. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  185. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
  187. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
  188. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
  189. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
  190. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
  191. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
  192. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
  193. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
  194. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
  195. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  197. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
  199. package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
  201. package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
  202. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
  203. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
  204. package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
  205. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
  206. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  207. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  209. package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
  210. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  211. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  212. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  213. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  214. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/index.d.ts +3 -1
  216. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  217. package/packages/pi-coding-agent/dist/index.js +1 -0
  218. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  220. package/packages/pi-coding-agent/dist/main.js +11 -199
  221. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  222. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  223. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  224. package/packages/pi-coding-agent/package.json +1 -1
  225. package/packages/pi-coding-agent/src/core/agent-session.ts +13 -37
  226. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  227. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
  228. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
  229. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
  230. package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
  231. package/packages/pi-coding-agent/src/core/extensions/loader.ts +23 -0
  232. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  233. package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
  234. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
  235. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
  236. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  237. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
  238. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
  239. package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
  240. package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
  241. package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
  242. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  243. package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
  244. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  245. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  246. package/packages/pi-coding-agent/src/index.ts +7 -0
  247. package/packages/pi-coding-agent/src/main.ts +11 -232
  248. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  249. package/pkg/package.json +1 -1
  250. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +22 -7
  251. package/src/resources/extensions/gsd/auto-prompts.ts +109 -42
  252. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  253. package/src/resources/extensions/gsd/auto-worktree.ts +16 -3
  254. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  255. package/src/resources/extensions/gsd/dispatch-guard.ts +28 -10
  256. package/src/resources/extensions/gsd/markdown-renderer.ts +7 -5
  257. package/src/resources/extensions/gsd/reactive-graph.ts +12 -2
  258. package/src/resources/extensions/gsd/skill-health.ts +2 -1
  259. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  260. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  261. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  262. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  263. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  264. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  265. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  266. package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +3 -3
  267. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  268. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  269. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  270. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  271. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  272. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  273. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  274. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  275. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  276. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  277. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  278. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  279. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  280. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  281. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  282. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  283. package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
  284. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  285. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  286. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +152 -183
  287. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  288. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  289. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  290. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  291. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  292. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  293. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  294. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  295. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  296. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  297. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  298. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  299. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  300. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  301. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  302. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  303. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  304. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  305. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  306. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  307. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  308. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  309. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  310. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  311. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  312. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  313. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  314. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  315. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  316. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  317. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  318. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  319. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  320. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  321. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  322. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  323. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  324. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  325. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  326. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  327. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  328. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  329. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  330. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  331. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  332. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  333. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  334. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  335. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  336. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  337. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  338. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  339. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  340. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  341. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  342. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  343. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  344. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  345. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  346. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  347. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  348. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  349. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  350. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  351. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  352. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  353. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  354. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  355. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  356. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  357. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  358. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  359. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  360. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  361. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  362. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  363. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  364. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  365. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  366. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  367. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  368. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  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 +9 -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-symlink-removal.test.ts +15 -22
  388. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  389. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  390. package/src/resources/extensions/gsd/tools/plan-milestone.ts +1 -18
  391. package/src/resources/extensions/gsd/tools/plan-slice.ts +1 -15
  392. package/src/resources/extensions/gsd/visualizer-data.ts +46 -14
  393. package/src/resources/extensions/gsd/workspace-index.ts +49 -18
  394. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  395. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  396. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  397. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  398. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_buildManifest.js +0 -0
  399. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
@@ -1,11 +1,10 @@
1
+ import { after, describe, test } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync, existsSync } from "node:fs";
2
4
  import { join } from "node:path";
3
5
  import { tmpdir } from "node:os";
4
6
 
5
7
  import { formatDoctorReport, runGSDDoctor, summarizeDoctorIssues, filterDoctorIssues, selectDoctorScope, validateTitle } from "../doctor.js";
6
- import { createTestContext } from './test-helpers.ts';
7
-
8
- const { assertEq, assertTrue, report } = createTestContext();
9
8
  const tmpBase = mkdtempSync(join(tmpdir(), "gsd-doctor-test-"));
10
9
  const gsd = join(tmpBase, ".gsd");
11
10
  const mDir = join(gsd, "milestones", "M001");
@@ -61,46 +60,41 @@ Implemented.
61
60
  - log
62
61
  `);
63
62
 
64
- async function main(): Promise<void> {
65
- console.log("\n=== doctor diagnose ===");
66
- {
63
+ describe('doctor', async () => {
64
+ test('doctor diagnose', async () => {
67
65
  const report = await runGSDDoctor(tmpBase, { fix: false });
68
66
  // Reconciliation issue codes have been removed — doctor should NOT report them
69
- assertTrue(!report.issues.some(issue => issue.code === "all_tasks_done_missing_slice_summary" as any), "does not report removed code all_tasks_done_missing_slice_summary");
70
- assertTrue(!report.issues.some(issue => issue.code === "all_tasks_done_missing_slice_uat" as any), "does not report removed code all_tasks_done_missing_slice_uat");
71
- assertTrue(!report.issues.some(issue => issue.code === "all_tasks_done_roadmap_not_checked" as any), "does not report removed code all_tasks_done_roadmap_not_checked");
72
- }
67
+ assert.ok(!report.issues.some(issue => issue.code === "all_tasks_done_missing_slice_summary" as any), "does not report removed code all_tasks_done_missing_slice_summary");
68
+ assert.ok(!report.issues.some(issue => issue.code === "all_tasks_done_missing_slice_uat" as any), "does not report removed code all_tasks_done_missing_slice_uat");
69
+ assert.ok(!report.issues.some(issue => issue.code === "all_tasks_done_roadmap_not_checked" as any), "does not report removed code all_tasks_done_roadmap_not_checked");
70
+ });
73
71
 
74
- console.log("\n=== doctor formatting ===");
75
- {
72
+ test('doctor formatting', async () => {
76
73
  const report = await runGSDDoctor(tmpBase, { fix: false });
77
74
  const summary = summarizeDoctorIssues(report.issues);
78
75
  const scoped = filterDoctorIssues(report.issues, { scope: "M001/S01", includeWarnings: true });
79
76
  const text = formatDoctorReport(report, { scope: "M001/S01", includeWarnings: true, maxIssues: 5 });
80
- assertTrue(text.includes("Scope: M001/S01"), "formatted report shows scope");
81
- }
77
+ assert.ok(text.includes("Scope: M001/S01"), "formatted report shows scope");
78
+ });
82
79
 
83
- console.log("\n=== doctor default scope ===");
84
- {
80
+ test('doctor default scope', async () => {
85
81
  const scope = await selectDoctorScope(tmpBase);
86
- assertEq(scope, "M001/S01", "default doctor scope targets the active slice");
87
- }
82
+ assert.deepStrictEqual(scope, "M001/S01", "default doctor scope targets the active slice");
83
+ });
88
84
 
89
- console.log("\n=== doctor fix ===");
90
- {
85
+ test('doctor fix', async () => {
91
86
  const report = await runGSDDoctor(tmpBase, { fix: true });
92
87
  // With reconciliation removed, doctor no longer creates placeholder summaries,
93
88
  // UAT files, or marks checkboxes. It only applies infrastructure fixes.
94
89
  // The task checkbox marking (task_summary_without_done_checkbox) is also removed.
95
90
  // Just verify it doesn't crash and produces a report.
96
- assertTrue(report.issues !== undefined, "doctor produces a report with issues array");
97
- }
91
+ assert.ok(report.issues !== undefined, "doctor produces a report with issues array");
92
+ });
98
93
 
99
- rmSync(tmpBase, { recursive: true, force: true });
94
+ after(() => rmSync(tmpBase, { recursive: true, force: true }));
100
95
 
101
96
  // ─── Milestone summary detection: missing summary ──────────────────────
102
- console.log("\n=== doctor detects missing milestone summary ===");
103
- {
97
+ test('doctor detects missing milestone summary', async () => {
104
98
  const msBase = mkdtempSync(join(tmpdir(), "gsd-doctor-ms-test-"));
105
99
  const msGsd = join(msBase, ".gsd");
106
100
  const msMDir = join(msGsd, "milestones", "M001");
@@ -153,22 +147,21 @@ parent: M001
153
147
  // NO milestone summary — this is the condition we're detecting
154
148
 
155
149
  const report = await runGSDDoctor(msBase, { fix: false });
156
- assertTrue(
150
+ assert.ok(
157
151
  report.issues.some(issue => issue.code === "all_slices_done_missing_milestone_summary"),
158
152
  "detects missing milestone summary when all slices are done"
159
153
  );
160
154
  const msIssue = report.issues.find(issue => issue.code === "all_slices_done_missing_milestone_summary");
161
- assertEq(msIssue?.scope, "milestone", "milestone summary issue has scope 'milestone'");
162
- assertEq(msIssue?.severity, "warning", "milestone summary issue has severity 'warning'");
163
- assertEq(msIssue?.unitId, "M001", "milestone summary issue unitId is 'M001'");
164
- assertTrue(msIssue?.message?.includes("SUMMARY") ?? false, "milestone summary issue message mentions SUMMARY");
155
+ assert.deepStrictEqual(msIssue?.scope, "milestone", "milestone summary issue has scope 'milestone'");
156
+ assert.deepStrictEqual(msIssue?.severity, "warning", "milestone summary issue has severity 'warning'");
157
+ assert.deepStrictEqual(msIssue?.unitId, "M001", "milestone summary issue unitId is 'M001'");
158
+ assert.ok(msIssue?.message?.includes("SUMMARY") ?? false, "milestone summary issue message mentions SUMMARY");
165
159
 
166
160
  rmSync(msBase, { recursive: true, force: true });
167
- }
161
+ });
168
162
 
169
163
  // ─── Milestone summary detection: summary present (no false positive) ──
170
- console.log("\n=== doctor does NOT flag milestone with summary ===");
171
- {
164
+ test('doctor does NOT flag milestone with summary', async () => {
172
165
  const msBase = mkdtempSync(join(tmpdir(), "gsd-doctor-ms-ok-test-"));
173
166
  const msGsd = join(msBase, ".gsd");
174
167
  const msMDir = join(msGsd, "milestones", "M001");
@@ -218,17 +211,16 @@ parent: M001
218
211
  writeFileSync(join(msMDir, "M001-SUMMARY.md"), `# M001 Summary\n\nMilestone complete.`);
219
212
 
220
213
  const report = await runGSDDoctor(msBase, { fix: false });
221
- assertTrue(
214
+ assert.ok(
222
215
  !report.issues.some(issue => issue.code === "all_slices_done_missing_milestone_summary"),
223
216
  "does NOT report missing milestone summary when summary exists"
224
217
  );
225
218
 
226
219
  rmSync(msBase, { recursive: true, force: true });
227
- }
220
+ });
228
221
 
229
222
  // ─── blocker_discovered_no_replan detection ────────────────────────────
230
- console.log("\n=== doctor detects blocker_discovered_no_replan ===");
231
- {
223
+ test('doctor detects blocker_discovered_no_replan', async () => {
232
224
  const bBase = mkdtempSync(join(tmpdir(), "gsd-doctor-blocker-test-"));
233
225
  const bGsd = join(bBase, ".gsd");
234
226
  const bMDir = join(bGsd, "milestones", "M001");
@@ -284,18 +276,17 @@ Discovered an issue.
284
276
  // No REPLAN.md — should trigger the issue
285
277
  const report = await runGSDDoctor(bBase, { fix: false });
286
278
  const blockerIssues = report.issues.filter(i => i.code === "blocker_discovered_no_replan");
287
- assertTrue(blockerIssues.length > 0, "detects blocker_discovered_no_replan");
288
- assertEq(blockerIssues[0]?.severity, "warning", "blocker issue has warning severity");
289
- assertEq(blockerIssues[0]?.scope, "slice", "blocker issue has slice scope");
290
- assertTrue(blockerIssues[0]?.message?.includes("T01") ?? false, "blocker issue message mentions T01");
291
- assertTrue(blockerIssues[0]?.message?.includes("S01") ?? false, "blocker issue message mentions S01");
279
+ assert.ok(blockerIssues.length > 0, "detects blocker_discovered_no_replan");
280
+ assert.deepStrictEqual(blockerIssues[0]?.severity, "warning", "blocker issue has warning severity");
281
+ assert.deepStrictEqual(blockerIssues[0]?.scope, "slice", "blocker issue has slice scope");
282
+ assert.ok(blockerIssues[0]?.message?.includes("T01") ?? false, "blocker issue message mentions T01");
283
+ assert.ok(blockerIssues[0]?.message?.includes("S01") ?? false, "blocker issue message mentions S01");
292
284
 
293
285
  rmSync(bBase, { recursive: true, force: true });
294
- }
286
+ });
295
287
 
296
288
  // ─── blocker_discovered with REPLAN.md (no false positive) ─────────────
297
- console.log("\n=== doctor does NOT flag blocker when REPLAN.md exists ===");
298
- {
289
+ test('doctor does NOT flag blocker when REPLAN.md exists', async () => {
299
290
  const bBase = mkdtempSync(join(tmpdir(), "gsd-doctor-blocker-ok-test-"));
300
291
  const bGsd = join(bBase, ".gsd");
301
292
  const bMDir = join(bGsd, "milestones", "M001");
@@ -345,14 +336,13 @@ Discovered an issue.
345
336
 
346
337
  const report = await runGSDDoctor(bBase, { fix: false });
347
338
  const blockerIssues = report.issues.filter(i => i.code === "blocker_discovered_no_replan");
348
- assertEq(blockerIssues.length, 0, "no blocker_discovered_no_replan when REPLAN.md exists");
339
+ assert.deepStrictEqual(blockerIssues.length, 0, "no blocker_discovered_no_replan when REPLAN.md exists");
349
340
 
350
341
  rmSync(bBase, { recursive: true, force: true });
351
- }
342
+ });
352
343
 
353
344
  // ─── Must-have verification: all addressed → no issue ─────────────────
354
- console.log("\n=== doctor: done task with must-haves all addressed → no issue ===");
355
- {
345
+ test('doctor: done task with must-haves all addressed → no issue', async () => {
356
346
  const mhBase = mkdtempSync(join(tmpdir(), "gsd-doctor-mh-ok-"));
357
347
  const mhGsd = join(mhBase, ".gsd");
358
348
  const mhMDir = join(mhGsd, "milestones", "M001");
@@ -370,17 +360,16 @@ Discovered an issue.
370
360
  writeFileSync(join(mhTDir, "T01-SUMMARY.md"), `---\nid: T01\nparent: S01\nmilestone: M001\n---\n# T01: Implement\n\n## What Happened\nAdded parseWidgets function. Unit tests pass with zero failures.\n`);
371
361
 
372
362
  const report = await runGSDDoctor(mhBase, { fix: false });
373
- assertTrue(
363
+ assert.ok(
374
364
  !report.issues.some(i => i.code === "task_done_must_haves_not_verified"),
375
365
  "no must-have issue when all must-haves are addressed"
376
366
  );
377
367
 
378
368
  rmSync(mhBase, { recursive: true, force: true });
379
- }
369
+ });
380
370
 
381
371
  // ─── Must-have verification: not addressed → warning fired ───────────
382
- console.log("\n=== doctor: done task with must-haves NOT addressed → warning ===");
383
- {
372
+ test('doctor: done task with must-haves NOT addressed → warning', async () => {
384
373
  const mhBase = mkdtempSync(join(tmpdir(), "gsd-doctor-mh-fail-"));
385
374
  const mhGsd = join(mhBase, ".gsd");
386
375
  const mhMDir = join(mhGsd, "milestones", "M001");
@@ -399,19 +388,18 @@ Discovered an issue.
399
388
 
400
389
  const report = await runGSDDoctor(mhBase, { fix: false });
401
390
  const mhIssue = report.issues.find(i => i.code === "task_done_must_haves_not_verified");
402
- assertTrue(!!mhIssue, "must-have issue is fired when summary doesn't address all must-haves");
403
- assertEq(mhIssue?.severity, "warning", "must-have issue is warning severity");
404
- assertEq(mhIssue?.scope, "task", "must-have issue scope is task");
405
- assertTrue(mhIssue?.message?.includes("3 must-haves") ?? false, "message mentions total must-have count");
406
- assertTrue(mhIssue?.message?.includes("only 1") ?? false, "message mentions addressed count");
407
- assertEq(mhIssue?.fixable, false, "must-have issue is not fixable");
391
+ assert.ok(!!mhIssue, "must-have issue is fired when summary doesn't address all must-haves");
392
+ assert.deepStrictEqual(mhIssue?.severity, "warning", "must-have issue is warning severity");
393
+ assert.deepStrictEqual(mhIssue?.scope, "task", "must-have issue scope is task");
394
+ assert.ok(mhIssue?.message?.includes("3 must-haves") ?? false, "message mentions total must-have count");
395
+ assert.ok(mhIssue?.message?.includes("only 1") ?? false, "message mentions addressed count");
396
+ assert.deepStrictEqual(mhIssue?.fixable, false, "must-have issue is not fixable");
408
397
 
409
398
  rmSync(mhBase, { recursive: true, force: true });
410
- }
399
+ });
411
400
 
412
401
  // ─── Must-have verification: no task plan → no issue ─────────────────
413
- console.log("\n=== doctor: done task with no task plan file → no issue ===");
414
- {
402
+ test('doctor: done task with no task plan file → no issue', async () => {
415
403
  const mhBase = mkdtempSync(join(tmpdir(), "gsd-doctor-mh-noplan-"));
416
404
  const mhGsd = join(mhBase, ".gsd");
417
405
  const mhMDir = join(mhGsd, "milestones", "M001");
@@ -426,17 +414,16 @@ Discovered an issue.
426
414
  writeFileSync(join(mhTDir, "T01-SUMMARY.md"), `---\nid: T01\nparent: S01\nmilestone: M001\n---\n# T01: Implement\n\n## What Happened\nDone.\n`);
427
415
 
428
416
  const report = await runGSDDoctor(mhBase, { fix: false });
429
- assertTrue(
417
+ assert.ok(
430
418
  !report.issues.some(i => i.code === "task_done_must_haves_not_verified"),
431
419
  "no must-have issue when task plan file doesn't exist"
432
420
  );
433
421
 
434
422
  rmSync(mhBase, { recursive: true, force: true });
435
- }
423
+ });
436
424
 
437
425
  // ─── Must-have verification: plan exists but no Must-Haves section → no issue
438
- console.log("\n=== doctor: done task with plan but no Must-Haves section → no issue ===");
439
- {
426
+ test('doctor: done task with plan but no Must-Haves section → no issue', async () => {
440
427
  const mhBase = mkdtempSync(join(tmpdir(), "gsd-doctor-mh-nosect-"));
441
428
  const mhGsd = join(mhBase, ".gsd");
442
429
  const mhMDir = join(mhGsd, "milestones", "M001");
@@ -453,55 +440,49 @@ Discovered an issue.
453
440
  writeFileSync(join(mhTDir, "T01-SUMMARY.md"), `---\nid: T01\nparent: S01\nmilestone: M001\n---\n# T01: Implement\n\n## What Happened\nDone.\n`);
454
441
 
455
442
  const report = await runGSDDoctor(mhBase, { fix: false });
456
- assertTrue(
443
+ assert.ok(
457
444
  !report.issues.some(i => i.code === "task_done_must_haves_not_verified"),
458
445
  "no must-have issue when task plan has no Must-Haves section"
459
446
  );
460
447
 
461
448
  rmSync(mhBase, { recursive: true, force: true });
462
- }
449
+ });
463
450
 
464
451
  // ─── validateTitle: em dash and slash detection ────────────────────────
465
- console.log("\n=== validateTitle: returns null for clean titles ===");
466
- {
467
- assertEq(validateTitle("Foundation"), null, "clean title passes");
468
- assertEq(validateTitle("Build Core Systems"), null, "clean title with spaces passes");
469
- assertEq(validateTitle("API v2 Integration"), null, "clean title with version passes");
470
- assertEq(validateTitle(""), null, "empty title passes");
471
- }
472
-
473
- console.log("\n=== validateTitle: detects em dash ===");
474
- {
452
+ test('validateTitle: returns null for clean titles', () => {
453
+ assert.deepStrictEqual(validateTitle("Foundation"), null, "clean title passes");
454
+ assert.deepStrictEqual(validateTitle("Build Core Systems"), null, "clean title with spaces passes");
455
+ assert.deepStrictEqual(validateTitle("API v2 Integration"), null, "clean title with version passes");
456
+ assert.deepStrictEqual(validateTitle(""), null, "empty title passes");
457
+ });
458
+
459
+ test('validateTitle: detects em dash', () => {
475
460
  const result = validateTitle("Foundation — Build Core");
476
- assertTrue(result !== null, "detects em dash in title");
477
- assertTrue(result!.includes("em/en dash"), "message mentions em/en dash");
478
- }
461
+ assert.ok(result !== null, "detects em dash in title");
462
+ assert.ok(result!.includes("em/en dash"), "message mentions em/en dash");
463
+ });
479
464
 
480
- console.log("\n=== validateTitle: detects en dash ===");
481
- {
465
+ test('validateTitle: detects en dash', () => {
482
466
  const result = validateTitle("Phase 1 – Phase 2");
483
- assertTrue(result !== null, "detects en dash in title");
484
- assertTrue(result!.includes("em/en dash"), "message mentions em/en dash for en dash");
485
- }
467
+ assert.ok(result !== null, "detects en dash in title");
468
+ assert.ok(result!.includes("em/en dash"), "message mentions em/en dash for en dash");
469
+ });
486
470
 
487
- console.log("\n=== validateTitle: detects forward slash ===");
488
- {
471
+ test('validateTitle: detects forward slash', () => {
489
472
  const result = validateTitle("Client/Server");
490
- assertTrue(result !== null, "detects forward slash in title");
491
- assertTrue(result!.includes("forward slash"), "message mentions forward slash");
492
- }
473
+ assert.ok(result !== null, "detects forward slash in title");
474
+ assert.ok(result!.includes("forward slash"), "message mentions forward slash");
475
+ });
493
476
 
494
- console.log("\n=== validateTitle: detects both em dash and slash ===");
495
- {
477
+ test('validateTitle: detects both em dash and slash', () => {
496
478
  const result = validateTitle("Client — Server/API");
497
- assertTrue(result !== null, "detects both delimiters");
498
- assertTrue(result!.includes("em/en dash"), "message mentions em/en dash");
499
- assertTrue(result!.includes("forward slash"), "message mentions forward slash");
500
- }
479
+ assert.ok(result !== null, "detects both delimiters");
480
+ assert.ok(result!.includes("em/en dash"), "message mentions em/en dash");
481
+ assert.ok(result!.includes("forward slash"), "message mentions forward slash");
482
+ });
501
483
 
502
484
  // ─── doctor detects delimiter_in_title for milestone ───────────────────
503
- console.log("\n=== doctor detects em dash in milestone title ===");
504
- {
485
+ test('doctor detects em dash in milestone title', async () => {
505
486
  const dtBase = mkdtempSync(join(tmpdir(), "gsd-doctor-dt-test-"));
506
487
  const dtGsd = join(dtBase, ".gsd");
507
488
  const dtMDir = join(dtGsd, "milestones", "M001");
@@ -516,20 +497,19 @@ Discovered an issue.
516
497
 
517
498
  const report = await runGSDDoctor(dtBase, { fix: false });
518
499
  const dtIssues = report.issues.filter(i => i.code === "delimiter_in_title");
519
- assertTrue(dtIssues.length >= 1, "detects delimiter_in_title for milestone with em dash");
500
+ assert.ok(dtIssues.length >= 1, "detects delimiter_in_title for milestone with em dash");
520
501
  const milestoneIssue = dtIssues.find(i => i.scope === "milestone");
521
- assertTrue(milestoneIssue !== undefined, "delimiter issue has milestone scope");
522
- assertEq(milestoneIssue?.severity, "warning", "delimiter issue has warning severity");
523
- assertEq(milestoneIssue?.unitId, "M001", "delimiter issue unitId is M001");
524
- assertTrue(milestoneIssue?.message?.includes("em/en dash") ?? false, "issue message mentions em/en dash");
525
- assertEq(milestoneIssue?.fixable, true, "delimiter issue is auto-fixable");
502
+ assert.ok(milestoneIssue !== undefined, "delimiter issue has milestone scope");
503
+ assert.deepStrictEqual(milestoneIssue?.severity, "warning", "delimiter issue has warning severity");
504
+ assert.deepStrictEqual(milestoneIssue?.unitId, "M001", "delimiter issue unitId is M001");
505
+ assert.ok(milestoneIssue?.message?.includes("em/en dash") ?? false, "issue message mentions em/en dash");
506
+ assert.deepStrictEqual(milestoneIssue?.fixable, true, "delimiter issue is auto-fixable");
526
507
 
527
508
  rmSync(dtBase, { recursive: true, force: true });
528
- }
509
+ });
529
510
 
530
511
  // ─── doctor detects delimiter_in_title for slice ────────────────────────
531
- console.log("\n=== doctor detects em dash in slice title ===");
532
- {
512
+ test('doctor detects em dash in slice title', async () => {
533
513
  const dtBase = mkdtempSync(join(tmpdir(), "gsd-doctor-dt-slice-"));
534
514
  const dtGsd = join(dtBase, ".gsd");
535
515
  const dtMDir = join(dtGsd, "milestones", "M001");
@@ -544,18 +524,17 @@ Discovered an issue.
544
524
 
545
525
  const report = await runGSDDoctor(dtBase, { fix: false });
546
526
  const dtIssues = report.issues.filter(i => i.code === "delimiter_in_title");
547
- assertTrue(dtIssues.length >= 1, "detects delimiter_in_title for slice with em dash");
527
+ assert.ok(dtIssues.length >= 1, "detects delimiter_in_title for slice with em dash");
548
528
  const sliceIssue = dtIssues.find(i => i.scope === "slice");
549
- assertTrue(sliceIssue !== undefined, "delimiter issue has slice scope");
550
- assertEq(sliceIssue?.severity, "warning", "slice delimiter issue has warning severity");
551
- assertEq(sliceIssue?.unitId, "M001/S01", "slice delimiter issue unitId is M001/S01");
529
+ assert.ok(sliceIssue !== undefined, "delimiter issue has slice scope");
530
+ assert.deepStrictEqual(sliceIssue?.severity, "warning", "slice delimiter issue has warning severity");
531
+ assert.deepStrictEqual(sliceIssue?.unitId, "M001/S01", "slice delimiter issue unitId is M001/S01");
552
532
 
553
533
  rmSync(dtBase, { recursive: true, force: true });
554
- }
534
+ });
555
535
 
556
536
  // ─── doctor does NOT flag clean titles ──────────────────────────────────
557
- console.log("\n=== doctor does NOT flag milestone with clean title ===");
558
- {
537
+ test('doctor does NOT flag milestone with clean title', async () => {
559
538
  const dtBase = mkdtempSync(join(tmpdir(), "gsd-doctor-dt-clean-"));
560
539
  const dtGsd = join(dtBase, ".gsd");
561
540
  const dtMDir = join(dtGsd, "milestones", "M001");
@@ -570,14 +549,13 @@ Discovered an issue.
570
549
 
571
550
  const report = await runGSDDoctor(dtBase, { fix: false });
572
551
  const dtIssues = report.issues.filter(i => i.code === "delimiter_in_title");
573
- assertEq(dtIssues.length, 0, "no delimiter_in_title issues for clean titles");
552
+ assert.deepStrictEqual(dtIssues.length, 0, "no delimiter_in_title issues for clean titles");
574
553
 
575
554
  rmSync(dtBase, { recursive: true, force: true });
576
- }
555
+ });
577
556
 
578
557
  // ─── unresolvable_dependency: range syntax dep warns ─────────────────
579
- console.log("\n=== doctor: unresolvable_dependency warns for leftover range ID ===");
580
- {
558
+ test('doctor: unresolvable_dependency warns for leftover range ID', async () => {
581
559
  // Simulate a roadmap where expandDependencies did NOT expand (pre-fix stored artifact)
582
560
  // by writing a dep that looks like a range but doesn't match any real slice.
583
561
  const base = mkdtempSync(join(tmpdir(), "gsd-doctor-udep-"));
@@ -599,16 +577,15 @@ Discovered an issue.
599
577
 
600
578
  const r = await runGSDDoctor(base, { fix: false });
601
579
  const udepIssues = r.issues.filter(i => i.code === "unresolvable_dependency");
602
- assertTrue(udepIssues.length > 0, "unresolvable_dependency fires for unknown dep S99");
603
- assertEq(udepIssues[0]?.severity, "warning", "severity is warning");
604
- assertTrue(udepIssues[0]?.message.includes("S99"), "message names the bad dep");
580
+ assert.ok(udepIssues.length > 0, "unresolvable_dependency fires for unknown dep S99");
581
+ assert.deepStrictEqual(udepIssues[0]?.severity, "warning", "severity is warning");
582
+ assert.ok(udepIssues[0]?.message.includes("S99"), "message names the bad dep");
605
583
 
606
584
  rmSync(base, { recursive: true, force: true });
607
- }
585
+ });
608
586
 
609
587
  // ─── unresolvable_dependency: valid deps do not warn ─────────────────
610
- console.log("\n=== doctor: no unresolvable_dependency for valid deps ===");
611
- {
588
+ test('doctor: no unresolvable_dependency for valid deps', async () => {
612
589
  const base = mkdtempSync(join(tmpdir(), "gsd-doctor-udep-ok-"));
613
590
  const mDir2 = join(base, ".gsd", "milestones", "M001");
614
591
  const sDir2 = join(mDir2, "slices", "S01");
@@ -628,15 +605,8 @@ Discovered an issue.
628
605
 
629
606
  const r = await runGSDDoctor(base, { fix: false });
630
607
  const udepIssues = r.issues.filter(i => i.code === "unresolvable_dependency");
631
- assertEq(udepIssues.length, 0, "no unresolvable_dependency for valid S01 dep");
608
+ assert.deepStrictEqual(udepIssues.length, 0, "no unresolvable_dependency for valid S01 dep");
632
609
 
633
610
  rmSync(base, { recursive: true, force: true });
634
- }
635
-
636
- report();
637
- }
638
-
639
- main().catch((error) => {
640
- console.error(error);
641
- process.exit(1);
611
+ });
642
612
  });