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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (399) hide show
  1. package/README.md +30 -12
  2. package/dist/cli.js +13 -1
  3. package/dist/help-text.js +24 -0
  4. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +21 -8
  5. package/dist/resources/extensions/gsd/auto-prompts.js +130 -51
  6. package/dist/resources/extensions/gsd/auto-start.js +10 -0
  7. package/dist/resources/extensions/gsd/auto-worktree.js +16 -2
  8. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  9. package/dist/resources/extensions/gsd/dispatch-guard.js +34 -10
  10. package/dist/resources/extensions/gsd/markdown-renderer.js +7 -5
  11. package/dist/resources/extensions/gsd/reactive-graph.js +13 -2
  12. package/dist/resources/extensions/gsd/skill-health.js +3 -1
  13. package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -11
  14. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -10
  15. package/dist/resources/extensions/gsd/visualizer-data.js +45 -13
  16. package/dist/resources/extensions/gsd/workspace-index.js +46 -15
  17. package/dist/web/standalone/.next/BUILD_ID +1 -1
  18. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
  19. package/dist/web/standalone/.next/build-manifest.json +3 -3
  20. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  21. package/dist/web/standalone/.next/required-server-files.json +4 -4
  22. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  23. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  25. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  33. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  34. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  35. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  37. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  39. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  49. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  87. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  93. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  109. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  111. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  113. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/index.html +1 -1
  123. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  124. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  125. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  126. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  128. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/page.js +2 -2
  130. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
  132. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  133. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  134. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/middleware.js +2 -2
  136. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  138. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  139. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  140. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  141. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  142. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  143. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  144. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  145. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  146. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  147. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  148. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  149. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  150. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  151. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  152. package/dist/web/standalone/server.js +1 -1
  153. package/package.json +4 -4
  154. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +3 -3
  155. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -34
  157. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  159. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
  161. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  162. package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
  164. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
  167. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  168. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  169. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  170. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  171. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  172. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  173. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  174. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  175. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  176. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
  177. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  178. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
  180. package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
  181. package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
  183. package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  185. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
  187. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
  188. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
  189. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
  190. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
  191. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
  192. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
  193. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
  194. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
  195. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  197. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
  199. package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
  201. package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
  202. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
  203. package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
  204. package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
  205. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
  206. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  207. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  209. package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
  210. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  211. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  212. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  213. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  214. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/index.d.ts +3 -1
  216. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  217. package/packages/pi-coding-agent/dist/index.js +1 -0
  218. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  220. package/packages/pi-coding-agent/dist/main.js +11 -199
  221. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  222. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  223. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  224. package/packages/pi-coding-agent/package.json +1 -1
  225. package/packages/pi-coding-agent/src/core/agent-session.ts +13 -37
  226. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  227. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
  228. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
  229. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
  230. package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
  231. package/packages/pi-coding-agent/src/core/extensions/loader.ts +23 -0
  232. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  233. package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
  234. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
  235. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
  236. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  237. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
  238. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
  239. package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
  240. package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
  241. package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
  242. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  243. package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
  244. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  245. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  246. package/packages/pi-coding-agent/src/index.ts +7 -0
  247. package/packages/pi-coding-agent/src/main.ts +11 -232
  248. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  249. package/pkg/package.json +1 -1
  250. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +22 -7
  251. package/src/resources/extensions/gsd/auto-prompts.ts +109 -42
  252. package/src/resources/extensions/gsd/auto-start.ts +14 -0
  253. package/src/resources/extensions/gsd/auto-worktree.ts +16 -3
  254. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  255. package/src/resources/extensions/gsd/dispatch-guard.ts +28 -10
  256. package/src/resources/extensions/gsd/markdown-renderer.ts +7 -5
  257. package/src/resources/extensions/gsd/reactive-graph.ts +12 -2
  258. package/src/resources/extensions/gsd/skill-health.ts +2 -1
  259. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  260. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  261. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  262. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  263. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  264. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  265. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  266. package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +3 -3
  267. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  268. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  269. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  270. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  271. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  272. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  273. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  274. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  275. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  276. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  277. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  278. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  279. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  280. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  281. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  282. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  283. package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
  284. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  285. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  286. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +152 -183
  287. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  288. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  289. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  290. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  291. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  292. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  293. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  294. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  295. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  296. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  297. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  298. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  299. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  300. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  301. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  302. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  303. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  304. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  305. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  306. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  307. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  308. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  309. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  310. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  311. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  312. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  313. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  314. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  315. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  316. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  317. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  318. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  319. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  320. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  321. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  322. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  323. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  324. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  325. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  326. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  327. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  328. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  329. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  330. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  331. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  332. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  333. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  334. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  335. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  336. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  337. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  338. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  339. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  340. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  341. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  342. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  343. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  344. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  345. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  346. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  347. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  348. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  349. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  350. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  351. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  352. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  353. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  354. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  355. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  356. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  357. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  358. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  359. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  360. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  361. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  362. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  363. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  364. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  365. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  366. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  367. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  368. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  369. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  370. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  371. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +9 -11
  372. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  373. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  374. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  375. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  376. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  377. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  378. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  379. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  380. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  381. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  382. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  383. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  384. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  385. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  386. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  387. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  388. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  389. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  390. package/src/resources/extensions/gsd/tools/plan-milestone.ts +1 -18
  391. package/src/resources/extensions/gsd/tools/plan-slice.ts +1 -15
  392. package/src/resources/extensions/gsd/visualizer-data.ts +46 -14
  393. package/src/resources/extensions/gsd/workspace-index.ts +49 -18
  394. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  395. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  396. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  397. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  398. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_buildManifest.js +0 -0
  399. /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
