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
@@ -17,9 +17,9 @@ import {
17
17
  } from "../worktree.ts";
18
18
  import { readIntegrationBranch } from "../git-service.ts";
19
19
  import { _resetHasChangesCache } from "../native-git-bridge.ts";
20
- import { describe, test } from 'node:test';
21
- import assert from 'node:assert/strict';
20
+ import { createTestContext } from './test-helpers.ts';
22
21
 
22
+ const { assertEq, assertTrue, report } = createTestContext();
23
23
 
24
24
  /**
25
25
  * Normalize a path for reliable comparison on Windows CI runners.
@@ -47,56 +47,56 @@ writeFileSync(join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-PLA
47
47
  run("git add .", base);
48
48
  run('git commit -m "chore: init"', base);
49
49
 
50
- describe('worktree', async () => {
50
+ async function main(): Promise<void> {
51
51
 
52
52
  console.log("\n=== autoCommitCurrentBranch ===");
53
53
  // Clean — should return null
54
54
  const cleanResult = autoCommitCurrentBranch(base, "execute-task", "M001/S01/T01");
55
- assert.deepStrictEqual(cleanResult, null, "returns null for clean repo");
55
+ assertEq(cleanResult, null, "returns null for clean repo");
56
56
 
57
57
  // Make dirty — reset the nativeHasChanges cache so the fresh dirt is detected
58
58
  _resetHasChangesCache();
59
59
  writeFileSync(join(base, "dirty.txt"), "uncommitted\n", "utf-8");
60
60
  const dirtyResult = autoCommitCurrentBranch(base, "execute-task", "M001/S01/T01");
61
- assert.ok(dirtyResult !== null, "returns commit message for dirty repo");
62
- assert.ok(dirtyResult!.includes("M001/S01/T01"), "commit message includes unit id");
63
- assert.deepStrictEqual(run("git status --short", base), "", "repo is clean after auto-commit");
61
+ assertTrue(dirtyResult !== null, "returns commit message for dirty repo");
62
+ assertTrue(dirtyResult!.includes("M001/S01/T01"), "commit message includes unit id");
63
+ assertEq(run("git status --short", base), "", "repo is clean after auto-commit");
64
64
 
65
65
  console.log("\n=== getSliceBranchName ===");
66
- assert.deepStrictEqual(getSliceBranchName("M001", "S01"), "gsd/M001/S01", "branch name format correct");
67
- assert.deepStrictEqual(getSliceBranchName("M001", "S01", null), "gsd/M001/S01", "null worktree = plain branch");
68
- assert.deepStrictEqual(getSliceBranchName("M001", "S01", "my-wt"), "gsd/my-wt/M001/S01", "worktree-namespaced branch");
66
+ assertEq(getSliceBranchName("M001", "S01"), "gsd/M001/S01", "branch name format correct");
67
+ assertEq(getSliceBranchName("M001", "S01", null), "gsd/M001/S01", "null worktree = plain branch");
68
+ assertEq(getSliceBranchName("M001", "S01", "my-wt"), "gsd/my-wt/M001/S01", "worktree-namespaced branch");
69
69
 
70
70
  console.log("\n=== parseSliceBranch ===");
71
71
  const plain = parseSliceBranch("gsd/M001/S01");
72
- assert.ok(plain !== null, "parses plain branch");
73
- assert.deepStrictEqual(plain!.worktreeName, null, "plain branch has no worktree name");
74
- assert.deepStrictEqual(plain!.milestoneId, "M001", "plain branch milestone");
75
- assert.deepStrictEqual(plain!.sliceId, "S01", "plain branch slice");
72
+ assertTrue(plain !== null, "parses plain branch");
73
+ assertEq(plain!.worktreeName, null, "plain branch has no worktree name");
74
+ assertEq(plain!.milestoneId, "M001", "plain branch milestone");
75
+ assertEq(plain!.sliceId, "S01", "plain branch slice");
76
76
 
77
77
  const namespaced = parseSliceBranch("gsd/feature-auth/M001/S01");
78
- assert.ok(namespaced !== null, "parses worktree-namespaced branch");
79
- assert.deepStrictEqual(namespaced!.worktreeName, "feature-auth", "worktree name extracted");
80
- assert.deepStrictEqual(namespaced!.milestoneId, "M001", "namespaced branch milestone");
81
- assert.deepStrictEqual(namespaced!.sliceId, "S01", "namespaced branch slice");
78
+ assertTrue(namespaced !== null, "parses worktree-namespaced branch");
79
+ assertEq(namespaced!.worktreeName, "feature-auth", "worktree name extracted");
80
+ assertEq(namespaced!.milestoneId, "M001", "namespaced branch milestone");
81
+ assertEq(namespaced!.sliceId, "S01", "namespaced branch slice");
82
82
 
83
83
  const invalid = parseSliceBranch("main");
84
- assert.deepStrictEqual(invalid, null, "non-slice branch returns null");
84
+ assertEq(invalid, null, "non-slice branch returns null");
85
85
 
86
86
  const worktreeBranch = parseSliceBranch("worktree/foo");
87
- assert.deepStrictEqual(worktreeBranch, null, "worktree/ prefix is not a slice branch");
87
+ assertEq(worktreeBranch, null, "worktree/ prefix is not a slice branch");
88
88
 
89
89
  console.log("\n=== SLICE_BRANCH_RE ===");
90
- assert.ok(SLICE_BRANCH_RE.test("gsd/M001/S01"), "regex matches plain branch");
91
- assert.ok(SLICE_BRANCH_RE.test("gsd/my-wt/M001/S01"), "regex matches worktree branch");
92
- assert.ok(!SLICE_BRANCH_RE.test("main"), "regex rejects main");
93
- assert.ok(!SLICE_BRANCH_RE.test("gsd/"), "regex rejects bare gsd/");
94
- assert.ok(!SLICE_BRANCH_RE.test("worktree/foo"), "regex rejects worktree/foo");
90
+ assertTrue(SLICE_BRANCH_RE.test("gsd/M001/S01"), "regex matches plain branch");
91
+ assertTrue(SLICE_BRANCH_RE.test("gsd/my-wt/M001/S01"), "regex matches worktree branch");
92
+ assertTrue(!SLICE_BRANCH_RE.test("main"), "regex rejects main");
93
+ assertTrue(!SLICE_BRANCH_RE.test("gsd/"), "regex rejects bare gsd/");
94
+ assertTrue(!SLICE_BRANCH_RE.test("worktree/foo"), "regex rejects worktree/foo");
95
95
 
96
96
  console.log("\n=== detectWorktreeName ===");
97
- assert.deepStrictEqual(detectWorktreeName("/projects/myapp"), null, "no worktree in plain path");
98
- assert.deepStrictEqual(detectWorktreeName("/projects/myapp/.gsd/worktrees/feature-auth"), "feature-auth", "detects worktree name");
99
- assert.deepStrictEqual(detectWorktreeName("/projects/myapp/.gsd/worktrees/my-wt/subdir"), "my-wt", "detects worktree with subdir");
97
+ assertEq(detectWorktreeName("/projects/myapp"), null, "no worktree in plain path");
98
+ assertEq(detectWorktreeName("/projects/myapp/.gsd/worktrees/feature-auth"), "feature-auth", "detects worktree name");
99
+ assertEq(detectWorktreeName("/projects/myapp/.gsd/worktrees/my-wt/subdir"), "my-wt", "detects worktree with subdir");
100
100
 
101
101
  // ═══════════════════════════════════════════════════════════════════════
102
102
  // Integration branch — facade-level tests
@@ -115,16 +115,16 @@ describe('worktree', async () => {
115
115
  run("git add -A && git commit -m init", repo);
116
116
 
117
117
  run("git checkout -b f-123-thing", repo);
118
- assert.deepStrictEqual(getCurrentBranch(repo), "f-123-thing", "on feature branch");
118
+ assertEq(getCurrentBranch(repo), "f-123-thing", "on feature branch");
119
119
 
120
120
  const commitsBefore = run("git rev-list --count HEAD", repo);
121
121
  captureIntegrationBranch(repo, "M001");
122
- assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), "f-123-thing",
122
+ assertEq(readIntegrationBranch(repo, "M001"), "f-123-thing",
123
123
  "captureIntegrationBranch records the current branch");
124
124
 
125
125
  // Metadata is stored in external state, not committed to git.
126
126
  const commitsAfter = run("git rev-list --count HEAD", repo);
127
- assert.deepStrictEqual(commitsAfter, commitsBefore, "captureIntegrationBranch does not create a git commit");
127
+ assertEq(commitsAfter, commitsBefore, "captureIntegrationBranch does not create a git commit");
128
128
 
129
129
  rmSync(repo, { recursive: true, force: true });
130
130
  }
@@ -144,7 +144,7 @@ describe('worktree', async () => {
144
144
  run("git checkout -b gsd/M001/S01", repo);
145
145
  captureIntegrationBranch(repo, "M001");
146
146
 
147
- assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null,
147
+ assertEq(readIntegrationBranch(repo, "M001"), null,
148
148
  "capture from slice branch is a no-op");
149
149
 
150
150
  rmSync(repo, { recursive: true, force: true });
@@ -167,12 +167,12 @@ describe('worktree', async () => {
167
167
 
168
168
  // Without milestone set, getMainBranch returns "main"
169
169
  setActiveMilestoneId(repo, null);
170
- assert.deepStrictEqual(getMainBranch(repo), "main",
170
+ assertEq(getMainBranch(repo), "main",
171
171
  "getMainBranch returns main without milestone set");
172
172
 
173
173
  // With milestone set, getMainBranch returns feature branch
174
174
  setActiveMilestoneId(repo, "M001");
175
- assert.deepStrictEqual(getMainBranch(repo), "my-feature",
175
+ assertEq(getMainBranch(repo), "my-feature",
176
176
  "getMainBranch returns integration branch with milestone set");
177
177
 
178
178
  rmSync(repo, { recursive: true, force: true });
@@ -180,22 +180,22 @@ describe('worktree', async () => {
180
180
 
181
181
  // ── detectWorktreeName: symlink-resolved paths ───────────────────────────
182
182
  console.log("\n=== detectWorktreeName (symlink-resolved paths) ===");
183
- assert.deepStrictEqual(
183
+ assertEq(
184
184
  detectWorktreeName("/Users/fran/.gsd/projects/89e1c9ad49bf/worktrees/M001"),
185
185
  "M001",
186
186
  "detects milestone in symlink-resolved path",
187
187
  );
188
- assert.deepStrictEqual(
188
+ assertEq(
189
189
  detectWorktreeName("/Users/fran/.gsd/projects/abc123/worktrees/M002/subdir"),
190
190
  "M002",
191
191
  "detects milestone with trailing subdir in symlink-resolved path",
192
192
  );
193
- assert.deepStrictEqual(
193
+ assertEq(
194
194
  detectWorktreeName("/Users/fran/.gsd/projects/abc123"),
195
195
  null,
196
196
  "returns null for project root without worktrees segment",
197
197
  );
198
- assert.deepStrictEqual(
198
+ assertEq(
199
199
  detectWorktreeName("/foo/.gsd/worktrees/M001"),
200
200
  "M001",
201
201
  "still detects direct layout path",
@@ -211,7 +211,7 @@ describe('worktree', async () => {
211
211
 
212
212
  // With GSD_PROJECT_ROOT env var set (layer 1 — coordinator passes it)
213
213
  process.env.GSD_PROJECT_ROOT = "/real/project";
214
- assert.deepStrictEqual(
214
+ assertEq(
215
215
  resolveProjectRoot("/Users/fran/.gsd/projects/89e1c9ad49bf/worktrees/M001"),
216
216
  "/real/project",
217
217
  "uses GSD_PROJECT_ROOT when set",
@@ -219,7 +219,7 @@ describe('worktree', async () => {
219
219
  delete process.env.GSD_PROJECT_ROOT;
220
220
 
221
221
  // Without GSD_PROJECT_ROOT, direct layout still works (no ~/.gsd collision)
222
- assert.deepStrictEqual(
222
+ assertEq(
223
223
  resolveProjectRoot("/some/repo"),
224
224
  "/some/repo",
225
225
  "ignores GSD_PROJECT_ROOT override for non-worktree paths",
@@ -227,19 +227,19 @@ describe('worktree', async () => {
227
227
  delete process.env.GSD_PROJECT_ROOT;
228
228
 
229
229
  // Without GSD_PROJECT_ROOT, direct layout still works (no ~/.gsd collision)
230
- assert.deepStrictEqual(
230
+ assertEq(
231
231
  resolveProjectRoot("/foo/.gsd/worktrees/M001"),
232
232
  "/foo",
233
233
  "still resolves direct layout path",
234
234
  );
235
- assert.deepStrictEqual(
235
+ assertEq(
236
236
  resolveProjectRoot("/some/repo"),
237
237
  "/some/repo",
238
238
  "returns unchanged for non-worktree path",
239
239
  );
240
240
 
241
241
  // Without GSD_PROJECT_ROOT, direct layout with nested subdirs
242
- assert.deepStrictEqual(
242
+ assertEq(
243
243
  resolveProjectRoot("/data/.gsd/worktrees/M003/nested"),
244
244
  "/data",
245
245
  "resolves correctly with nested subdirs after worktree name (direct layout)",
@@ -264,7 +264,7 @@ describe('worktree', async () => {
264
264
  mkdirSync(deep, { recursive: true });
265
265
 
266
266
  process.env.GSD_HOME = join(fakeHome, ".gsd");
267
- assert.deepStrictEqual(
267
+ assertEq(
268
268
  normalizePath(resolveProjectRoot(realpathSync(deep))),
269
269
  normalizePath(project),
270
270
  "resolves to real project root from deep symlink-resolved worktree path",
@@ -276,4 +276,10 @@ describe('worktree', async () => {
276
276
  }
277
277
 
278
278
  rmSync(base, { recursive: true, force: true });
279
+ report();
280
+ }
281
+
282
+ main().catch((error) => {
283
+ console.error(error);
284
+ process.exit(1);
279
285
  });
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8974],{2600:(e,t,n)=>{Promise.resolve().then(n.bind(n,66919))},5214:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorage",{enumerable:!0,get:function(){return r.workAsyncStorageInstance}});let r=n(17828)},17828:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorageInstance",{enumerable:!0,get:function(){return r}});let r=(0,n(64054).createAsyncLocalStorage)()},21957:(e,t,n)=>{"use strict";function r({moduleIds:e}){return null}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"PreloadChunks",{enumerable:!0,get:function(){return r}}),n(95155),n(47650),n(5214),n(2451),n(53887)},37206:(e,t,n)=>{"use strict";n.d(t,{default:()=>u.a});var r=n(75707),u=n.n(r)},41112:(e,t,n)=>{"use strict";function r({reason:e,children:t}){return t}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"BailoutToCSR",{enumerable:!0,get:function(){return r}}),n(1980)},64054:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={bindSnapshot:function(){return s},createAsyncLocalStorage:function(){return a},createSnapshot:function(){return i}};for(var r in n)Object.defineProperty(t,r,{enumerable:!0,get:n[r]});let u=Object.defineProperty(Error("Invariant: AsyncLocalStorage accessed in runtime where it is not available"),"__NEXT_ERROR_CODE",{value:"E504",enumerable:!1,configurable:!0});class l{disable(){throw u}getStore(){}run(){throw u}exit(){throw u}enterWith(){throw u}static bind(e){return e}}let o="u">typeof globalThis&&globalThis.AsyncLocalStorage;function a(){return o?new o:new l}function s(e){return o?o.bind(e):l.bind(e)}function i(){return o?o.snapshot():function(e,...t){return e(...t)}}},66919:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>l});var r=n(95155);let u=(0,n(37206).default)(()=>Promise.all([n.e(1838),n.e(6079),n.e(4986),n.e(3721),n.e(4024)]).then(n.bind(n,4024)).then(e=>e.GSDAppShell),{loadableGenerated:{webpack:()=>[4024]},ssr:!1,loading:()=>(0,r.jsx)("div",{className:"flex h-screen items-center justify-center bg-background text-sm text-muted-foreground",children:"Loading workspace…"})});function l(){return(0,r.jsx)(u,{})}},68635:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}});let r=n(95155),u=n(12115),l=n(41112);function o(e){return{default:e&&"default"in e?e.default:e}}n(21957);let a={loader:()=>Promise.resolve(o(()=>null)),loading:null,ssr:!0},s=function(e){let t={...a,...e},n=(0,u.lazy)(()=>t.loader().then(o)),s=t.loading;function i(e){let o=s?(0,r.jsx)(s,{isLoading:!0,pastDelay:!0,error:null}):null,a=!t.ssr||!!t.loading,i=a?u.Suspense:u.Fragment,c=t.ssr?(0,r.jsxs)(r.Fragment,{children:[null,(0,r.jsx)(n,{...e})]}):(0,r.jsx)(l.BailoutToCSR,{reason:"next/dynamic",children:(0,r.jsx)(n,{...e})});return(0,r.jsx)(i,{...a?{fallback:o}:{},children:c})}return i.displayName="LoadableComponent",i}},75707:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return u}});let r=n(73623)._(n(68635));function u(e,t){let n={};"function"==typeof e&&(n.loader=e);let u={...n,...t};return(0,r.default)({...u,modules:u.loadableGenerated?.modules})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=2600)),_N_E=e.O()}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7358],{19393:()=>{},55548:(e,s,n)=>{Promise.resolve().then(n.t.bind(n,27123,23)),Promise.resolve().then(n.t.bind(n,61304,23)),Promise.resolve().then(n.t.bind(n,78616,23)),Promise.resolve().then(n.t.bind(n,64777,23)),Promise.resolve().then(n.t.bind(n,57121,23)),Promise.resolve().then(n.t.bind(n,74581,23)),Promise.resolve().then(n.t.bind(n,90484,23)),Promise.resolve().then(n.bind(n,86869))}},e=>{var s=s=>e(e.s=s);e.O(0,[8441,3794],()=>(s(83861),s(55548))),_N_E=e.O()}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9337],{43946:(e,s,_)=>{Promise.resolve().then(_.t.bind(_,27123,23))}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=43946)),_N_E=e.O()}]);
@@ -1,100 +0,0 @@
1
- /**
2
- * Tests that /gsd quick is blocked when auto-mode is active.
3
- *
4
- * Relates to #2417: /gsd quick freezes terminal when auto-mode is active.
5
- * The fix adds an isAutoActive() guard in handleWorkflowCommand before
6
- * delegating to handleQuick.
7
- */
8
-
9
- import { describe, it, mock, beforeEach, afterEach } from "node:test";
10
- import assert from "node:assert/strict";
11
- import { readFileSync } from "node:fs";
12
- import { join } from "node:path";
13
-
14
- // ─── Structural test: verify the guard exists in source ──────────────────────
15
-
16
- describe("/gsd quick auto-mode guard (#2417)", () => {
17
- it("handleWorkflowCommand checks isAutoActive() before calling handleQuick", () => {
18
- // Read the source file and verify the guard is structurally present
19
- const src = readFileSync(
20
- join(
21
- import.meta.dirname,
22
- "..",
23
- "commands",
24
- "handlers",
25
- "workflow.ts",
26
- ),
27
- "utf-8",
28
- );
29
-
30
- // Find the quick command block
31
- const quickBlockMatch = src.match(
32
- /if\s*\(\s*trimmed\s*===\s*"quick"\s*\|\|\s*trimmed\.startsWith\("quick "\)\s*\)\s*\{([\s\S]*?)\n \}/,
33
- );
34
- assert.ok(quickBlockMatch, "quick command block exists in handleWorkflowCommand");
35
-
36
- const quickBlock = quickBlockMatch[1];
37
-
38
- // Verify isAutoActive guard comes BEFORE handleQuick call
39
- const guardIndex = quickBlock.indexOf("isAutoActive()");
40
- const handleQuickIndex = quickBlock.indexOf("handleQuick(");
41
-
42
- assert.ok(guardIndex !== -1, "isAutoActive() guard exists in quick command block");
43
- assert.ok(handleQuickIndex !== -1, "handleQuick() call exists in quick command block");
44
- assert.ok(
45
- guardIndex < handleQuickIndex,
46
- "isAutoActive() guard appears before handleQuick() call",
47
- );
48
- });
49
-
50
- it("guard shows error message mentioning /gsd stop", () => {
51
- const src = readFileSync(
52
- join(
53
- import.meta.dirname,
54
- "..",
55
- "commands",
56
- "handlers",
57
- "workflow.ts",
58
- ),
59
- "utf-8",
60
- );
61
-
62
- // The error message should tell the user to stop auto-mode first
63
- assert.ok(
64
- src.includes("/gsd quick cannot run while auto-mode is active"),
65
- "error message explains that quick cannot run during auto-mode",
66
- );
67
- assert.ok(
68
- src.includes("/gsd stop"),
69
- "error message mentions /gsd stop as the resolution",
70
- );
71
- });
72
-
73
- it("guard returns true (handled) to prevent falling through", () => {
74
- const src = readFileSync(
75
- join(
76
- import.meta.dirname,
77
- "..",
78
- "commands",
79
- "handlers",
80
- "workflow.ts",
81
- ),
82
- "utf-8",
83
- );
84
-
85
- // After the isAutoActive() check and notify, there should be a `return true`
86
- // before the handleQuick call
87
- const quickBlockMatch = src.match(
88
- /if\s*\(\s*trimmed\s*===\s*"quick"\s*\|\|\s*trimmed\.startsWith\("quick "\)\s*\)\s*\{([\s\S]*?)\n \}/,
89
- );
90
- assert.ok(quickBlockMatch);
91
- const quickBlock = quickBlockMatch[1];
92
-
93
- // The guard block should have its own return true before handleQuick
94
- const guardBlock = quickBlock.slice(0, quickBlock.indexOf("handleQuick("));
95
- assert.ok(
96
- guardBlock.includes("return true"),
97
- "guard block returns true before handleQuick is reached",
98
- );
99
- });
100
- });
@@ -1,63 +0,0 @@
1
- /**
2
- * sqlite-unavailable-gate.test.ts — #2419
3
- *
4
- * When the SQLite provider fails to open, bootstrapAutoSession must
5
- * refuse to start auto-mode. Otherwise gsd_task_complete returns
6
- * "db_unavailable", artifact retry re-dispatches the same task, and
7
- * the session loops forever.
8
- *
9
- * This test verifies the gate by reading auto-start.ts source and
10
- * confirming the pattern: after the DB lifecycle block, if the DB
11
- * file exists on disk but isDbAvailable() still returns false after
12
- * the open attempt, bootstrap must abort with an error notification.
13
- */
14
-
15
- import { readFileSync } from "node:fs";
16
- import { join } from "node:path";
17
- import { createTestContext } from "./test-helpers.ts";
18
-
19
- const { assertTrue, report } = createTestContext();
20
-
21
- const srcPath = join(import.meta.dirname, "..", "auto-start.ts");
22
- const src = readFileSync(srcPath, "utf-8");
23
-
24
- console.log("\n=== #2419: SQLite unavailable gate in auto-start.ts ===");
25
-
26
- // The DB lifecycle section tries to open the DB. After those try/catch
27
- // blocks, there must be a HARD GATE: if the DB file exists on disk but
28
- // isDbAvailable() is still false (open failed), bootstrap must abort
29
- // by calling releaseLockAndReturn() with an error notification.
30
-
31
- const dbLifecycleIdx = src.indexOf("DB lifecycle");
32
- assertTrue(dbLifecycleIdx > 0, "auto-start.ts has a DB lifecycle section");
33
-
34
- const afterDbLifecycle = src.slice(dbLifecycleIdx);
35
-
36
- // Find the second isDbAvailable check — the one AFTER the open attempts.
37
- // The first check at line ~543 tries to open the DB.
38
- // There must be a SECOND check that gates bootstrap if it's still unavailable.
39
- const firstCheck = afterDbLifecycle.indexOf("isDbAvailable()");
40
- assertTrue(firstCheck > 0, "DB lifecycle section has isDbAvailable() check");
41
-
42
- const afterFirstCheck = afterDbLifecycle.slice(firstCheck + "isDbAvailable()".length);
43
- const secondCheck = afterFirstCheck.indexOf("isDbAvailable()");
44
-
45
- assertTrue(
46
- secondCheck > 0,
47
- "auto-start.ts has a SECOND isDbAvailable() check after the open attempt — this is the gate (#2419)",
48
- );
49
-
50
- // The second check must lead to releaseLockAndReturn (abort bootstrap)
51
- if (secondCheck > 0) {
52
- const gateRegion = afterFirstCheck.slice(secondCheck, secondCheck + 500);
53
- assertTrue(
54
- gateRegion.includes("releaseLockAndReturn"),
55
- "The DB availability gate calls releaseLockAndReturn() to abort bootstrap (#2419)",
56
- );
57
- assertTrue(
58
- /database|sqlite|db.*unavailable/i.test(gateRegion),
59
- "The DB availability gate includes a user-facing error message about the database (#2419)",
60
- );
61
- }
62
-
63
- report();