gsd-pi 2.44.0-dev.848dd4c → 2.44.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 (298) hide show
  1. package/README.md +12 -30
  2. package/dist/resources/extensions/gsd/auto-start.js +0 -10
  3. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +0 -5
  4. package/dist/web/standalone/.next/BUILD_ID +1 -1
  5. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  6. package/dist/web/standalone/.next/build-manifest.json +3 -3
  7. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  8. package/dist/web/standalone/.next/required-server-files.json +3 -3
  9. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  10. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  12. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  13. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  14. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  15. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  16. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  17. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  18. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  19. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  20. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  21. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  23. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  24. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  26. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  30. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  31. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  32. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  33. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  34. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  35. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  36. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  37. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  38. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  39. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  40. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  41. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  42. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  49. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  74. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  80. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  94. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  96. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  98. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  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.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/index.html +1 -1
  110. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  111. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  112. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  113. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  115. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/page.js +2 -2
  117. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  119. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  120. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  121. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/middleware.js +2 -2
  123. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  125. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  126. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  127. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  128. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  129. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  130. package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +1 -0
  131. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  132. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  133. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  134. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  135. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  136. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  137. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  138. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  139. package/dist/web/standalone/server.js +1 -1
  140. package/package.json +1 -1
  141. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +8 -6
  142. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  143. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +26 -24
  144. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  145. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +48 -29
  146. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  147. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +44 -34
  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 +34 -30
  150. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  151. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +12 -10
  152. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  153. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +47 -43
  154. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  155. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  156. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  157. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +43 -31
  158. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +45 -40
  159. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  160. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  161. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  162. package/src/resources/extensions/gsd/auto-start.ts +0 -14
  163. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +0 -8
  164. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  165. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +16 -14
  166. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +57 -43
  167. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +13 -11
  168. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +523 -465
  169. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +75 -73
  170. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +56 -34
  171. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +656 -533
  172. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +143 -165
  173. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +52 -29
  174. package/src/resources/extensions/gsd/tests/captures.test.ts +176 -148
  175. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +33 -32
  176. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +143 -141
  177. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  178. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  179. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +59 -38
  180. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +263 -228
  181. package/src/resources/extensions/gsd/tests/complete-task.test.ts +302 -250
  182. package/src/resources/extensions/gsd/tests/context-store.test.ts +367 -354
  183. package/src/resources/extensions/gsd/tests/continue-here.test.ts +72 -68
  184. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +106 -92
  185. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +35 -27
  186. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +237 -220
  187. package/src/resources/extensions/gsd/tests/db-writer.test.ts +420 -390
  188. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +92 -76
  189. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +83 -68
  190. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +183 -152
  191. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +101 -78
  192. package/src/resources/extensions/gsd/tests/derive-state.test.ts +227 -192
  193. package/src/resources/extensions/gsd/tests/detection.test.ts +278 -232
  194. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +34 -30
  195. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +180 -164
  196. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +49 -43
  197. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +32 -28
  198. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +29 -27
  199. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +38 -34
  200. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +75 -54
  201. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +32 -21
  202. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +97 -72
  203. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +44 -38
  204. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +145 -104
  205. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +106 -84
  206. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +60 -54
  207. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +93 -72
  208. package/src/resources/extensions/gsd/tests/doctor.test.ts +134 -104
  209. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +131 -123
  210. package/src/resources/extensions/gsd/tests/exit-command.test.ts +24 -20
  211. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +57 -48
  212. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +7 -5
  213. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +42 -30
  214. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +206 -198
  215. package/src/resources/extensions/gsd/tests/git-locale.test.ts +27 -13
  216. package/src/resources/extensions/gsd/tests/git-service.test.ts +388 -285
  217. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +39 -31
  218. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +69 -63
  219. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +264 -255
  220. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +119 -108
  221. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +103 -81
  222. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +262 -229
  223. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  224. package/src/resources/extensions/gsd/tests/health-widget.test.ts +37 -29
  225. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +102 -81
  226. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +18 -16
  227. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +46 -41
  228. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +53 -42
  229. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +91 -75
  230. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  231. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +194 -150
  232. package/src/resources/extensions/gsd/tests/md-importer.test.ts +125 -101
  233. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +54 -45
  234. package/src/resources/extensions/gsd/tests/memory-store.test.ts +93 -80
  235. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +66 -57
  236. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +93 -83
  237. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +170 -161
  238. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +141 -125
  239. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +131 -107
  240. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +96 -87
  241. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +164 -125
  242. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +94 -81
  243. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +36 -35
  244. package/src/resources/extensions/gsd/tests/overrides.test.ts +106 -99
  245. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +47 -40
  246. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +28 -25
  247. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +83 -66
  248. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +77 -54
  249. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +115 -68
  250. package/src/resources/extensions/gsd/tests/parsers.test.ts +611 -546
  251. package/src/resources/extensions/gsd/tests/paths.test.ts +87 -72
  252. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +117 -77
  253. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  254. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +119 -93
  255. package/src/resources/extensions/gsd/tests/queue-order.test.ts +82 -70
  256. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +55 -42
  257. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +73 -45
  258. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +38 -28
  259. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +80 -73
  260. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +74 -71
  261. package/src/resources/extensions/gsd/tests/requirements.test.ts +75 -70
  262. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +66 -44
  263. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +181 -114
  264. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +65 -63
  265. package/src/resources/extensions/gsd/tests/run-uat.test.ts +128 -66
  266. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +25 -18
  267. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +44 -37
  268. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +26 -19
  269. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +8 -6
  270. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +28 -22
  271. package/src/resources/extensions/gsd/tests/token-savings.test.ts +56 -54
  272. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +25 -23
  273. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +11 -9
  274. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +82 -66
  275. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +47 -46
  276. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +22 -20
  277. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +86 -84
  278. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +43 -41
  279. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +96 -94
  280. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +13 -11
  281. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +29 -27
  282. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +52 -50
  283. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +13 -10
  284. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +18 -14
  285. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +39 -38
  286. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +21 -17
  287. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +30 -25
  288. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +37 -30
  289. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +22 -15
  290. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +66 -59
  291. package/src/resources/extensions/gsd/tests/worktree.test.ts +50 -44
  292. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +0 -1
  293. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  294. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  295. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +0 -100
  296. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +0 -63
  297. /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 → mgkxN0mGP6gSUmGPEzbk_}/_buildManifest.js +0 -0
  298. /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 → mgkxN0mGP6gSUmGPEzbk_}/_ssgManifest.js +0 -0