@@ -1,15 +1,14 @@
1
1
  // GSD Extension - Override Tests
2
2
  // Tests for parseOverrides, appendOverride, loadActiveOverrides, formatOverridesSection, resolveAllOverrides
3
3
 
4
+ import { describe, test, afterEach } from 'node:test';
5
+ import assert from 'node:assert/strict';
4
6
  import { mkdtempSync, mkdirSync, readFileSync, writeFileSync, rmSync } from "node:fs";
5
7
  import { join } from "node:path";
6
8
  import { tmpdir } from "node:os";
7
- import { createTestContext } from './test-helpers.ts';
8
9
  import { parseOverrides, appendOverride, loadActiveOverrides, formatOverridesSection, resolveAllOverrides } from '../files.ts';
9
10
  import type { Override } from '../files.ts';
10
11
 
11
- const { assertEq, assertTrue, assertMatch, assertNoMatch, report } = createTestContext();
12
-
13
12
  const tempDirs: string[] = [];
14
13
 
15
14
  function makeTempDir(prefix: string): string {
@@ -26,106 +25,100 @@ function cleanup(): void {
26
25
  tempDirs.length = 0;
27
26
  }
28
27
 
29
- console.log('\n=== parseOverrides: empty content ===');
30
- { const result = parseOverrides(""); assertEq(result.length, 0, "empty content returns no overrides"); }
31
-
32
- console.log('\n=== parseOverrides: single active override ===');
33
- {
34
- const content = `# GSD Overrides\n\nUser-issued overrides that supersede plan document content.\n\n---\n\n## Override: 2026-03-14T10:00:00.000Z\n\n**Change:** Use Postgres instead of SQLite\n**Scope:** active\n**Applied-at:** M001/S02/T03\n\n---\n`;
35
- const result = parseOverrides(content);
36
- assertEq(result.length, 1, "parses one override");
37
- assertEq(result[0].timestamp, "2026-03-14T10:00:00.000Z", "correct timestamp");
38
- assertEq(result[0].change, "Use Postgres instead of SQLite", "correct change");
39
- assertEq(result[0].scope, "active", "correct scope");
40
- assertEq(result[0].appliedAt, "M001/S02/T03", "correct appliedAt");
41
- }
42
-
43
- console.log('\n=== parseOverrides: multiple overrides, mixed scopes ===');
44
- {
45
- const content = `# GSD Overrides\n\n---\n\n## Override: 2026-03-14T10:00:00.000Z\n\n**Change:** Use Postgres instead of SQLite\n**Scope:** resolved\n**Applied-at:** M001/S02/T03\n\n---\n\n## Override: 2026-03-14T11:00:00.000Z\n\n**Change:** Use JWT instead of session cookies\n**Scope:** active\n**Applied-at:** M001/S03/T01\n\n---\n`;
46
- const result = parseOverrides(content);
47
- assertEq(result.length, 2, "parses two overrides");
48
- assertEq(result[0].scope, "resolved", "first is resolved");
49
- assertEq(result[1].scope, "active", "second is active");
50
- assertEq(result[1].change, "Use JWT instead of session cookies", "second change text");
51
- }
52
-
53
- console.log('\n=== appendOverride: creates new file ===');
54
- {
55
- const tmp = makeTempDir("append-new");
56
- await appendOverride(tmp, "Use Postgres", "M001/S01/T01");
57
- const content = readFileSync(join(tmp, ".gsd", "OVERRIDES.md"), "utf-8");
58
- assertTrue(content.includes("# GSD Overrides"), "has header");
59
- assertTrue(content.includes("**Change:** Use Postgres"), "has change");
60
- assertTrue(content.includes("**Scope:** active"), "has active scope");
61
- assertTrue(content.includes("**Applied-at:** M001/S01/T01"), "has appliedAt");
62
- }
63
-
64
- console.log('\n=== appendOverride: appends to existing file ===');
65
- {
66
- const tmp = makeTempDir("append-existing");
67
- await appendOverride(tmp, "First override", "M001/S01/T01");
68
- await appendOverride(tmp, "Second override", "M001/S02/T02");
69
- const content = readFileSync(join(tmp, ".gsd", "OVERRIDES.md"), "utf-8");
70
- assertTrue(content.includes("**Change:** First override"), "has first override");
71
- assertTrue(content.includes("**Change:** Second override"), "has second override");
72
- const parsed = parseOverrides(content);
73
- assertEq(parsed.length, 2, "two overrides in file");
74
- }
75
-
76
- console.log('\n=== loadActiveOverrides: no file ===');
77
- {
78
- const tmp = makeTempDir("load-no-file");
79
- const result = await loadActiveOverrides(tmp);
80
- assertEq(result.length, 0, "returns empty when no file");
81
- }
82
-
83
- console.log('\n=== loadActiveOverrides: filters to active only ===');
84
- {
85
- const tmp = makeTempDir("load-filter");
86
- const content = `# GSD Overrides\n\n---\n\n## Override: 2026-03-14T10:00:00.000Z\n\n**Change:** Resolved change\n**Scope:** resolved\n**Applied-at:** M001/S01/T01\n\n---\n\n## Override: 2026-03-14T11:00:00.000Z\n\n**Change:** Active change\n**Scope:** active\n**Applied-at:** M001/S02/T01\n\n---\n`;
87
- writeFileSync(join(tmp, ".gsd", "OVERRIDES.md"), content, "utf-8");
88
- const result = await loadActiveOverrides(tmp);
89
- assertEq(result.length, 1, "only one active override");
90
- assertEq(result[0].change, "Active change", "correct active change");
91
- }
92
-
93
- console.log('\n=== formatOverridesSection: empty array ===');
94
- { const result = formatOverridesSection([]); assertEq(result, "", "empty overrides returns empty string"); }
95
-
96
- console.log('\n=== formatOverridesSection: formats section ===');
97
- {
98
- const overrides: Override[] = [
99
- { timestamp: "2026-03-14T10:00:00.000Z", change: "Use Postgres", scope: "active", appliedAt: "M001/S01/T01" },
100
- ];
101
- const result = formatOverridesSection(overrides);
102
- assertTrue(result.includes("## Active Overrides (supersede plan content)"), "has header");
103
- assertTrue(result.includes("**Use Postgres**"), "has change text");
104
- assertTrue(result.includes("supersede any conflicting content"), "has instruction");
105
- }
106
-
107
- console.log('\n=== resolveAllOverrides: marks all as resolved ===');
108
- {
109
- const tmp = makeTempDir("resolve-all");
110
- await appendOverride(tmp, "First", "M001/S01/T01");
111
- await appendOverride(tmp, "Second", "M001/S02/T01");
112
- let active = await loadActiveOverrides(tmp);
113
- assertEq(active.length, 2, "two active before resolve");
114
- await resolveAllOverrides(tmp);
115
- active = await loadActiveOverrides(tmp);
116
- assertEq(active.length, 0, "no active after resolve");
117
- const content = readFileSync(join(tmp, ".gsd", "OVERRIDES.md"), "utf-8");
118
- const allOverrides = parseOverrides(content);
119
- assertEq(allOverrides.length, 2, "still two overrides total");
120
- assertTrue(allOverrides.every(o => o.scope === "resolved"), "all resolved");
121
- }
122
-
123
- console.log('\n=== resolveAllOverrides: no file no error ===');
124
- {
125
- const tmp = makeTempDir("resolve-no-file");
126
- await resolveAllOverrides(tmp);
127
- assertTrue(true, "resolveAllOverrides with no file does not throw");
128
- }
129
-
130
- cleanup();
131
- report();
28
+ describe('overrides', () => {
29
+ afterEach(() => cleanup());
30
+
31
+ test('parseOverrides: empty content', () => {
32
+ const result = parseOverrides(""); assert.deepStrictEqual(result.length, 0, "empty content returns no overrides");
33
+ });
34
+
35
+ test('parseOverrides: single active override', () => {
36
+ const content = `# GSD Overrides\n\nUser-issued overrides that supersede plan document content.\n\n---\n\n## Override: 2026-03-14T10:00:00.000Z\n\n**Change:** Use Postgres instead of SQLite\n**Scope:** active\n**Applied-at:** M001/S02/T03\n\n---\n`;
37
+ const result = parseOverrides(content);
38
+ assert.deepStrictEqual(result.length, 1, "parses one override");
39
+ assert.deepStrictEqual(result[0].timestamp, "2026-03-14T10:00:00.000Z", "correct timestamp");
40
+ assert.deepStrictEqual(result[0].change, "Use Postgres instead of SQLite", "correct change");
41
+ assert.deepStrictEqual(result[0].scope, "active", "correct scope");
42
+ assert.deepStrictEqual(result[0].appliedAt, "M001/S02/T03", "correct appliedAt");
43
+ });
44
+
45
+ test('parseOverrides: multiple overrides, mixed scopes', () => {
46
+ const content = `# GSD Overrides\n\n---\n\n## Override: 2026-03-14T10:00:00.000Z\n\n**Change:** Use Postgres instead of SQLite\n**Scope:** resolved\n**Applied-at:** M001/S02/T03\n\n---\n\n## Override: 2026-03-14T11:00:00.000Z\n\n**Change:** Use JWT instead of session cookies\n**Scope:** active\n**Applied-at:** M001/S03/T01\n\n---\n`;
47
+ const result = parseOverrides(content);
48
+ assert.deepStrictEqual(result.length, 2, "parses two overrides");
49
+ assert.deepStrictEqual(result[0].scope, "resolved", "first is resolved");
50
+ assert.deepStrictEqual(result[1].scope, "active", "second is active");
51
+ assert.deepStrictEqual(result[1].change, "Use JWT instead of session cookies", "second change text");
52
+ });
53
+
54
+ test('appendOverride: creates new file', async () => {
55
+ const tmp = makeTempDir("append-new");
56
+ await appendOverride(tmp, "Use Postgres", "M001/S01/T01");
57
+ const content = readFileSync(join(tmp, ".gsd", "OVERRIDES.md"), "utf-8");
58
+ assert.ok(content.includes("# GSD Overrides"), "has header");
59
+ assert.ok(content.includes("**Change:** Use Postgres"), "has change");
60
+ assert.ok(content.includes("**Scope:** active"), "has active scope");
61
+ assert.ok(content.includes("**Applied-at:** M001/S01/T01"), "has appliedAt");
62
+ });
63
+
64
+ test('appendOverride: appends to existing file', async () => {
65
+ const tmp = makeTempDir("append-existing");
66
+ await appendOverride(tmp, "First override", "M001/S01/T01");
67
+ await appendOverride(tmp, "Second override", "M001/S02/T02");
68
+ const content = readFileSync(join(tmp, ".gsd", "OVERRIDES.md"), "utf-8");
69
+ assert.ok(content.includes("**Change:** First override"), "has first override");
70
+ assert.ok(content.includes("**Change:** Second override"), "has second override");
71
+ const parsed = parseOverrides(content);
72
+ assert.deepStrictEqual(parsed.length, 2, "two overrides in file");
73
+ });
74
+
75
+ test('loadActiveOverrides: no file', async () => {
76
+ const tmp = makeTempDir("load-no-file");
77
+ const result = await loadActiveOverrides(tmp);
78
+ assert.deepStrictEqual(result.length, 0, "returns empty when no file");
79
+ });
80
+
81
+ test('loadActiveOverrides: filters to active only', async () => {
82
+ const tmp = makeTempDir("load-filter");
83
+ const content = `# GSD Overrides\n\n---\n\n## Override: 2026-03-14T10:00:00.000Z\n\n**Change:** Resolved change\n**Scope:** resolved\n**Applied-at:** M001/S01/T01\n\n---\n\n## Override: 2026-03-14T11:00:00.000Z\n\n**Change:** Active change\n**Scope:** active\n**Applied-at:** M001/S02/T01\n\n---\n`;
84
+ writeFileSync(join(tmp, ".gsd", "OVERRIDES.md"), content, "utf-8");
85
+ const result = await loadActiveOverrides(tmp);
86
+ assert.deepStrictEqual(result.length, 1, "only one active override");
87
+ assert.deepStrictEqual(result[0].change, "Active change", "correct active change");
88
+ });
89
+
90
+ test('formatOverridesSection: empty array', () => {
91
+ const result = formatOverridesSection([]); assert.deepStrictEqual(result, "", "empty overrides returns empty string");
92
+ });
93
+
94
+ test('formatOverridesSection: formats section', () => {
95
+ const overrides: Override[] = [
96
+ { timestamp: "2026-03-14T10:00:00.000Z", change: "Use Postgres", scope: "active", appliedAt: "M001/S01/T01" },
97
+ ];
98
+ const result = formatOverridesSection(overrides);
99
+ assert.ok(result.includes("## Active Overrides (supersede plan content)"), "has header");
100
+ assert.ok(result.includes("**Use Postgres**"), "has change text");
101
+ assert.ok(result.includes("supersede any conflicting content"), "has instruction");
102
+ });
103
+
104
+ test('resolveAllOverrides: marks all as resolved', async () => {
105
+ const tmp = makeTempDir("resolve-all");
106
+ await appendOverride(tmp, "First", "M001/S01/T01");
107
+ await appendOverride(tmp, "Second", "M001/S02/T01");
108
+ let active = await loadActiveOverrides(tmp);
109
+ assert.deepStrictEqual(active.length, 2, "two active before resolve");
110
+ await resolveAllOverrides(tmp);
111
+ active = await loadActiveOverrides(tmp);
112
+ assert.deepStrictEqual(active.length, 0, "no active after resolve");
113
+ const content = readFileSync(join(tmp, ".gsd", "OVERRIDES.md"), "utf-8");
114
+ const allOverrides = parseOverrides(content);
115
+ assert.deepStrictEqual(allOverrides.length, 2, "still two overrides total");
116
+ assert.ok(allOverrides.every(o => o.scope === "resolved"), "all resolved");
117
+ });
118
+
119
+ test('resolveAllOverrides: no file no error', async () => {
120
+ const tmp = makeTempDir("resolve-no-file");
121
+ await resolveAllOverrides(tmp);
122
+ assert.ok(true, "resolveAllOverrides with no file does not throw");
123
+ });
124
+ });
@@ -5,6 +5,8 @@
5
5
  * restored after a coordinator crash, with PID liveness filtering.
6
6
  */
7
7
 
8
+ import { describe, test } from 'node:test';
9
+ import assert from 'node:assert/strict';
8
10
  import {
9
11
  mkdtempSync,
10
12
  mkdirSync,
@@ -24,10 +26,6 @@ import {
24
26
  type PersistedState,
25
27
  } from "../parallel-orchestrator.ts";
26
28
  import { writeSessionStatus, readAllSessionStatuses, removeSessionStatus } from "../session-status-io.ts";
27
- import { createTestContext } from './test-helpers.ts';
28
-
29
- const { assertEq, assertTrue, report } = createTestContext();
30
-
31
29
  // ─── Helpers ──────────────────────────────────────────────────────────────────
32
30
 
33
31
  function makeTempDir(): string {
@@ -57,8 +55,9 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
57
55
 
58
56
  // ─── Tests ────────────────────────────────────────────────────────────────────
59
57
 
60
- // Test 1: persistState writes valid JSON
61
- {
58
+
59
+ describe('parallel-crash-recovery', () => {
60
+ test('Test 1: persistState writes valid JSON', () => {
62
61
  const basePath = makeTempDir();
63
62
  try {
64
63
  // We can't call persistState directly without internal state set up,
@@ -82,29 +81,27 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
82
81
 
83
82
  const raw = readFileSync(stateFilePath(basePath), "utf-8");
84
83
  const parsed = JSON.parse(raw) as PersistedState;
85
- assertEq(parsed.active, true, "persistState: active field preserved");
86
- assertEq(parsed.workers.length, 1, "persistState: worker count preserved");
87
- assertEq(parsed.workers[0].milestoneId, "M001", "persistState: milestoneId preserved");
88
- assertEq(parsed.workers[0].cost, 0.15, "persistState: cost preserved");
89
- assertEq(parsed.totalCost, 0.15, "persistState: totalCost preserved");
84
+ assert.deepStrictEqual(parsed.active, true, "persistState: active field preserved");
85
+ assert.deepStrictEqual(parsed.workers.length, 1, "persistState: worker count preserved");
86
+ assert.deepStrictEqual(parsed.workers[0].milestoneId, "M001", "persistState: milestoneId preserved");
87
+ assert.deepStrictEqual(parsed.workers[0].cost, 0.15, "persistState: cost preserved");
88
+ assert.deepStrictEqual(parsed.totalCost, 0.15, "persistState: totalCost preserved");
90
89
  } finally {
91
90
  rmSync(basePath, { recursive: true, force: true });
92
91
  }
93
- }
92
+ });
94
93
 
95
- // Test 2: restoreState returns null for missing file
96
- {
94
+ test('Test 2: restoreState returns null for missing file', () => {
97
95
  const basePath = makeTempDir();
98
96
  try {
99
97
  const result = restoreState(basePath);
100
- assertEq(result, null, "restoreState: returns null when no state file");
98
+ assert.deepStrictEqual(result, null, "restoreState: returns null when no state file");
101
99
  } finally {
102
100
  rmSync(basePath, { recursive: true, force: true });
103
101
  }
104
- }
102
+ });
105
103
 
106
- // Test 3: restoreState filters dead PIDs
107
- {
104
+ test('Test 3: restoreState filters dead PIDs', () => {
108
105
  const basePath = makeTempDir();
109
106
  try {
110
107
  // PID 99999999 is almost certainly not alive
@@ -136,15 +133,14 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
136
133
 
137
134
  const result = restoreState(basePath);
138
135
  // Both PIDs are dead, so result should be null and file should be cleaned up
139
- assertEq(result, null, "restoreState: returns null when all PIDs dead");
140
- assertTrue(!existsSync(stateFilePath(basePath)), "restoreState: cleans up state file when all dead");
136
+ assert.deepStrictEqual(result, null, "restoreState: returns null when all PIDs dead");
137
+ assert.ok(!existsSync(stateFilePath(basePath)), "restoreState: cleans up state file when all dead");
141
138
  } finally {
142
139
  rmSync(basePath, { recursive: true, force: true });
143
140
  }
144
- }
141
+ });
145
142
 
146
- // Test 4: restoreState keeps alive PIDs
147
- {
143
+ test('Test 4: restoreState keeps alive PIDs', () => {
148
144
  const basePath = makeTempDir();
149
145
  try {
150
146
  // Use current process PID (definitely alive)
@@ -176,18 +172,17 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
176
172
  writeStateFile(basePath, state);
177
173
 
178
174
  const result = restoreState(basePath);
179
- assertTrue(result !== null, "restoreState: returns state when alive PID exists");
180
- assertEq(result!.workers.length, 1, "restoreState: filters out dead PID");
181
- assertEq(result!.workers[0].milestoneId, "M001", "restoreState: keeps alive worker");
182
- assertEq(result!.workers[0].pid, process.pid, "restoreState: preserves PID");
183
- assertEq(result!.workers[0].completedUnits, 5, "restoreState: preserves progress");
175
+ assert.ok(result !== null, "restoreState: returns state when alive PID exists");
176
+ assert.deepStrictEqual(result!.workers.length, 1, "restoreState: filters out dead PID");
177
+ assert.deepStrictEqual(result!.workers[0].milestoneId, "M001", "restoreState: keeps alive worker");
178
+ assert.deepStrictEqual(result!.workers[0].pid, process.pid, "restoreState: preserves PID");
179
+ assert.deepStrictEqual(result!.workers[0].completedUnits, 5, "restoreState: preserves progress");
184
180
  } finally {
185
181
  rmSync(basePath, { recursive: true, force: true });
186
182
  }
187
- }
183
+ });
188
184
 
189
- // Test 5: restoreState skips stopped/error workers even with alive PIDs
190
- {
185
+ test('Test 5: restoreState skips stopped/error workers even with alive PIDs', () => {
191
186
  const basePath = makeTempDir();
192
187
  try {
193
188
  const state = makePersistedState({
@@ -207,14 +202,13 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
207
202
  writeStateFile(basePath, state);
208
203
 
209
204
  const result = restoreState(basePath);
210
- assertEq(result, null, "restoreState: skips stopped workers");
205
+ assert.deepStrictEqual(result, null, "restoreState: skips stopped workers");
211
206
  } finally {
212
207
  rmSync(basePath, { recursive: true, force: true });
213
208
  }
214
- }
209
+ });
215
210
 
216
- // Test 6: orphan detection finds stale sessions
217
- {
211
+ test('Test 6: orphan detection finds stale sessions', () => {
218
212
  const basePath = makeTempDir();
219
213
  try {
220
214
  // Write a session status with a dead PID
@@ -246,7 +240,7 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
246
240
 
247
241
  // Read all sessions — both should exist initially
248
242
  const before = readAllSessionStatuses(basePath);
249
- assertEq(before.length, 2, "orphan: both sessions exist before detection");
243
+ assert.deepStrictEqual(before.length, 2, "orphan: both sessions exist before detection");
250
244
 
251
245
  // Now simulate orphan detection logic (same as prepareParallelStart)
252
246
  const sessions = readAllSessionStatuses(basePath);
@@ -265,34 +259,33 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
265
259
  }
266
260
  }
267
261
 
268
- assertTrue(orphans.length === 2, "orphan: detected both sessions");
262
+ assert.ok(orphans.length === 2, "orphan: detected both sessions");
269
263
  const deadOrphan = orphans.find(o => o.milestoneId === "M001");
270
- assertTrue(deadOrphan !== undefined && !deadOrphan.alive, "orphan: M001 detected as dead");
264
+ assert.ok(deadOrphan !== undefined && !deadOrphan.alive, "orphan: M001 detected as dead");
271
265
  const aliveOrphan = orphans.find(o => o.milestoneId === "M002");
272
- assertTrue(aliveOrphan !== undefined && aliveOrphan.alive, "orphan: M002 detected as alive");
266
+ assert.ok(aliveOrphan !== undefined && aliveOrphan.alive, "orphan: M002 detected as alive");
273
267
 
274
268
  // Dead session should be cleaned up
275
269
  const after = readAllSessionStatuses(basePath);
276
- assertEq(after.length, 1, "orphan: dead session cleaned up");
277
- assertEq(after[0].milestoneId, "M002", "orphan: alive session remains");
270
+ assert.deepStrictEqual(after.length, 1, "orphan: dead session cleaned up");
271
+ assert.deepStrictEqual(after[0].milestoneId, "M002", "orphan: alive session remains");
278
272
  } finally {
279
273
  rmSync(basePath, { recursive: true, force: true });
280
274
  }
281
- }
275
+ });
282
276
 
283
- // Test 7: restoreState handles corrupt JSON gracefully
284
- {
277
+ test('Test 7: restoreState handles corrupt JSON gracefully', () => {
285
278
  const basePath = makeTempDir();
286
279
  try {
287
280
  writeFileSync(stateFilePath(basePath), "{ not valid json !!!", "utf-8");
288
281
  const result = restoreState(basePath);
289
- assertEq(result, null, "restoreState: returns null for corrupt JSON");
282
+ assert.deepStrictEqual(result, null, "restoreState: returns null for corrupt JSON");
290
283
  } finally {
291
284
  rmSync(basePath, { recursive: true, force: true });
292
285
  }
293
- }
286
+ });
294
287
 
295
288
  // Clean up module state
296
289
  resetOrchestrator();
297
290
 
298
- report();
291
+ });
@@ -10,12 +10,11 @@
10
10
  * 6. completedUnits counter increments on assistant message_end
11
11
  */
12
12
 
13
+ import assert from 'node:assert/strict';
13
14
  import { describe, it, after } from "node:test";
14
15
  import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "node:fs";
15
16
  import { join } from "node:path";
16
17
  import { tmpdir } from "node:os";
17
- import { createTestContext } from "./test-helpers.ts";
18
-
19
18
  // We test processWorkerLine indirectly via the module's exported state.
20
19
  // To test the internal function, we use the exported accessors.
21
20
  import {
@@ -27,8 +26,6 @@ import {
27
26
  refreshWorkerStatuses,
28
27
  } from "../parallel-orchestrator.ts";
29
28
 
30
- const { assertEq, assertTrue, report } = createTestContext();
31
-
32
29
  // ─── Helpers ──────────────────────────────────────────────────────────────
33
30
 
34
31
  /** Create a minimal message_end NDJSON line with cost data. */
@@ -52,7 +49,7 @@ function makeMessageEndLine(cost: number, role = "assistant"): string {
52
49
  describe("parallel-worker-monitoring", () => {
53
50
  after(() => {
54
51
  resetOrchestrator();
55
- report();
52
+
56
53
  });
57
54
 
58
55
  // Note: processWorkerLine is not exported, so we test the observable effects
@@ -61,39 +58,39 @@ describe("parallel-worker-monitoring", () => {
61
58
 
62
59
  it("isBudgetExceeded returns false when no state exists", () => {
63
60
  resetOrchestrator();
64
- assertTrue(!isBudgetExceeded(), "no state = not exceeded");
61
+ assert.ok(!isBudgetExceeded(), "no state = not exceeded");
65
62
  });
66
63
 
67
64
  it("isBudgetExceeded returns false when no ceiling configured", () => {
68
65
  resetOrchestrator();
69
66
  // Can't directly set state without startParallel, so test the accessor
70
- assertTrue(!isBudgetExceeded(), "no ceiling = not exceeded");
67
+ assert.ok(!isBudgetExceeded(), "no ceiling = not exceeded");
71
68
  });
72
69
 
73
70
  it("getAggregateCost returns 0 when no state exists", () => {
74
71
  resetOrchestrator();
75
- assertEq(getAggregateCost(), 0, "no state = zero cost");
72
+ assert.deepStrictEqual(getAggregateCost(), 0, "no state = zero cost");
76
73
  });
77
74
 
78
75
  it("isParallelActive returns false after reset", () => {
79
76
  resetOrchestrator();
80
- assertTrue(!isParallelActive(), "reset = not active");
77
+ assert.ok(!isParallelActive(), "reset = not active");
81
78
  });
82
79
 
83
80
  it("getWorkerStatuses returns empty array when no state", () => {
84
81
  resetOrchestrator();
85
- assertEq(getWorkerStatuses().length, 0, "no state = empty workers");
82
+ assert.deepStrictEqual(getWorkerStatuses().length, 0, "no state = empty workers");
86
83
  });
87
84
 
88
85
  it("NDJSON message_end format matches expected structure", () => {
89
86
  // Verify the NDJSON line format we expect from workers
90
87
  const line = makeMessageEndLine(0.05);
91
88
  const parsed = JSON.parse(line);
92
- assertEq(parsed.type, "message_end", "type is message_end");
93
- assertEq(parsed.message.role, "assistant", "role is assistant");
94
- assertEq(parsed.message.usage.cost.total, 0.05, "cost.total is 0.05");
95
- assertTrue(typeof parsed.message.usage.input === "number", "input is number");
96
- assertTrue(typeof parsed.message.usage.output === "number", "output is number");
89
+ assert.deepStrictEqual(parsed.type, "message_end", "type is message_end");
90
+ assert.deepStrictEqual(parsed.message.role, "assistant", "role is assistant");
91
+ assert.deepStrictEqual(parsed.message.usage.cost.total, 0.05, "cost.total is 0.05");
92
+ assert.ok(typeof parsed.message.usage.input === "number", "input is number");
93
+ assert.ok(typeof parsed.message.usage.output === "number", "output is number");
97
94
  });
98
95
 
99
96
  it("malformed JSON does not throw (tested via parse safety)", () => {
@@ -111,7 +108,7 @@ describe("parallel-worker-monitoring", () => {
111
108
  JSON.parse(line);
112
109
  } catch {
113
110
  // Expected — processWorkerLine catches this silently
114
- assertTrue(true, `malformed line "${line.slice(0, 20)}" handled`);
111
+ assert.ok(true, `malformed line "${line.slice(0, 20)}" handled`);
115
112
  }
116
113
  }
117
114
  });
@@ -122,25 +119,25 @@ describe("parallel-worker-monitoring", () => {
122
119
  let total = 0;
123
120
  for (const c of costs) total += c;
124
121
  // Floating point: round to 2 decimal places for comparison
125
- assertEq(Math.round(total * 100) / 100, 0.28, "cost sum is correct");
122
+ assert.deepStrictEqual(Math.round(total * 100) / 100, 0.28, "cost sum is correct");
126
123
  });
127
124
 
128
125
  it("budget ceiling comparison works with typical values", () => {
129
126
  // Test the ceiling check pattern
130
127
  const ceiling = 5.0;
131
- assertTrue(0 < ceiling, "0 is under ceiling");
132
- assertTrue(4.99 < ceiling, "4.99 is under ceiling");
133
- assertTrue(!(5.0 < ceiling), "5.0 is at ceiling");
134
- assertTrue(!(5.01 < ceiling), "5.01 is over ceiling");
128
+ assert.ok(0 < ceiling, "0 is under ceiling");
129
+ assert.ok(4.99 < ceiling, "4.99 is under ceiling");
130
+ assert.ok(!(5.0 < ceiling), "5.0 is at ceiling");
131
+ assert.ok(!(5.01 < ceiling), "5.01 is over ceiling");
135
132
  });
136
133
 
137
134
  it("worker spawn args include --mode json", () => {
138
135
  // Verify the spawn command includes JSON mode for NDJSON output.
139
136
  // We can't easily test the actual spawn, but we verify the args pattern.
140
137
  const expectedArgs = ["--mode", "json", "--print", "/gsd auto"];
141
- assertTrue(expectedArgs.includes("--mode"), "args include --mode");
142
- assertTrue(expectedArgs.includes("json"), "args include json");
143
- assertTrue(expectedArgs.indexOf("--mode") < expectedArgs.indexOf("json"),
138
+ assert.ok(expectedArgs.includes("--mode"), "args include --mode");
139
+ assert.ok(expectedArgs.includes("json"), "args include json");
140
+ assert.ok(expectedArgs.indexOf("--mode") < expectedArgs.indexOf("json"),
144
141
  "--mode comes before json");
145
142
  });
146
143
 
@@ -168,8 +165,8 @@ describe("parallel-worker-monitoring", () => {
168
165
  }, null, 2));
169
166
  refreshWorkerStatuses(base, { restoreIfNeeded: true });
170
167
  const workers = getWorkerStatuses();
171
- assertEq(workers.length, 1, "restored one worker");
172
- assertEq(workers[0].milestoneId, "M001", "worker restored from persisted state");
168
+ assert.deepStrictEqual(workers.length, 1, "restored one worker");
169
+ assert.deepStrictEqual(workers[0].milestoneId, "M001", "worker restored from persisted state");
173
170
  } finally {
174
171
  resetOrchestrator();
175
172
  rmSync(base, { recursive: true, force: true });
@@ -193,8 +190,8 @@ describe("parallel-worker-monitoring", () => {
193
190
  }, null, 2));
194
191
  refreshWorkerStatuses(base, { restoreIfNeeded: true });
195
192
  const workers = getWorkerStatuses();
196
- assertEq(workers[0].state, "running", "live session status restored");
197
- assertEq(workers[0].completedUnits, 3, "completed units restored from status file");
193
+ assert.deepStrictEqual(workers[0].state, "running", "live session status restored");
194
+ assert.deepStrictEqual(workers[0].completedUnits, 3, "completed units restored from status file");
198
195
  } finally {
199
196
  resetOrchestrator();
200
197
  rmSync(base, { recursive: true, force: true });