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
@@ -91,140 +91,142 @@ async function loadGuidanceExport(): Promise<{ collectOneSecretWithGuidance: Fun
91
91
 
92
92
  // ─── collectSecretsFromManifest: categorization ───────────────────────────────
93
93
 
94
- test("collectSecretsFromManifest: categorizes entries — pending keys need collection, existing keys are skipped", async (t) => {
94
+ test("collectSecretsFromManifest: categorizes entries — pending keys need collection, existing keys are skipped", async () => {
95
95
  const { collectSecretsFromManifest } = await loadOrchestrator();
96
96
 
97
97
  const tmp = makeTempDir("manifest-collect");
98
98
  const savedA = process.env.EXISTING_KEY_A;
99
- t.after(() => {
100
- delete process.env.EXISTING_KEY_A;
101
- if (savedA !== undefined) process.env.EXISTING_KEY_A = savedA;
102
- rmSync(tmp, { recursive: true, force: true });
103
- });
104
-
105
- process.env.EXISTING_KEY_A = "already-set";
106
-
107
- const manifest = makeManifest([
108
- { key: "EXISTING_KEY_A", status: "pending" },
109
- { key: "PENDING_KEY_B", status: "pending", guidance: ["Step 1: Go to dashboard", "Step 2: Click create key"] },
110
- { key: "SKIPPED_KEY_C", status: "skipped" },
111
- ]);
112
- await writeManifestFile(tmp, manifest);
113
-
114
- let callIndex = 0;
115
- const mockCtx = {
116
- cwd: tmp,
117
- hasUI: true,
118
- ui: {
119
- custom: async (_factory: any) => {
120
- callIndex++;
121
- if (callIndex <= 1) return null; // summary screen dismiss
122
- return "mock-secret-value"; // collect pending key
99
+ try {
100
+ process.env.EXISTING_KEY_A = "already-set";
101
+
102
+ const manifest = makeManifest([
103
+ { key: "EXISTING_KEY_A", status: "pending" },
104
+ { key: "PENDING_KEY_B", status: "pending", guidance: ["Step 1: Go to dashboard", "Step 2: Click create key"] },
105
+ { key: "SKIPPED_KEY_C", status: "skipped" },
106
+ ]);
107
+ await writeManifestFile(tmp, manifest);
108
+
109
+ let callIndex = 0;
110
+ const mockCtx = {
111
+ cwd: tmp,
112
+ hasUI: true,
113
+ ui: {
114
+ custom: async (_factory: any) => {
115
+ callIndex++;
116
+ if (callIndex <= 1) return null; // summary screen dismiss
117
+ return "mock-secret-value"; // collect pending key
118
+ },
123
119
  },
124
- },
125
- };
120
+ };
126
121
 
127
- const result = await collectSecretsFromManifest(tmp, "M001", mockCtx as any);
122
+ const result = await collectSecretsFromManifest(tmp, "M001", mockCtx as any);
128
123
 
129
- // EXISTING_KEY_A should be in existingSkipped (it's in process.env)
130
- assert.ok(result.existingSkipped?.includes("EXISTING_KEY_A"),
131
- "EXISTING_KEY_A should be in existingSkipped");
124
+ // EXISTING_KEY_A should be in existingSkipped (it's in process.env)
125
+ assert.ok(result.existingSkipped?.includes("EXISTING_KEY_A"),
126
+ "EXISTING_KEY_A should be in existingSkipped");
132
127
 
133
- // PENDING_KEY_B should have been collected (applied)
134
- assert.ok(result.applied.includes("PENDING_KEY_B"),
135
- "PENDING_KEY_B should be in applied");
128
+ // PENDING_KEY_B should have been collected (applied)
129
+ assert.ok(result.applied.includes("PENDING_KEY_B"),
130
+ "PENDING_KEY_B should be in applied");
136
131
 
137
- // SKIPPED_KEY_C should remain skipped
138
- assert.ok(result.skipped.includes("SKIPPED_KEY_C"),
139
- "SKIPPED_KEY_C should be in skipped");
132
+ // SKIPPED_KEY_C should remain skipped
133
+ assert.ok(result.skipped.includes("SKIPPED_KEY_C"),
134
+ "SKIPPED_KEY_C should be in skipped");
135
+ } finally {
136
+ delete process.env.EXISTING_KEY_A;
137
+ if (savedA !== undefined) process.env.EXISTING_KEY_A = savedA;
138
+ rmSync(tmp, { recursive: true, force: true });
139
+ }
140
140
  });
141
141
 
142
- test("collectSecretsFromManifest: existing keys are excluded from the collection list — not prompted", async (t) => {
142
+ test("collectSecretsFromManifest: existing keys are excluded from the collection list — not prompted", async () => {
143
143
  const { collectSecretsFromManifest } = await loadOrchestrator();
144
144
 
145
145
  const tmp = makeTempDir("manifest-collect-skip");
146
146
  const savedA = process.env.ALREADY_SET_KEY;
147
- t.after(() => {
148
- delete process.env.ALREADY_SET_KEY;
149
- if (savedA !== undefined) process.env.ALREADY_SET_KEY = savedA;
150
- rmSync(tmp, { recursive: true, force: true });
151
- });
152
-
153
- process.env.ALREADY_SET_KEY = "present";
154
-
155
- const manifest = makeManifest([
156
- { key: "ALREADY_SET_KEY", status: "pending" },
157
- { key: "NEEDS_COLLECTION", status: "pending" },
158
- ]);
159
- await writeManifestFile(tmp, manifest);
160
-
161
- const collectedKeyNames: string[] = [];
162
- let summaryShown = false;
163
- const mockCtx = {
164
- cwd: tmp,
165
- hasUI: true,
166
- ui: {
167
- custom: async (factory: any) => {
168
- // Intercept the factory to check what key is being collected
169
- if (!summaryShown) {
170
- summaryShown = true;
171
- return null; // dismiss summary
172
- }
173
- collectedKeyNames.push("prompted");
174
- return "mock-value";
147
+ try {
148
+ process.env.ALREADY_SET_KEY = "present";
149
+
150
+ const manifest = makeManifest([
151
+ { key: "ALREADY_SET_KEY", status: "pending" },
152
+ { key: "NEEDS_COLLECTION", status: "pending" },
153
+ ]);
154
+ await writeManifestFile(tmp, manifest);
155
+
156
+ const collectedKeyNames: string[] = [];
157
+ let summaryShown = false;
158
+ const mockCtx = {
159
+ cwd: tmp,
160
+ hasUI: true,
161
+ ui: {
162
+ custom: async (factory: any) => {
163
+ // Intercept the factory to check what key is being collected
164
+ if (!summaryShown) {
165
+ summaryShown = true;
166
+ return null; // dismiss summary
167
+ }
168
+ collectedKeyNames.push("prompted");
169
+ return "mock-value";
170
+ },
175
171
  },
176
- },
177
- };
172
+ };
178
173
 
179
- const result = await collectSecretsFromManifest(tmp, "M001", mockCtx as any);
174
+ const result = await collectSecretsFromManifest(tmp, "M001", mockCtx as any);
180
175
 
181
- // ALREADY_SET_KEY should not have been prompted — only NEEDS_COLLECTION should
182
- assert.ok(!result.applied.includes("ALREADY_SET_KEY"),
183
- "ALREADY_SET_KEY should not be in applied (it was auto-skipped)");
184
- assert.ok(result.existingSkipped?.includes("ALREADY_SET_KEY"),
185
- "ALREADY_SET_KEY should be in existingSkipped");
176
+ // ALREADY_SET_KEY should not have been prompted — only NEEDS_COLLECTION should
177
+ assert.ok(!result.applied.includes("ALREADY_SET_KEY"),
178
+ "ALREADY_SET_KEY should not be in applied (it was auto-skipped)");
179
+ assert.ok(result.existingSkipped?.includes("ALREADY_SET_KEY"),
180
+ "ALREADY_SET_KEY should be in existingSkipped");
181
+ } finally {
182
+ delete process.env.ALREADY_SET_KEY;
183
+ if (savedA !== undefined) process.env.ALREADY_SET_KEY = savedA;
184
+ rmSync(tmp, { recursive: true, force: true });
185
+ }
186
186
  });
187
187
 
188
- test("collectSecretsFromManifest: manifest statuses are updated after collection", async (t) => {
188
+ test("collectSecretsFromManifest: manifest statuses are updated after collection", async () => {
189
189
  const { collectSecretsFromManifest } = await loadOrchestrator();
190
190
 
191
191
  const tmp = makeTempDir("manifest-update");
192
- t.after(() => rmSync(tmp, { recursive: true, force: true }));
193
-
194
- const manifest = makeManifest([
195
- { key: "KEY_TO_COLLECT", status: "pending" },
196
- { key: "KEY_TO_SKIP", status: "pending" },
197
- ]);
198
- const manifestPath = await writeManifestFile(tmp, manifest);
199
-
200
- let callIndex = 0;
201
- const mockCtx = {
202
- cwd: tmp,
203
- hasUI: true,
204
- ui: {
205
- custom: async (_factory: any) => {
206
- callIndex++;
207
- if (callIndex <= 1) return null; // summary screen dismiss
208
- if (callIndex === 2) return "secret-value"; // KEY_TO_COLLECT
209
- return null; // KEY_TO_SKIP — user skips
192
+ try {
193
+ const manifest = makeManifest([
194
+ { key: "KEY_TO_COLLECT", status: "pending" },
195
+ { key: "KEY_TO_SKIP", status: "pending" },
196
+ ]);
197
+ const manifestPath = await writeManifestFile(tmp, manifest);
198
+
199
+ let callIndex = 0;
200
+ const mockCtx = {
201
+ cwd: tmp,
202
+ hasUI: true,
203
+ ui: {
204
+ custom: async (_factory: any) => {
205
+ callIndex++;
206
+ if (callIndex <= 1) return null; // summary screen dismiss
207
+ if (callIndex === 2) return "secret-value"; // KEY_TO_COLLECT
208
+ return null; // KEY_TO_SKIP user skips
209
+ },
210
210
  },
211
- },
212
- };
211
+ };
213
212
 
214
- await collectSecretsFromManifest(tmp, "M001", mockCtx as any);
213
+ await collectSecretsFromManifest(tmp, "M001", mockCtx as any);
215
214
 
216
- // Read back the manifest file and verify statuses were updated
217
- const { parseSecretsManifest } = await loadFilesExports();
218
- const updatedContent = readFileSync(manifestPath, "utf8");
219
- const updatedManifest = parseSecretsManifest(updatedContent);
215
+ // Read back the manifest file and verify statuses were updated
216
+ const { parseSecretsManifest } = await loadFilesExports();
217
+ const updatedContent = readFileSync(manifestPath, "utf8");
218
+ const updatedManifest = parseSecretsManifest(updatedContent);
220
219
 
221
- const keyToCollect = updatedManifest.entries.find(e => e.key === "KEY_TO_COLLECT");
222
- const keyToSkip = updatedManifest.entries.find(e => e.key === "KEY_TO_SKIP");
220
+ const keyToCollect = updatedManifest.entries.find(e => e.key === "KEY_TO_COLLECT");
221
+ const keyToSkip = updatedManifest.entries.find(e => e.key === "KEY_TO_SKIP");
223
222
 
224
- assert.equal(keyToCollect?.status, "collected",
225
- "KEY_TO_COLLECT should have status 'collected' after providing a value");
226
- assert.equal(keyToSkip?.status, "skipped",
227
- "KEY_TO_SKIP should have status 'skipped' after user skipped it");
223
+ assert.equal(keyToCollect?.status, "collected",
224
+ "KEY_TO_COLLECT should have status 'collected' after providing a value");
225
+ assert.equal(keyToSkip?.status, "skipped",
226
+ "KEY_TO_SKIP should have status 'skipped' after user skipped it");
227
+ } finally {
228
+ rmSync(tmp, { recursive: true, force: true });
229
+ }
228
230
  });
229
231
 
230
232
  // ─── showSecretsSummary: render output ────────────────────────────────────────
@@ -421,47 +423,47 @@ test("collectOneSecret: no guidance provided — render output has no guidance s
421
423
 
422
424
  // ─── collectSecretsFromManifest: returns structured result ────────────────────
423
425
 
424
- test("collectSecretsFromManifest: returns result with applied, skipped, and existingSkipped arrays", async (t) => {
426
+ test("collectSecretsFromManifest: returns result with applied, skipped, and existingSkipped arrays", async () => {
425
427
  const { collectSecretsFromManifest } = await loadOrchestrator();
426
428
 
427
429
  const tmp = makeTempDir("manifest-result");
428
430
  const savedKey = process.env.RESULT_TEST_EXISTING;
429
- t.after(() => {
430
- delete process.env.RESULT_TEST_EXISTING;
431
- if (savedKey !== undefined) process.env.RESULT_TEST_EXISTING = savedKey;
432
- rmSync(tmp, { recursive: true, force: true });
433
- });
434
-
435
- process.env.RESULT_TEST_EXISTING = "already-here";
436
-
437
- const manifest = makeManifest([
438
- { key: "RESULT_TEST_EXISTING", status: "pending" },
439
- { key: "RESULT_TEST_NEW", status: "pending" },
440
- ]);
441
- await writeManifestFile(tmp, manifest);
442
-
443
- let callIndex = 0;
444
- const mockCtx = {
445
- cwd: tmp,
446
- hasUI: true,
447
- ui: {
448
- custom: async (_factory: any) => {
449
- callIndex++;
450
- if (callIndex <= 1) return null; // summary dismiss
451
- return "secret-value"; // collect the pending key
431
+ try {
432
+ process.env.RESULT_TEST_EXISTING = "already-here";
433
+
434
+ const manifest = makeManifest([
435
+ { key: "RESULT_TEST_EXISTING", status: "pending" },
436
+ { key: "RESULT_TEST_NEW", status: "pending" },
437
+ ]);
438
+ await writeManifestFile(tmp, manifest);
439
+
440
+ let callIndex = 0;
441
+ const mockCtx = {
442
+ cwd: tmp,
443
+ hasUI: true,
444
+ ui: {
445
+ custom: async (_factory: any) => {
446
+ callIndex++;
447
+ if (callIndex <= 1) return null; // summary dismiss
448
+ return "secret-value"; // collect the pending key
449
+ },
452
450
  },
453
- },
454
- };
451
+ };
455
452
 
456
- const result = await collectSecretsFromManifest(tmp, "M001", mockCtx as any);
453
+ const result = await collectSecretsFromManifest(tmp, "M001", mockCtx as any);
457
454
 
458
- // Verify result shape
459
- assert.ok(Array.isArray(result.applied), "result should have applied array");
460
- assert.ok(Array.isArray(result.skipped), "result should have skipped array");
461
- assert.ok(Array.isArray(result.existingSkipped), "result should have existingSkipped array");
455
+ // Verify result shape
456
+ assert.ok(Array.isArray(result.applied), "result should have applied array");
457
+ assert.ok(Array.isArray(result.skipped), "result should have skipped array");
458
+ assert.ok(Array.isArray(result.existingSkipped), "result should have existingSkipped array");
462
459
 
463
- assert.ok(result.existingSkipped.includes("RESULT_TEST_EXISTING"),
464
- "existing key should be in existingSkipped");
465
- assert.ok(result.applied.includes("RESULT_TEST_NEW"),
466
- "collected key should be in applied");
460
+ assert.ok(result.existingSkipped.includes("RESULT_TEST_EXISTING"),
461
+ "existing key should be in existingSkipped");
462
+ assert.ok(result.applied.includes("RESULT_TEST_NEW"),
463
+ "collected key should be in applied");
464
+ } finally {
465
+ delete process.env.RESULT_TEST_EXISTING;
466
+ if (savedKey !== undefined) process.env.RESULT_TEST_EXISTING = savedKey;
467
+ rmSync(tmp, { recursive: true, force: true });
468
+ }
467
469
  });
@@ -7,40 +7,40 @@ import fs from "node:fs";
7
7
  import { handleInspect } from "../commands-inspect.ts";
8
8
  import { closeDatabase, openDatabase } from "../gsd-db.ts";
9
9
 
10
- test("/gsd inspect opens existing database when it was not yet opened in session", async (t) => {
10
+ test("/gsd inspect opens existing database when it was not yet opened in session", async () => {
11
11
  closeDatabase();
12
12
 
13
13
  const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-inspect-db-"));
14
14
  const prevCwd = process.cwd();
15
15
 
16
- t.after(() => {
17
- process.chdir(prevCwd);
18
- closeDatabase();
19
- fs.rmSync(tmp, { recursive: true, force: true });
20
- });
16
+ try {
17
+ const gsdDir = path.join(tmp, ".gsd");
18
+ fs.mkdirSync(gsdDir, { recursive: true });
19
+ const dbPath = path.join(gsdDir, "gsd.db");
21
20
 
22
- const gsdDir = path.join(tmp, ".gsd");
23
- fs.mkdirSync(gsdDir, { recursive: true });
24
- const dbPath = path.join(gsdDir, "gsd.db");
25
-
26
- assert.equal(openDatabase(dbPath), true);
27
- closeDatabase();
21
+ assert.equal(openDatabase(dbPath), true);
22
+ closeDatabase();
28
23
 
29
- process.chdir(tmp);
24
+ process.chdir(tmp);
30
25
 
31
- const notifications: Array<{ message: string; level: string }> = [];
32
- const ctx = {
33
- ui: {
34
- notify(message: string, level: string) {
35
- notifications.push({ message, level });
26
+ const notifications: Array<{ message: string; level: string }> = [];
27
+ const ctx = {
28
+ ui: {
29
+ notify(message: string, level: string) {
30
+ notifications.push({ message, level });
31
+ },
36
32
  },
37
- },
38
- } as any;
33
+ } as any;
39
34
 
40
- await handleInspect(ctx);
35
+ await handleInspect(ctx);
41
36
 
42
- assert.equal(notifications.length, 1);
43
- assert.equal(notifications[0].level, "info");
44
- assert.match(notifications[0].message, /=== GSD Database Inspect ===/);
45
- assert.doesNotMatch(notifications[0].message, /No GSD database available/);
37
+ assert.equal(notifications.length, 1);
38
+ assert.equal(notifications[0].level, "info");
39
+ assert.match(notifications[0].message, /=== GSD Database Inspect ===/);
40
+ assert.doesNotMatch(notifications[0].message, /No GSD database available/);
41
+ } finally {
42
+ process.chdir(prevCwd);
43
+ closeDatabase();
44
+ fs.rmSync(tmp, { recursive: true, force: true });
45
+ }
46
46
  });
@@ -42,22 +42,22 @@ function writeDebugLog(dir: string, name: string, entries: Record<string, unknow
42
42
 
43
43
  // ─── Tests ──────────────────────────────────────────────────────────────────
44
44
 
45
- test("logs shows empty state message when no logs exist", async (t) => {
45
+ test("logs shows empty state message when no logs exist", async () => {
46
46
  const dir = createTestDir();
47
47
  const ctx = createMockCtx();
48
48
  const origCwd = process.cwd();
49
49
  process.chdir(dir);
50
- t.after(() => {
50
+ try {
51
+ await handleLogs("", ctx as any);
52
+ assert.equal(ctx.notifications.length, 1);
53
+ assert.ok(ctx.notifications[0].msg.includes("No logs found"));
54
+ } finally {
51
55
  process.chdir(origCwd);
52
56
  rmSync(dir, { recursive: true, force: true });
53
- });
54
-
55
- await handleLogs("", ctx as any);
56
- assert.equal(ctx.notifications.length, 1);
57
- assert.ok(ctx.notifications[0].msg.includes("No logs found"));
57
+ }
58
58
  });
59
59
 
60
- test("logs lists activity logs", async (t) => {
60
+ test("logs lists activity logs", async () => {
61
61
  const dir = createTestDir();
62
62
  const ctx = createMockCtx();
63
63
  const origCwd = process.cwd();
@@ -71,21 +71,21 @@ test("logs lists activity logs", async (t) => {
71
71
  { role: "assistant", content: "Completing slice S01" },
72
72
  ]);
73
73
 
74
- t.after(() => {
74
+ try {
75
+ await handleLogs("", ctx as any);
76
+ assert.equal(ctx.notifications.length, 1);
77
+ const msg = ctx.notifications[0].msg;
78
+ assert.ok(msg.includes("Activity Logs"), "should show activity logs header");
79
+ assert.ok(msg.includes("execute-task"), "should show unit type");
80
+ assert.ok(msg.includes("complete-slice"), "should show second log");
81
+ assert.ok(msg.includes("/gsd logs <#>"), "should show usage hint");
82
+ } finally {
75
83
  process.chdir(origCwd);
76
84
  rmSync(dir, { recursive: true, force: true });
77
- });
78
-
79
- await handleLogs("", ctx as any);
80
- assert.equal(ctx.notifications.length, 1);
81
- const msg = ctx.notifications[0].msg;
82
- assert.ok(msg.includes("Activity Logs"), "should show activity logs header");
83
- assert.ok(msg.includes("execute-task"), "should show unit type");
84
- assert.ok(msg.includes("complete-slice"), "should show second log");
85
- assert.ok(msg.includes("/gsd logs <#>"), "should show usage hint");
85
+ }
86
86
  });
87
87
 
88
- test("logs <N> shows activity log details", async (t) => {
88
+ test("logs <N> shows activity log details", async () => {
89
89
  const dir = createTestDir();
90
90
  const ctx = createMockCtx();
91
91
  const origCwd = process.cwd();
@@ -99,40 +99,40 @@ test("logs <N> shows activity log details", async (t) => {
99
99
  { role: "assistant", content: "I ran the tests and wrote a file" },
100
100
  ]);
101
101
 
102
- t.after(() => {
102
+ try {
103
+ await handleLogs("1", ctx as any);
104
+ assert.equal(ctx.notifications.length, 1);
105
+ const msg = ctx.notifications[0].msg;
106
+ assert.ok(msg.includes("Activity Log #1"), "should show log number");
107
+ assert.ok(msg.includes("execute-task"), "should show unit type");
108
+ assert.ok(msg.includes("Tool calls: 2"), "should count tool calls");
109
+ assert.ok(msg.includes("Errors: 1"), "should count errors");
110
+ assert.ok(msg.includes("/tmp/test.ts"), "should show files written");
111
+ assert.ok(msg.includes("npm test"), "should show commands run");
112
+ } finally {
103
113
  process.chdir(origCwd);
104
114
  rmSync(dir, { recursive: true, force: true });
105
- });
106
-
107
- await handleLogs("1", ctx as any);
108
- assert.equal(ctx.notifications.length, 1);
109
- const msg = ctx.notifications[0].msg;
110
- assert.ok(msg.includes("Activity Log #1"), "should show log number");
111
- assert.ok(msg.includes("execute-task"), "should show unit type");
112
- assert.ok(msg.includes("Tool calls: 2"), "should count tool calls");
113
- assert.ok(msg.includes("Errors: 1"), "should count errors");
114
- assert.ok(msg.includes("/tmp/test.ts"), "should show files written");
115
- assert.ok(msg.includes("npm test"), "should show commands run");
115
+ }
116
116
  });
117
117
 
118
- test("logs <N> shows not found for invalid seq", async (t) => {
118
+ test("logs <N> shows not found for invalid seq", async () => {
119
119
  const dir = createTestDir();
120
120
  const ctx = createMockCtx();
121
121
  const origCwd = process.cwd();
122
122
  process.chdir(dir);
123
123
 
124
- t.after(() => {
124
+ try {
125
+ await handleLogs("999", ctx as any);
126
+ assert.equal(ctx.notifications.length, 1);
127
+ assert.ok(ctx.notifications[0].msg.includes("not found"));
128
+ assert.equal(ctx.notifications[0].level, "warning");
129
+ } finally {
125
130
  process.chdir(origCwd);
126
131
  rmSync(dir, { recursive: true, force: true });
127
- });
128
-
129
- await handleLogs("999", ctx as any);
130
- assert.equal(ctx.notifications.length, 1);
131
- assert.ok(ctx.notifications[0].msg.includes("not found"));
132
- assert.equal(ctx.notifications[0].level, "warning");
132
+ }
133
133
  });
134
134
 
135
- test("logs debug lists debug logs", async (t) => {
135
+ test("logs debug lists debug logs", async () => {
136
136
  const dir = createTestDir();
137
137
  const ctx = createMockCtx();
138
138
  const origCwd = process.cwd();
@@ -143,19 +143,19 @@ test("logs debug lists debug logs", async (t) => {
143
143
  { ts: "2026-03-18T10:35:00Z", event: "debug-summary", dispatches: 5 },
144
144
  ]);
145
145
 
146
- t.after(() => {
146
+ try {
147
+ await handleLogs("debug", ctx as any);
148
+ assert.equal(ctx.notifications.length, 1);
149
+ const msg = ctx.notifications[0].msg;
150
+ assert.ok(msg.includes("Debug Logs"), "should show debug logs header");
151
+ assert.ok(msg.includes("debug-2026-03-18T10-30-00.log"), "should show filename");
152
+ } finally {
147
153
  process.chdir(origCwd);
148
154
  rmSync(dir, { recursive: true, force: true });
149
- });
150
-
151
- await handleLogs("debug", ctx as any);
152
- assert.equal(ctx.notifications.length, 1);
153
- const msg = ctx.notifications[0].msg;
154
- assert.ok(msg.includes("Debug Logs"), "should show debug logs header");
155
- assert.ok(msg.includes("debug-2026-03-18T10-30-00.log"), "should show filename");
155
+ }
156
156
  });
157
157
 
158
- test("logs debug <N> shows debug log summary", async (t) => {
158
+ test("logs debug <N> shows debug log summary", async () => {
159
159
  const dir = createTestDir();
160
160
  const ctx = createMockCtx();
161
161
  const origCwd = process.cwd();
@@ -167,21 +167,21 @@ test("logs debug <N> shows debug log summary", async (t) => {
167
167
  { ts: "2026-03-18T10:35:00Z", event: "debug-summary", dispatches: 5 },
168
168
  ]);
169
169
 
170
- t.after(() => {
170
+ try {
171
+ await handleLogs("debug 1", ctx as any);
172
+ assert.equal(ctx.notifications.length, 1);
173
+ const msg = ctx.notifications[0].msg;
174
+ assert.ok(msg.includes("Debug Log:"), "should show debug log header");
175
+ assert.ok(msg.includes("Events: 3"), "should count events");
176
+ assert.ok(msg.includes("Dispatches: 5"), "should show dispatch count");
177
+ assert.ok(msg.includes("dispatch-error"), "should show errors");
178
+ } finally {
171
179
  process.chdir(origCwd);
172
180
  rmSync(dir, { recursive: true, force: true });
173
- });
174
-
175
- await handleLogs("debug 1", ctx as any);
176
- assert.equal(ctx.notifications.length, 1);
177
- const msg = ctx.notifications[0].msg;
178
- assert.ok(msg.includes("Debug Log:"), "should show debug log header");
179
- assert.ok(msg.includes("Events: 3"), "should count events");
180
- assert.ok(msg.includes("Dispatches: 5"), "should show dispatch count");
181
- assert.ok(msg.includes("dispatch-error"), "should show errors");
181
+ }
182
182
  });
183
183
 
184
- test("logs tail shows recent activity summaries", async (t) => {
184
+ test("logs tail shows recent activity summaries", async () => {
185
185
  const dir = createTestDir();
186
186
  const ctx = createMockCtx();
187
187
  const origCwd = process.cwd();
@@ -195,20 +195,20 @@ test("logs tail shows recent activity summaries", async (t) => {
195
195
  { role: "toolResult", toolCallId: "1", toolName: "bash", isError: true },
196
196
  ]);
197
197
 
198
- t.after(() => {
198
+ try {
199
+ await handleLogs("tail 2", ctx as any);
200
+ assert.equal(ctx.notifications.length, 1);
201
+ const msg = ctx.notifications[0].msg;
202
+ assert.ok(msg.includes("Last 2 activity log(s)"), "should show count");
203
+ assert.ok(msg.includes("#1"), "should show first log");
204
+ assert.ok(msg.includes("#2"), "should show second log");
205
+ } finally {
199
206
  process.chdir(origCwd);
200
207
  rmSync(dir, { recursive: true, force: true });
201
- });
202
-
203
- await handleLogs("tail 2", ctx as any);
204
- assert.equal(ctx.notifications.length, 1);
205
- const msg = ctx.notifications[0].msg;
206
- assert.ok(msg.includes("Last 2 activity log(s)"), "should show count");
207
- assert.ok(msg.includes("#1"), "should show first log");
208
- assert.ok(msg.includes("#2"), "should show second log");
208
+ }
209
209
  });
210
210
 
211
- test("logs clear removes old logs", async (t) => {
211
+ test("logs clear removes old logs", async () => {
212
212
  const dir = createTestDir();
213
213
  const ctx = createMockCtx();
214
214
  const origCwd = process.cwd();
@@ -225,17 +225,17 @@ test("logs clear removes old logs", async (t) => {
225
225
  writeActivityLog(dir, i, "execute-task", `M001/S01/T0${i}`, [{ type: "toolCall" }]);
226
226
  }
227
227
 
228
- t.after(() => {
228
+ try {
229
+ await handleLogs("clear", ctx as any);
230
+ assert.equal(ctx.notifications.length, 1);
231
+ // Old log should be removed, recent ones kept
232
+ assert.ok(!existsSync(oldFile), "old log should be removed");
233
+ assert.ok(
234
+ existsSync(join(dir, ".gsd", "activity", "007-execute-task-M001-S01-T07.jsonl")),
235
+ "most recent log should be kept",
236
+ );
237
+ } finally {
229
238
  process.chdir(origCwd);
230
239
  rmSync(dir, { recursive: true, force: true });
231
- });
232
-
233
- await handleLogs("clear", ctx as any);
234
- assert.equal(ctx.notifications.length, 1);
235
- // Old log should be removed, recent ones kept
236
- assert.ok(!existsSync(oldFile), "old log should be removed");
237
- assert.ok(
238
- existsSync(join(dir, ".gsd", "activity", "007-execute-task-M001-S01-T07.jsonl")),
239
- "most recent log should be kept",
240
- );
240
+ }
241
241
  });