@@ -1,5 +1,3 @@
1
- import { describe, test } from 'node:test';
2
- import assert from 'node:assert/strict';
3
1
  /**
4
2
  * doctor-git.test.ts — Integration tests for doctor git health checks.
5
3
  *
@@ -16,6 +14,10 @@ import { tmpdir } from "node:os";
16
14
  import { execSync } from "node:child_process";
17
15
 
18
16
  import { runGSDDoctor } from "../doctor.ts";
17
+ import { createTestContext } from "./test-helpers.ts";
18
+
19
+ const { assertEq, assertTrue, report } = createTestContext();
20
+
19
21
  function run(cmd: string, cwd: string): string {
20
22
  return execSync(cmd, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
21
23
  }
@@ -112,7 +114,7 @@ _None_
112
114
  return dir;
113
115
  }
114
116
 
115
- describe('doctor-git', async () => {
117
+ async function main(): Promise<void> {
116
118
  const cleanups: string[] = [];
117
119
 
118
120
  try {
@@ -122,7 +124,8 @@ describe('doctor-git', async () => {
122
124
  // logic is correct (tested on macOS/Linux) — the test infra doesn't
123
125
  // produce matching paths on Windows CI.
124
126
  if (process.platform !== "win32") {
125
- test('orphaned_auto_worktree', async () => {
127
+ console.log("\n=== orphaned_auto_worktree ===");
128
+ {
126
129
  const dir = createRepoWithCompletedMilestone();
127
130
  cleanups.push(dir);
128
131
 
@@ -132,24 +135,26 @@ describe('doctor-git', async () => {
132
135
 
133
136
  const detect = await runGSDDoctor(dir, { isolationMode: "worktree" });
134
137
  const orphanIssues = detect.issues.filter(i => i.code === "orphaned_auto_worktree");
135
- assert.ok(orphanIssues.length > 0, "detects orphaned worktree");
136
- assert.deepStrictEqual(orphanIssues[0]?.unitId, "M001", "orphaned worktree unitId is M001");
138
+ assertTrue(orphanIssues.length > 0, "detects orphaned worktree");
139
+ assertEq(orphanIssues[0]?.unitId, "M001", "orphaned worktree unitId is M001");
137
140
 
138
141
  const fixed = await runGSDDoctor(dir, { fix: true, isolationMode: "worktree" });
139
- assert.ok(fixed.fixesApplied.some(f => f.includes("removed orphaned worktree")), "fix removes orphaned worktree");
142
+ assertTrue(fixed.fixesApplied.some(f => f.includes("removed orphaned worktree")), "fix removes orphaned worktree");
140
143
 
141
144
  // Verify worktree is gone
142
145
  const wtList = run("git worktree list", dir);
143
- assert.ok(!wtList.includes("milestone/M001"), "worktree no longer listed after fix");
144
- });
146
+ assertTrue(!wtList.includes("milestone/M001"), "worktree no longer listed after fix");
147
+ }
145
148
  } else {
149
+ console.log("\n=== orphaned_auto_worktree (skipped on Windows) ===");
146
150
  }
147
151
 
148
152
  // ─── Test 2: Stale milestone branch detection & fix ────────────────
149
153
  // Skip on Windows: git branch glob matching and path resolution
150
154
  // behave differently in Windows temp dirs.
151
155
  if (process.platform !== "win32") {
152
- test('stale_milestone_branch', async () => {
156
+ console.log("\n=== stale_milestone_branch ===");
157
+ {
153
158
  const dir = createRepoWithCompletedMilestone();
154
159
  cleanups.push(dir);
155
160
 
@@ -158,21 +163,23 @@ describe('doctor-git', async () => {
158
163
 
159
164
  const detect = await runGSDDoctor(dir, { isolationMode: "worktree" });
160
165
  const staleIssues = detect.issues.filter(i => i.code === "stale_milestone_branch");
161
- assert.ok(staleIssues.length > 0, "detects stale milestone branch");
162
- assert.deepStrictEqual(staleIssues[0]?.unitId, "M001", "stale branch unitId is M001");
166
+ assertTrue(staleIssues.length > 0, "detects stale milestone branch");
167
+ assertEq(staleIssues[0]?.unitId, "M001", "stale branch unitId is M001");
163
168
 
164
169
  const fixed = await runGSDDoctor(dir, { fix: true, isolationMode: "worktree" });
165
- assert.ok(fixed.fixesApplied.some(f => f.includes("deleted stale branch")), "fix deletes stale branch");
170
+ assertTrue(fixed.fixesApplied.some(f => f.includes("deleted stale branch")), "fix deletes stale branch");
166
171
 
167
172
  // Verify branch is gone
168
173
  const branches = run("git branch --list milestone/*", dir);
169
- assert.ok(!branches.includes("milestone/M001"), "branch gone after fix");
170
- });
174
+ assertTrue(!branches.includes("milestone/M001"), "branch gone after fix");
175
+ }
171
176
  } else {
177
+ console.log("\n=== stale_milestone_branch (skipped on Windows) ===");
172
178
  }
173
179
 
174
180
  // ─── Test 3: Corrupt merge state detection & fix ───────────────────
175
- test('corrupt_merge_state', async () => {
181
+ console.log("\n=== corrupt_merge_state ===");
182
+ {
176
183
  const dir = createRepoWithCompletedMilestone();
177
184
  cleanups.push(dir);
178
185
 
@@ -182,17 +189,18 @@ describe('doctor-git', async () => {
182
189
 
183
190
  const detect = await runGSDDoctor(dir);
184
191
  const mergeIssues = detect.issues.filter(i => i.code === "corrupt_merge_state");
185
- assert.ok(mergeIssues.length > 0, "detects corrupt merge state");
192
+ assertTrue(mergeIssues.length > 0, "detects corrupt merge state");
186
193
 
187
194
  const fixed = await runGSDDoctor(dir, { fix: true });
188
- assert.ok(fixed.fixesApplied.some(f => f.includes("cleaned merge state")), "fix cleans merge state");
195
+ assertTrue(fixed.fixesApplied.some(f => f.includes("cleaned merge state")), "fix cleans merge state");
189
196
 
190
197
  // Verify MERGE_HEAD is gone
191
- assert.ok(!existsSync(join(dir, ".git", "MERGE_HEAD")), "MERGE_HEAD removed after fix");
192
- });
198
+ assertTrue(!existsSync(join(dir, ".git", "MERGE_HEAD")), "MERGE_HEAD removed after fix");
199
+ }
193
200
 
194
201
  // ─── Test 4: Tracked runtime files detection & fix ─────────────────
195
- test('tracked_runtime_files', async () => {
202
+ console.log("\n=== tracked_runtime_files ===");
203
+ {
196
204
  const dir = createRepoWithCompletedMilestone();
197
205
  cleanups.push(dir);
198
206
 
@@ -205,18 +213,19 @@ describe('doctor-git', async () => {
205
213
 
206
214
  const detect = await runGSDDoctor(dir);
207
215
  const trackedIssues = detect.issues.filter(i => i.code === "tracked_runtime_files");
208
- assert.ok(trackedIssues.length > 0, "detects tracked runtime files");
216
+ assertTrue(trackedIssues.length > 0, "detects tracked runtime files");
209
217
 
210
218
  const fixed = await runGSDDoctor(dir, { fix: true });
211
- assert.ok(fixed.fixesApplied.some(f => f.includes("untracked")), "fix untracks runtime files");
219
+ assertTrue(fixed.fixesApplied.some(f => f.includes("untracked")), "fix untracks runtime files");
212
220
 
213
221
  // Verify file is no longer tracked
214
222
  const tracked = run("git ls-files .gsd/activity/", dir);
215
- assert.deepStrictEqual(tracked, "", "runtime file untracked after fix");
216
- });
223
+ assertEq(tracked, "", "runtime file untracked after fix");
224
+ }
217
225
 
218
226
  // ─── Test 5: Non-git directory — graceful degradation ──────────────
219
- test('non-git directory', async () => {
227
+ console.log("\n=== non-git directory ===");
228
+ {
220
229
  const dir = realpathSync(mkdtempSync(join(tmpdir(), "doc-git-test-")));
221
230
  cleanups.push(dir);
222
231
 
@@ -227,14 +236,15 @@ describe('doctor-git', async () => {
227
236
  const gitIssues = result.issues.filter(i =>
228
237
  ["orphaned_auto_worktree", "stale_milestone_branch", "corrupt_merge_state", "tracked_runtime_files"].includes(i.code)
229
238
  );
230
- assert.deepStrictEqual(gitIssues.length, 0, "no git issues in non-git directory");
239
+ assertEq(gitIssues.length, 0, "no git issues in non-git directory");
231
240
  // Should not throw — reaching here means no crash
232
- assert.ok(true, "non-git directory does not crash");
233
- });
241
+ assertTrue(true, "non-git directory does not crash");
242
+ }
234
243
 
235
244
  // ─── Test 6: Active worktree NOT flagged (false positive prevention) ─
236
245
  if (process.platform !== "win32") {
237
- test('active worktree safety', async () => {
246
+ console.log("\n=== active worktree safety ===");
247
+ {
238
248
  const dir = createRepoWithActiveMilestone();
239
249
  cleanups.push(dir);
240
250
 
@@ -244,9 +254,10 @@ describe('doctor-git', async () => {
244
254
 
245
255
  const detect = await runGSDDoctor(dir, { isolationMode: "worktree" });
246
256
  const orphanIssues = detect.issues.filter(i => i.code === "orphaned_auto_worktree");
247
- assert.deepStrictEqual(orphanIssues.length, 0, "active worktree NOT flagged as orphaned");
248
- });
257
+ assertEq(orphanIssues.length, 0, "active worktree NOT flagged as orphaned");
258
+ }
249
259
  } else {
260
+ console.log("\n=== active worktree safety (skipped on Windows) ===");
250
261
  }
251
262
 
252
263
  // ─── Test 7: none-mode skips orphaned worktree check ───────────────
@@ -254,7 +265,8 @@ describe('doctor-git', async () => {
254
265
  // at module load time from process.cwd(). We write the prefs file to
255
266
  // the test runner's cwd .gsd/preferences.md and clean up afterwards.
256
267
  if (process.platform !== "win32") {
257
- test('none-mode skips orphaned worktree', async () => {
268
+ console.log("\n=== none-mode skips orphaned worktree ===");
269
+ {
258
270
  const dir = createRepoWithCompletedMilestone();
259
271
  cleanups.push(dir);
260
272
 
@@ -264,14 +276,16 @@ describe('doctor-git', async () => {
264
276
 
265
277
  const result = await runGSDDoctor(dir, { isolationMode: "none" });
266
278
  const orphanIssues = result.issues.filter(i => i.code === "orphaned_auto_worktree");
267
- assert.deepStrictEqual(orphanIssues.length, 0, "none-mode: orphaned worktree NOT detected");
268
- });
279
+ assertEq(orphanIssues.length, 0, "none-mode: orphaned worktree NOT detected");
280
+ }
269
281
  } else {
282
+ console.log("\n=== none-mode skips orphaned worktree (skipped on Windows) ===");
270
283
  }
271
284
 
272
285
  // ─── Test 8: none-mode skips stale branch check ────────────────────
273
286
  if (process.platform !== "win32") {
274
- test('none-mode skips stale branch', async () => {
287
+ console.log("\n=== none-mode skips stale branch ===");
288
+ {
275
289
  const dir = createRepoWithCompletedMilestone();
276
290
  cleanups.push(dir);
277
291
 
@@ -280,14 +294,16 @@ describe('doctor-git', async () => {
280
294
 
281
295
  const result = await runGSDDoctor(dir, { isolationMode: "none" });
282
296
  const staleIssues = result.issues.filter(i => i.code === "stale_milestone_branch");
283
- assert.deepStrictEqual(staleIssues.length, 0, "none-mode: stale branch NOT detected");
284
- });
297
+ assertEq(staleIssues.length, 0, "none-mode: stale branch NOT detected");
298
+ }
285
299
  } else {
300
+ console.log("\n=== none-mode skips stale branch (skipped on Windows) ===");
286
301
  }
287
302
 
288
303
  // ─── Test: Integration branch missing ──────────────────────────────
289
304
  if (process.platform !== "win32") {
290
- test('integration_branch_missing', async () => {
305
+ console.log("\n=== integration_branch_missing ===");
306
+ {
291
307
  const dir = createRepoWithActiveMilestone();
292
308
  cleanups.push(dir);
293
309
 
@@ -297,20 +313,22 @@ describe('doctor-git', async () => {
297
313
 
298
314
  const detect = await runGSDDoctor(dir);
299
315
  const missingBranchIssues = detect.issues.filter(i => i.code === "integration_branch_missing");
300
- assert.ok(missingBranchIssues.length > 0, "detects missing integration branch");
301
- assert.ok(
316
+ assertTrue(missingBranchIssues.length > 0, "detects missing integration branch");
317
+ assertTrue(
302
318
  missingBranchIssues[0]?.message.includes("feat/does-not-exist"),
303
319
  "message includes the missing branch name",
304
320
  );
305
- assert.deepStrictEqual(missingBranchIssues[0]?.fixable, true, "integration_branch_missing is auto-fixable via fallback");
306
- assert.deepStrictEqual(missingBranchIssues[0]?.severity, "warning", "severity is warning (fallback available)");
307
- });
321
+ assertEq(missingBranchIssues[0]?.fixable, true, "integration_branch_missing is auto-fixable via fallback");
322
+ assertEq(missingBranchIssues[0]?.severity, "warning", "severity is warning (fallback available)");
323
+ }
308
324
  } else {
325
+ console.log("\n=== integration_branch_missing (skipped on Windows) ===");
309
326
  }
310
327
 
311
328
  // ─── Test: Integration branch present — no false positive ──────────
312
329
  if (process.platform !== "win32") {
313
- test('integration_branch_missing (no false positive)', async () => {
330
+ console.log("\n=== integration_branch_missing (no false positive) ===");
331
+ {
314
332
  const dir = createRepoWithActiveMilestone();
315
333
  cleanups.push(dir);
316
334
 
@@ -320,13 +338,15 @@ describe('doctor-git', async () => {
320
338
 
321
339
  const detect = await runGSDDoctor(dir);
322
340
  const missingBranchIssues = detect.issues.filter(i => i.code === "integration_branch_missing");
323
- assert.deepStrictEqual(missingBranchIssues.length, 0, "existing integration branch NOT flagged");
324
- });
341
+ assertEq(missingBranchIssues.length, 0, "existing integration branch NOT flagged");
342
+ }
325
343
  } else {
344
+ console.log("\n=== integration_branch_missing (no false positive — skipped on Windows) ===");
326
345
  }
327
346
 
328
347
  // ─── Test: Orphaned worktree directory ─────────────────────────────
329
- test('integration_branch_missing: stale metadata with detected fallback', async () => {
348
+ console.log("\n=== integration_branch_missing: stale metadata with detected fallback ===");
349
+ {
330
350
  const dir = createRepoWithActiveMilestone();
331
351
  cleanups.push(dir);
332
352
 
@@ -335,26 +355,27 @@ describe('doctor-git', async () => {
335
355
 
336
356
  const detect = await runGSDDoctor(dir);
337
357
  const missingBranchIssues = detect.issues.filter(i => i.code === "integration_branch_missing");
338
- assert.deepStrictEqual(missingBranchIssues.length, 1, "reports one stale integration branch issue");
339
- assert.deepStrictEqual(missingBranchIssues[0]?.severity, "warning", "stale metadata is warning when a fallback branch exists");
340
- assert.deepStrictEqual(missingBranchIssues[0]?.fixable, true, "stale metadata becomes auto-fixable when fallback exists");
341
- assert.ok(
358
+ assertEq(missingBranchIssues.length, 1, "reports one stale integration branch issue");
359
+ assertEq(missingBranchIssues[0]?.severity, "warning", "stale metadata is warning when a fallback branch exists");
360
+ assertEq(missingBranchIssues[0]?.fixable, true, "stale metadata becomes auto-fixable when fallback exists");
361
+ assertTrue(
342
362
  missingBranchIssues[0]?.message.includes("feat/does-not-exist") &&
343
363
  missingBranchIssues[0]?.message.includes("main"),
344
364
  "warning mentions stale recorded branch and detected fallback branch",
345
365
  );
346
366
 
347
367
  const fixed = await runGSDDoctor(dir, { fix: true });
348
- assert.ok(
368
+ assertTrue(
349
369
  fixed.fixesApplied.some(f => f.includes('updated integration branch for M001 to "main"')),
350
370
  "doctor fix rewrites stale integration branch metadata to detected fallback branch",
351
371
  );
352
372
 
353
373
  const repairedMeta = JSON.parse(readFileSync(metaPath, "utf-8"));
354
- assert.deepStrictEqual(repairedMeta.integrationBranch, "main", "metadata rewritten to detected fallback branch");
355
- });
374
+ assertEq(repairedMeta.integrationBranch, "main", "metadata rewritten to detected fallback branch");
375
+ }
356
376
 
357
- test('integration_branch_missing: stale metadata with configured fallback', async () => {
377
+ console.log("\n=== integration_branch_missing: stale metadata with configured fallback ===");
378
+ {
358
379
  const dir = createRepoWithActiveMilestone();
359
380
  cleanups.push(dir);
360
381
 
@@ -369,17 +390,17 @@ describe('doctor-git', async () => {
369
390
  try {
370
391
  const detect = await runGSDDoctor(dir);
371
392
  const missingBranchIssues = detect.issues.filter(i => i.code === "integration_branch_missing");
372
- assert.deepStrictEqual(missingBranchIssues.length, 1, "configured fallback still reports one stale integration branch issue");
373
- assert.deepStrictEqual(missingBranchIssues[0]?.severity, "warning", "configured fallback keeps stale metadata at warning severity");
374
- assert.deepStrictEqual(missingBranchIssues[0]?.fixable, true, "configured fallback remains auto-fixable");
375
- assert.ok(
393
+ assertEq(missingBranchIssues.length, 1, "configured fallback still reports one stale integration branch issue");
394
+ assertEq(missingBranchIssues[0]?.severity, "warning", "configured fallback keeps stale metadata at warning severity");
395
+ assertEq(missingBranchIssues[0]?.fixable, true, "configured fallback remains auto-fixable");
396
+ assertTrue(
376
397
  missingBranchIssues[0]?.message.includes("feat/does-not-exist") &&
377
398
  missingBranchIssues[0]?.message.includes("trunk"),
378
399
  "warning mentions stale recorded branch and configured fallback branch",
379
400
  );
380
401
 
381
402
  const fixed = await runGSDDoctor(dir, { fix: true });
382
- assert.ok(
403
+ assertTrue(
383
404
  fixed.fixesApplied.some(f => f.includes('updated integration branch for M001 to "trunk"')),
384
405
  "doctor fix rewrites stale metadata to configured fallback branch",
385
406
  );
@@ -388,11 +409,12 @@ describe('doctor-git', async () => {
388
409
  }
389
410
 
390
411
  const repairedMeta = JSON.parse(readFileSync(metaPath, "utf-8"));
391
- assert.deepStrictEqual(repairedMeta.integrationBranch, "trunk", "metadata rewritten to configured fallback branch");
392
- });
412
+ assertEq(repairedMeta.integrationBranch, "trunk", "metadata rewritten to configured fallback branch");
413
+ }
393
414
 
394
415
  if (process.platform !== "win32") {
395
- test('worktree_directory_orphaned', async () => {
416
+ console.log("\n=== worktree_directory_orphaned ===");
417
+ {
396
418
  const dir = createRepoWithActiveMilestone();
397
419
  cleanups.push(dir);
398
420
 
@@ -403,26 +425,28 @@ describe('doctor-git', async () => {
403
425
 
404
426
  const detect = await runGSDDoctor(dir);
405
427
  const orphanDirIssues = detect.issues.filter(i => i.code === "worktree_directory_orphaned");
406
- assert.ok(orphanDirIssues.length > 0, "detects orphaned worktree directory");
407
- assert.ok(
428
+ assertTrue(orphanDirIssues.length > 0, "detects orphaned worktree directory");
429
+ assertTrue(
408
430
  orphanDirIssues[0]?.message.includes("orphan-feature"),
409
431
  "message includes the orphaned directory name",
410
432
  );
411
- assert.ok(orphanDirIssues[0]?.fixable === true, "worktree_directory_orphaned is fixable");
433
+ assertTrue(orphanDirIssues[0]?.fixable === true, "worktree_directory_orphaned is fixable");
412
434
 
413
435
  const fixed = await runGSDDoctor(dir, { fix: true });
414
- assert.ok(
436
+ assertTrue(
415
437
  fixed.fixesApplied.some(f => f.includes("removed orphaned worktree directory")),
416
438
  "fix removes orphaned worktree directory",
417
439
  );
418
- assert.ok(!existsSync(orphanDir), "orphaned directory removed after fix");
419
- });
440
+ assertTrue(!existsSync(orphanDir), "orphaned directory removed after fix");
441
+ }
420
442
  } else {
443
+ console.log("\n=== worktree_directory_orphaned (skipped on Windows) ===");
421
444
  }
422
445
 
423
446
  // ─── Test: Registered worktree NOT flagged as orphaned ─────────────
424
447
  if (process.platform !== "win32") {
425
- test('worktree_directory_orphaned (registered worktree not flagged)', async () => {
448
+ console.log("\n=== worktree_directory_orphaned (registered worktree not flagged) ===");
449
+ {
426
450
  const dir = createRepoWithActiveMilestone();
427
451
  cleanups.push(dir);
428
452
 
@@ -432,13 +456,15 @@ describe('doctor-git', async () => {
432
456
 
433
457
  const detect = await runGSDDoctor(dir);
434
458
  const orphanDirIssues = detect.issues.filter(i => i.code === "worktree_directory_orphaned");
435
- assert.deepStrictEqual(orphanDirIssues.length, 0, "registered worktree NOT flagged as orphaned");
436
- });
459
+ assertEq(orphanDirIssues.length, 0, "registered worktree NOT flagged as orphaned");
460
+ }
437
461
  } else {
462
+ console.log("\n=== worktree_directory_orphaned (registered worktree not flagged — skipped on Windows) ===");
438
463
  }
439
464
 
440
465
  // ─── Test 9: none-mode still detects corrupt merge state ───────────
441
- test('none-mode keeps corrupt merge state', async () => {
466
+ console.log("\n=== none-mode keeps corrupt merge state ===");
467
+ {
442
468
  const dir = createRepoWithCompletedMilestone();
443
469
  cleanups.push(dir);
444
470
 
@@ -448,11 +474,12 @@ describe('doctor-git', async () => {
448
474
 
449
475
  const result = await runGSDDoctor(dir, { isolationMode: "none" });
450
476
  const mergeIssues = result.issues.filter(i => i.code === "corrupt_merge_state");
451
- assert.ok(mergeIssues.length > 0, "none-mode: corrupt merge state IS detected");
452
- });
477
+ assertTrue(mergeIssues.length > 0, "none-mode: corrupt merge state IS detected");
478
+ }
453
479
 
454
480
  // ─── Test 10: none-mode still detects tracked runtime files ────────
455
- test('none-mode keeps tracked runtime files', async () => {
481
+ console.log("\n=== none-mode keeps tracked runtime files ===");
482
+ {
456
483
  const dir = createRepoWithCompletedMilestone();
457
484
  cleanups.push(dir);
458
485
 
@@ -465,12 +492,13 @@ describe('doctor-git', async () => {
465
492
 
466
493
  const result = await runGSDDoctor(dir, { isolationMode: "none" });
467
494
  const trackedIssues = result.issues.filter(i => i.code === "tracked_runtime_files");
468
- assert.ok(trackedIssues.length > 0, "none-mode: tracked runtime files IS detected");
469
- });
495
+ assertTrue(trackedIssues.length > 0, "none-mode: tracked runtime files IS detected");
496
+ }
470
497
 
471
498
  // ─── Test: Symlinked .gsd does not cause false orphan detection ────
472
499
  if (process.platform !== "win32") {
473
- test('worktree_directory_orphaned (symlinked .gsd not false-positive)', async () => {
500
+ console.log("\n=== worktree_directory_orphaned (symlinked .gsd not false-positive) ===");
501
+ {
474
502
  const dir = createRepoWithActiveMilestone();
475
503
  cleanups.push(dir);
476
504
 
@@ -487,14 +515,16 @@ describe('doctor-git', async () => {
487
515
 
488
516
  const detect = await runGSDDoctor(dir);
489
517
  const orphanDirIssues = detect.issues.filter(i => i.code === "worktree_directory_orphaned");
490
- assert.deepStrictEqual(orphanDirIssues.length, 0, "registered worktree via symlinked .gsd NOT flagged as orphaned");
491
- });
518
+ assertEq(orphanDirIssues.length, 0, "registered worktree via symlinked .gsd NOT flagged as orphaned");
519
+ }
492
520
  } else {
521
+ console.log("\n=== worktree_directory_orphaned (symlinked .gsd — skipped on Windows) ===");
493
522
  }
494
523
 
495
524
  // ─── Test: worktree_branch_merged detection & fix ──────────────────
496
525
  if (process.platform !== "win32") {
497
- test('worktree_branch_merged', async () => {
526
+ console.log("\n=== worktree_branch_merged ===");
527
+ {
498
528
  const dir = createRepoWithActiveMilestone();
499
529
  cleanups.push(dir);
500
530
 
@@ -511,21 +541,23 @@ describe('doctor-git', async () => {
511
541
 
512
542
  const detect = await runGSDDoctor(dir);
513
543
  const mergedIssues = detect.issues.filter(i => i.code === "worktree_branch_merged");
514
- assert.ok(mergedIssues.length > 0, "detects merged worktree branch");
515
- assert.ok(mergedIssues[0]?.message.includes("safe to remove"), "message says safe to remove");
516
- assert.ok(mergedIssues[0]?.fixable === true, "merged worktree is fixable");
544
+ assertTrue(mergedIssues.length > 0, "detects merged worktree branch");
545
+ assertTrue(mergedIssues[0]?.message.includes("safe to remove"), "message says safe to remove");
546
+ assertTrue(mergedIssues[0]?.fixable === true, "merged worktree is fixable");
517
547
 
518
548
  // Fix should remove the worktree
519
549
  const fixed = await runGSDDoctor(dir, { fix: true });
520
- assert.ok(fixed.fixesApplied.some(f => f.includes("removed merged worktree")), "fix removes merged worktree");
521
- assert.ok(!existsSync(wtPath), "worktree directory removed after fix");
522
- });
550
+ assertTrue(fixed.fixesApplied.some(f => f.includes("removed merged worktree")), "fix removes merged worktree");
551
+ assertTrue(!existsSync(wtPath), "worktree directory removed after fix");
552
+ }
523
553
  } else {
554
+ console.log("\n=== worktree_branch_merged (skipped on Windows) ===");
524
555
  }
525
556
 
526
557
  // ─── Test: merged milestone/* worktree removes milestone branch ────
527
558
  if (process.platform !== "win32") {
528
- test('worktree_branch_merged (milestone branch cleanup)', async () => {
559
+ console.log("\n=== worktree_branch_merged (milestone branch cleanup) ===");
560
+ {
529
561
  const dir = createRepoWithActiveMilestone();
530
562
  cleanups.push(dir);
531
563
 
@@ -538,18 +570,20 @@ describe('doctor-git', async () => {
538
570
  run("git merge milestone/M001 --no-edit", dir);
539
571
 
540
572
  const fixed = await runGSDDoctor(dir, { fix: true });
541
- assert.ok(fixed.fixesApplied.some(f => f.includes("removed merged worktree")), "fix removes merged milestone worktree");
542
- assert.ok(!existsSync(wtPath), "milestone worktree directory removed after fix");
573
+ assertTrue(fixed.fixesApplied.some(f => f.includes("removed merged worktree")), "fix removes merged milestone worktree");
574
+ assertTrue(!existsSync(wtPath), "milestone worktree directory removed after fix");
543
575
 
544
576
  const branches = run("git branch --list milestone/M001", dir);
545
- assert.deepStrictEqual(branches, "", "milestone/M001 branch deleted after merged worktree cleanup");
546
- });
577
+ assertEq(branches, "", "milestone/M001 branch deleted after merged worktree cleanup");
578
+ }
547
579
  } else {
580
+ console.log("\n=== worktree_branch_merged (milestone branch cleanup — skipped on Windows) ===");
548
581
  }
549
582
 
550
583
  // ─── Test: worktree_branch_merged NOT flagged for unmerged worktree ─
551
584
  if (process.platform !== "win32") {
552
- test('worktree_branch_merged (no false positive)', async () => {
585
+ console.log("\n=== worktree_branch_merged (no false positive) ===");
586
+ {
553
587
  const dir = createRepoWithActiveMilestone();
554
588
  cleanups.push(dir);
555
589
 
@@ -563,14 +597,16 @@ describe('doctor-git', async () => {
563
597
  // Do NOT merge — branch is ahead of main
564
598
  const detect = await runGSDDoctor(dir);
565
599
  const mergedIssues = detect.issues.filter(i => i.code === "worktree_branch_merged");
566
- assert.deepStrictEqual(mergedIssues.length, 0, "unmerged worktree NOT flagged as merged");
567
- });
600
+ assertEq(mergedIssues.length, 0, "unmerged worktree NOT flagged as merged");
601
+ }
568
602
  } else {
603
+ console.log("\n=== worktree_branch_merged (no false positive — skipped on Windows) ===");
569
604
  }
570
605
 
571
606
  // ─── Test: legacy_slice_branches now fixable ───────────────────────
572
607
  if (process.platform !== "win32") {
573
- test('legacy_slice_branches (fixable)', async () => {
608
+ console.log("\n=== legacy_slice_branches (fixable) ===");
609
+ {
574
610
  const dir = createRepoWithActiveMilestone();
575
611
  cleanups.push(dir);
576
612
 
@@ -582,17 +618,18 @@ describe('doctor-git', async () => {
582
618
 
583
619
  const detect = await runGSDDoctor(dir);
584
620
  const legacyIssues = detect.issues.filter(i => i.code === "legacy_slice_branches");
585
- assert.ok(legacyIssues.length > 0, "detects legacy slice branches");
586
- assert.ok(legacyIssues[0]?.fixable === true, "legacy branches are fixable");
621
+ assertTrue(legacyIssues.length > 0, "detects legacy slice branches");
622
+ assertTrue(legacyIssues[0]?.fixable === true, "legacy branches are fixable");
587
623
 
588
624
  const fixed = await runGSDDoctor(dir, { fix: true });
589
- assert.ok(fixed.fixesApplied.some(f => f.includes("legacy slice branch")), "fix deletes legacy branches");
625
+ assertTrue(fixed.fixesApplied.some(f => f.includes("legacy slice branch")), "fix deletes legacy branches");
590
626
 
591
627
  // Verify branches are gone
592
628
  const remaining = run("git branch --list gsd/*/*", dir);
593
- assert.deepStrictEqual(remaining, "gsd/quick/1-fix-typo", "quick branch preserved; legacy branches removed");
594
- });
629
+ assertEq(remaining, "gsd/quick/1-fix-typo", "quick branch preserved; legacy branches removed");
630
+ }
595
631
  } else {
632
+ console.log("\n=== legacy_slice_branches (fixable — skipped on Windows) ===");
596
633
  }
597
634
 
598
635
  } finally {
@@ -600,4 +637,8 @@ describe('doctor-git', async () => {
600
637
  try { rmSync(dir, { recursive: true, force: true }); } catch { /* ignore */ }
601
638
  }
602
639
  }
603
- });
640
+
641
+ report();
642
+ }
643
+
644
+ main();