gsd-pi 2.44.0 → 2.45.0-dev.6b9da3e

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 (463) hide show
  1. package/README.md +30 -12
  2. package/dist/resources/extensions/gsd/activity-log.js +7 -0
  3. package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
  4. package/dist/resources/extensions/gsd/auto/phases.js +37 -36
  5. package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
  6. package/dist/resources/extensions/gsd/auto-start.js +31 -2
  7. package/dist/resources/extensions/gsd/auto-timers.js +57 -3
  8. package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
  9. package/dist/resources/extensions/gsd/auto-worktree.js +9 -6
  10. package/dist/resources/extensions/gsd/auto.js +30 -3
  11. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +156 -0
  12. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
  13. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  14. package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
  15. package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
  16. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  17. package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
  18. package/dist/resources/extensions/gsd/db-writer.js +34 -16
  19. package/dist/resources/extensions/gsd/doctor.js +8 -0
  20. package/dist/resources/extensions/gsd/git-service.js +8 -3
  21. package/dist/resources/extensions/gsd/gsd-db.js +12 -1
  22. package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
  23. package/dist/resources/extensions/gsd/preferences.js +9 -1
  24. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  25. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  26. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  27. package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  28. package/dist/resources/extensions/gsd/prompts/rethink.md +78 -0
  29. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  30. package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
  31. package/dist/resources/extensions/gsd/repo-identity.js +45 -7
  32. package/dist/resources/extensions/gsd/rethink.js +115 -0
  33. package/dist/resources/extensions/gsd/state.js +41 -3
  34. package/dist/resources/extensions/gsd/tools/plan-slice.js +1 -0
  35. package/dist/resources/extensions/gsd/tools/plan-task.js +1 -0
  36. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -0
  37. package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
  38. package/dist/resources/extensions/gsd/worktree-manager.js +32 -2
  39. package/dist/resources/extensions/gsd/worktree-resolver.js +6 -0
  40. package/dist/resources/extensions/mcp-client/index.js +14 -0
  41. package/dist/web/standalone/.next/BUILD_ID +1 -1
  42. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  43. package/dist/web/standalone/.next/build-manifest.json +4 -4
  44. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  45. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  46. package/dist/web/standalone/.next/required-server-files.json +3 -3
  47. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  48. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  49. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  50. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  58. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  59. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  60. package/dist/web/standalone/.next/server/app/_not-found.rsc +5 -5
  61. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +5 -5
  62. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  64. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  67. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  74. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  112. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  118. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  132. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  134. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  136. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  138. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/index.html +1 -1
  148. package/dist/web/standalone/.next/server/app/index.rsc +6 -6
  149. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  150. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +6 -6
  151. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  153. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  154. package/dist/web/standalone/.next/server/app/page.js +2 -2
  155. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  157. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  158. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  159. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/middleware.js +2 -2
  162. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  164. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  165. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  166. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  167. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +9 -0
  168. package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
  169. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  170. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  171. package/dist/web/standalone/.next/static/chunks/app/page-6654a8cca61a3d1c.js +1 -0
  172. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  173. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  174. package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
  175. package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
  176. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  177. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  178. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  179. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  180. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  181. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  182. package/dist/web/standalone/server.js +1 -1
  183. package/package.json +1 -1
  184. package/packages/native/dist/stream-process/index.js +2 -2
  185. package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
  186. package/packages/native/src/stream-process/index.ts +2 -2
  187. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
  188. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
  190. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  192. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  193. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  194. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  196. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  197. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
  198. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
  199. package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
  200. package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
  201. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +11 -0
  202. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  203. package/packages/pi-coding-agent/dist/core/model-registry.js +20 -1
  204. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  205. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  206. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  207. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  208. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  209. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  210. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  211. package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
  212. package/packages/pi-coding-agent/dist/core/settings-manager.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/main.d.ts.map +1 -1
  216. package/packages/pi-coding-agent/dist/main.js +17 -0
  217. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  218. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
  219. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
  220. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
  221. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
  222. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  224. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
  225. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  226. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  227. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  228. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  229. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  230. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
  231. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
  232. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
  233. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
  234. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  235. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
  236. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  237. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
  238. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  239. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
  240. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
  243. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  245. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
  246. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  247. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  248. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  249. package/packages/pi-coding-agent/package.json +1 -1
  250. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  251. package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
  252. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  253. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  254. package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
  255. package/packages/pi-coding-agent/src/core/model-registry.ts +21 -1
  256. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  257. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  258. package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
  259. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  260. package/packages/pi-coding-agent/src/main.ts +19 -0
  261. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
  262. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
  263. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  264. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
  265. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
  266. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
  267. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
  268. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
  269. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  270. package/pkg/package.json +1 -1
  271. package/src/resources/extensions/gsd/activity-log.ts +1 -0
  272. package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
  273. package/src/resources/extensions/gsd/auto/phases.ts +46 -48
  274. package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
  275. package/src/resources/extensions/gsd/auto-start.ts +39 -2
  276. package/src/resources/extensions/gsd/auto-timers.ts +64 -3
  277. package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
  278. package/src/resources/extensions/gsd/auto-worktree.ts +9 -6
  279. package/src/resources/extensions/gsd/auto.ts +37 -3
  280. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +148 -0
  281. package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
  282. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  283. package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
  284. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  285. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  286. package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
  287. package/src/resources/extensions/gsd/db-writer.ts +39 -17
  288. package/src/resources/extensions/gsd/doctor.ts +7 -1
  289. package/src/resources/extensions/gsd/git-service.ts +6 -2
  290. package/src/resources/extensions/gsd/gsd-db.ts +16 -1
  291. package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
  292. package/src/resources/extensions/gsd/preferences.ts +11 -1
  293. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  294. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  295. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  296. package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  297. package/src/resources/extensions/gsd/prompts/rethink.md +78 -0
  298. package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  299. package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
  300. package/src/resources/extensions/gsd/repo-identity.ts +46 -7
  301. package/src/resources/extensions/gsd/rethink.ts +154 -0
  302. package/src/resources/extensions/gsd/state.ts +41 -1
  303. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  304. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  305. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  306. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
  307. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  308. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  309. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  310. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  311. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  312. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  313. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  314. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  315. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  316. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  317. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  318. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  319. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  320. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  321. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  322. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
  323. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  324. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  325. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  326. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  327. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  328. package/src/resources/extensions/gsd/tests/db-writer.test.ts +465 -416
  329. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  330. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  331. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
  332. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +210 -181
  333. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  334. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  335. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  336. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  337. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  338. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  339. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  340. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  341. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  342. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  343. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  344. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  345. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  346. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  347. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  348. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  349. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  350. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  351. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  352. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
  353. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  354. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  355. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  356. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  357. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  358. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  359. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  360. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  361. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  362. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  363. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  364. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  365. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  366. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  367. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  368. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  369. package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
  370. package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
  371. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  372. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  373. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  374. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  375. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  376. package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
  377. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  378. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
  379. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  380. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  381. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  382. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
  383. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  384. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  385. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  386. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  387. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  388. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  389. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  390. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  391. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
  392. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  393. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  394. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  395. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  396. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  397. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  398. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  399. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  400. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  401. package/src/resources/extensions/gsd/tests/preferences.test.ts +27 -0
  402. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -7
  403. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  404. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  405. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  406. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  407. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  408. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  409. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  410. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
  411. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  412. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  413. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  414. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  415. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  416. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  417. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  418. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  419. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  420. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  421. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  422. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  423. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
  424. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
  425. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  426. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
  427. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  428. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  429. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +10 -11
  430. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  431. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  432. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  433. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  434. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  435. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  436. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  437. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  438. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  439. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  440. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  441. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  442. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  443. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  444. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  445. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
  446. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  447. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  448. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  449. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
  450. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -0
  451. package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -0
  452. package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
  453. package/src/resources/extensions/gsd/worktree-manager.ts +43 -2
  454. package/src/resources/extensions/gsd/worktree-resolver.ts +7 -0
  455. package/src/resources/extensions/mcp-client/index.ts +20 -0
  456. package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
  457. package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +0 -1
  458. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  459. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  460. package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
  461. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
  462. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → rzO54ZboyINyEt7cVM_uS}/_buildManifest.js +0 -0
  463. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → rzO54ZboyINyEt7cVM_uS}/_ssgManifest.js +0 -0
@@ -5,6 +5,8 @@
5
5
  * Runs in a real temp git repo.
6
6
  */
7
7
 
8
+ import { describe, test, afterEach } from "node:test";
9
+ import assert from "node:assert/strict";
8
10
  import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, realpathSync } from "node:fs";
9
11
  import { join } from "node:path";
10
12
  import { tmpdir } from "node:os";
@@ -20,10 +22,9 @@ import {
20
22
  getActiveAutoWorktreeContext,
21
23
  } from "../auto-worktree.ts";
22
24
 
23
- import { createTestContext } from "./test-helpers.ts";
24
-
25
- const { assertEq, assertTrue, report } = createTestContext();
26
-
25
+ // Note: execSync is used intentionally in tests for git operations with
26
+ // controlled, hardcoded inputs (no user input). This is safe and matches
27
+ // the pattern used by the original test file.
27
28
  function run(command: string, cwd: string): string {
28
29
  return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
29
30
  }
@@ -42,11 +43,19 @@ function createTempRepo(): string {
42
43
  return dir;
43
44
  }
44
45
 
45
- async function main(): Promise<void> {
46
+ describe("auto-worktree lifecycle", () => {
46
47
  const savedCwd = process.cwd();
47
48
  let tempDir = "";
48
49
 
49
- try {
50
+ afterEach(() => {
51
+ process.chdir(savedCwd);
52
+ if (tempDir && existsSync(tempDir)) {
53
+ rmSync(tempDir, { recursive: true, force: true });
54
+ }
55
+ tempDir = "";
56
+ });
57
+
58
+ test("create → detect → teardown", () => {
50
59
  tempDir = createTempRepo();
51
60
 
52
61
  // Create .gsd/milestones/M003 with a dummy file (simulates planning artifacts)
@@ -56,28 +65,26 @@ async function main(): Promise<void> {
56
65
  run("git add .", tempDir);
57
66
  run("git commit -m \"add milestone\"", tempDir);
58
67
 
59
- console.log("\n=== auto-worktree lifecycle ===");
60
-
61
68
  // ─── createAutoWorktree ──────────────────────────────────────────
62
69
  const wtPath = createAutoWorktree(tempDir, "M003");
63
70
 
64
- assertTrue(existsSync(wtPath), "worktree directory exists after create");
65
- assertEq(process.cwd(), wtPath, "process.cwd() is worktree path after create");
71
+ assert.ok(existsSync(wtPath), "worktree directory exists after create");
72
+ assert.strictEqual(process.cwd(), wtPath, "process.cwd() is worktree path after create");
66
73
 
67
74
  const branch = run("git branch --show-current", wtPath);
68
- assertEq(branch, "milestone/M003", "git branch is milestone/M003");
75
+ assert.strictEqual(branch, "milestone/M003", "git branch is milestone/M003");
69
76
 
70
- assertTrue(
77
+ assert.ok(
71
78
  existsSync(join(wtPath, ".gsd", "milestones", "M003", "CONTEXT.md")),
72
79
  "planning files inherited in worktree",
73
80
  );
74
81
 
75
82
  // ─── isInAutoWorktree ────────────────────────────────────────────
76
- assertTrue(isInAutoWorktree(tempDir), "isInAutoWorktree returns true when inside");
83
+ assert.ok(isInAutoWorktree(tempDir), "isInAutoWorktree returns true when inside");
77
84
 
78
85
  // ─── getAutoWorktreeOriginalBase ─────────────────────────────────
79
- assertEq(getAutoWorktreeOriginalBase(), tempDir, "originalBase returns temp dir");
80
- assertEq(
86
+ assert.strictEqual(getAutoWorktreeOriginalBase(), tempDir, "originalBase returns temp dir");
87
+ assert.deepStrictEqual(
81
88
  getActiveAutoWorktreeContext(),
82
89
  {
83
90
  originalBase: tempDir,
@@ -88,33 +95,39 @@ async function main(): Promise<void> {
88
95
  );
89
96
 
90
97
  // ─── getAutoWorktreePath ─────────────────────────────────────────
91
- assertEq(getAutoWorktreePath(tempDir, "M003"), wtPath, "getAutoWorktreePath returns correct path");
92
- assertEq(getAutoWorktreePath(tempDir, "M999"), null, "getAutoWorktreePath returns null for nonexistent");
98
+ assert.strictEqual(getAutoWorktreePath(tempDir, "M003"), wtPath, "getAutoWorktreePath returns correct path");
99
+ assert.strictEqual(getAutoWorktreePath(tempDir, "M999"), null, "getAutoWorktreePath returns null for nonexistent");
93
100
 
94
101
  // ─── teardownAutoWorktree ────────────────────────────────────────
95
102
  teardownAutoWorktree(tempDir, "M003");
96
103
 
97
- assertEq(process.cwd(), tempDir, "process.cwd() back to original after teardown");
98
- assertTrue(!existsSync(wtPath), "worktree directory removed after teardown");
99
- assertTrue(!isInAutoWorktree(tempDir), "isInAutoWorktree returns false after teardown");
100
- assertEq(getAutoWorktreeOriginalBase(), null, "originalBase is null after teardown");
101
- assertEq(getActiveAutoWorktreeContext(), null, "active auto-worktree context clears after teardown");
104
+ assert.strictEqual(process.cwd(), tempDir, "process.cwd() back to original after teardown");
105
+ assert.ok(!existsSync(wtPath), "worktree directory removed after teardown");
106
+ assert.ok(!isInAutoWorktree(tempDir), "isInAutoWorktree returns false after teardown");
107
+ assert.strictEqual(getAutoWorktreeOriginalBase(), null, "originalBase is null after teardown");
108
+ assert.strictEqual(getActiveAutoWorktreeContext(), null, "active auto-worktree context clears after teardown");
109
+ });
102
110
 
103
- // ─── Re-entry: create again, exit without teardown, re-enter ─────
104
- console.log("\n=== re-entry ===");
111
+ test("re-entry: create again, exit without teardown, re-enter", () => {
112
+ tempDir = createTempRepo();
113
+ const msDir = join(tempDir, ".gsd", "milestones", "M003");
114
+ mkdirSync(msDir, { recursive: true });
115
+ writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
116
+ run("git add .", tempDir);
117
+ run("git commit -m \"add milestone\"", tempDir);
105
118
 
106
119
  const wtPath2 = createAutoWorktree(tempDir, "M003");
107
- assertTrue(existsSync(wtPath2), "worktree re-created");
120
+ assert.ok(existsSync(wtPath2), "worktree re-created");
108
121
 
109
122
  // Manually chdir out (simulates pause/crash)
110
123
  process.chdir(tempDir);
111
124
 
112
125
  // enterAutoWorktree should re-enter
113
126
  const entered = enterAutoWorktree(tempDir, "M003");
114
- assertEq(process.cwd(), entered, "re-entered worktree via enterAutoWorktree");
115
- assertEq(getAutoWorktreeOriginalBase(), tempDir, "originalBase restored on re-entry");
116
- assertTrue(isInAutoWorktree(tempDir), "isInAutoWorktree true after re-entry");
117
- assertEq(
127
+ assert.strictEqual(process.cwd(), entered, "re-entered worktree via enterAutoWorktree");
128
+ assert.strictEqual(getAutoWorktreeOriginalBase(), tempDir, "originalBase restored on re-entry");
129
+ assert.ok(isInAutoWorktree(tempDir), "isInAutoWorktree true after re-entry");
130
+ assert.deepStrictEqual(
118
131
  getActiveAutoWorktreeContext(),
119
132
  {
120
133
  originalBase: tempDir,
@@ -126,142 +139,151 @@ async function main(): Promise<void> {
126
139
 
127
140
  // Cleanup
128
141
  teardownAutoWorktree(tempDir, "M003");
142
+ });
129
143
 
130
- // ─── Coexistence with manual worktree ─────────────────────────────
131
- console.log("\n=== coexistence ===");
144
+ test("coexistence with manual worktree", async () => {
145
+ tempDir = createTempRepo();
146
+ const msDir = join(tempDir, ".gsd", "milestones", "M003");
147
+ mkdirSync(msDir, { recursive: true });
148
+ writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
149
+ run("git add .", tempDir);
150
+ run("git commit -m \"add milestone\"", tempDir);
132
151
 
133
152
  // Import createWorktree directly for manual worktree
134
153
  const { createWorktree } = await import("../worktree-manager.ts");
135
154
 
136
155
  // Create manual worktree (uses worktree/<name> branch)
137
156
  const manualWt = createWorktree(tempDir, "feature-x");
138
- assertTrue(existsSync(manualWt.path), "manual worktree exists");
139
- assertEq(manualWt.branch, "worktree/feature-x", "manual worktree uses worktree/ prefix");
157
+ assert.ok(existsSync(manualWt.path), "manual worktree exists");
158
+ assert.strictEqual(manualWt.branch, "worktree/feature-x", "manual worktree uses worktree/ prefix");
140
159
 
141
160
  // Create auto-worktree alongside
142
161
  const autoWtPath = createAutoWorktree(tempDir, "M003");
143
- assertTrue(existsSync(autoWtPath), "auto-worktree coexists with manual");
144
- assertTrue(existsSync(manualWt.path), "manual worktree still exists");
162
+ assert.ok(existsSync(autoWtPath), "auto-worktree coexists with manual");
163
+ assert.ok(existsSync(manualWt.path), "manual worktree still exists");
145
164
 
146
165
  // Cleanup both
147
166
  teardownAutoWorktree(tempDir, "M003");
148
167
  const { removeWorktree } = await import("../worktree-manager.ts");
149
168
  removeWorktree(tempDir, "feature-x");
169
+ });
150
170
 
151
- // ─── Failure: split-brain prevention ──────────────────────────────
152
- console.log("\n=== split-brain prevention ===");
153
- // After teardown, originalBase should be null
154
- assertEq(getAutoWorktreeOriginalBase(), null, "no split-brain: originalBase cleared");
171
+ test("split-brain prevention: originalBase cleared after teardown", () => {
172
+ tempDir = createTempRepo();
173
+ const msDir = join(tempDir, ".gsd", "milestones", "M003");
174
+ mkdirSync(msDir, { recursive: true });
175
+ writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
176
+ run("git add .", tempDir);
177
+ run("git commit -m \"add milestone\"", tempDir);
155
178
 
156
- // ─── #1526: getMainBranch returns milestone branch in auto-worktree ──
157
- console.log("\n=== #1526: getMainBranch() returns milestone/<MID> in auto-worktree ===");
158
- {
159
- const { GitServiceImpl } = await import("../git-service.ts");
179
+ createAutoWorktree(tempDir, "M003");
180
+ teardownAutoWorktree(tempDir, "M003");
160
181
 
161
- // Create worktree
162
- const wtPath = createAutoWorktree(tempDir, "M005");
163
- // Don't set main_branch pref so getMainBranch falls through to worktree detection
164
- const gitService = new GitServiceImpl(wtPath);
165
- gitService.setMilestoneId("M005");
182
+ assert.strictEqual(getAutoWorktreeOriginalBase(), null, "no split-brain: originalBase cleared");
183
+ });
166
184
 
167
- // Verify getMainBranch returns the milestone branch
168
- const mainBranch = gitService.getMainBranch();
169
- assertEq(mainBranch, "milestone/M005", "getMainBranch returns milestone/<MID> in auto-worktree");
185
+ test("#1526: getMainBranch returns milestone/<MID> in auto-worktree", async () => {
186
+ tempDir = createTempRepo();
187
+ const msDir = join(tempDir, ".gsd", "milestones", "M005");
188
+ mkdirSync(msDir, { recursive: true });
189
+ writeFileSync(join(msDir, "CONTEXT.md"), "# M005 Context\n");
190
+ run("git add .", tempDir);
191
+ run("git commit -m \"add milestone\"", tempDir);
170
192
 
171
- // Cleanup
172
- teardownAutoWorktree(tempDir, "M005");
173
- }
193
+ const { GitServiceImpl } = await import("../git-service.ts");
174
194
 
175
- // ─── #1713: stale worktree directory recovery ─────────────────────
176
- console.log("\n=== #1713: stale worktree directory without .git file ===");
177
- {
178
- // Simulate a crash leaving a stale directory with no .git file.
179
- // createAutoWorktree should detect and remove the stale directory,
180
- // then successfully create a fresh worktree.
181
- const { worktreePath } = await import("../worktree-manager.ts");
182
- const staleDir = worktreePath(tempDir, "M010");
183
- mkdirSync(staleDir, { recursive: true });
184
- // Write a dummy file to prove it's not an empty directory
185
- writeFileSync(join(staleDir, "orphan.txt"), "stale leftover\n");
186
- assertTrue(existsSync(staleDir), "stale directory exists before recovery");
187
- assertTrue(!existsSync(join(staleDir, ".git")), "stale directory has no .git file");
188
-
189
- // createAutoWorktree should remove the stale dir and create a real worktree
190
- const recoveredPath = createAutoWorktree(tempDir, "M010");
191
- assertTrue(existsSync(recoveredPath), "worktree created after stale dir recovery");
192
- assertTrue(existsSync(join(recoveredPath, ".git")), "recovered worktree has .git file");
193
- assertTrue(!existsSync(join(recoveredPath, "orphan.txt")), "stale file removed by recovery");
194
-
195
- teardownAutoWorktree(tempDir, "M010");
196
- }
195
+ // Create worktree
196
+ const wtPath = createAutoWorktree(tempDir, "M005");
197
+ // Don't set main_branch pref so getMainBranch falls through to worktree detection
198
+ const gitService = new GitServiceImpl(wtPath);
199
+ gitService.setMilestoneId("M005");
197
200
 
198
- // ─── #778: reconcile plan checkboxes on re-attach ─────────────────
199
- console.log("\n=== #778: reconcile plan checkboxes on re-attach ===");
200
- {
201
- // Simulate: T01 [x] was committed to milestone branch, T02 [x] was
202
- // written to project root by syncStateToProjectRoot() but the
203
- // auto-commit crashed before it fired. On restart the worktree is
204
- // re-created from the milestone branch HEAD (T02 still [ ]).
205
- // reconcilePlanCheckboxes should forward-apply T02 [x] from the root.
206
-
207
- const planRelPath = join(".gsd", "milestones", "M004", "slices", "S01", "S01-PLAN.md");
208
- const planDir = join(tempDir, ".gsd", "milestones", "M004", "slices", "S01");
209
- const { mkdirSync: mkdir, writeFileSync: write, readFileSync: read } = await import("node:fs");
210
-
211
- // Plan on integration branch (project root): T01 [x], T02 [x]
212
- mkdir(planDir, { recursive: true });
213
- write(
214
- join(tempDir, planRelPath),
215
- "# S01 Plan\n- [x] **T01:** task one\n- [x] **T02:** task two\n- [ ] **T03:** task three\n",
216
- );
217
-
218
- // Write integration-branch plan to git so milestone branch starts from it
219
- run(`git add .`, tempDir);
220
- run(`git commit -m "add plan with T01 and T02 checked" --allow-empty`, tempDir);
221
-
222
- // Create milestone branch with only T01 [x] (simulating crash before T02 commit)
223
- const milestoneBranch = "milestone/M004";
224
- run(`git checkout -b ${milestoneBranch}`, tempDir);
225
- mkdir(planDir, { recursive: true });
226
- write(
227
- join(tempDir, planRelPath),
228
- "# S01 Plan\n- [x] **T01:** task one\n- [ ] **T02:** task two\n- [ ] **T03:** task three\n",
229
- );
230
- run(`git add .`, tempDir);
231
- run(`git commit -m "milestone: only T01 checked"`, tempDir);
232
- run(`git checkout main`, tempDir);
233
-
234
- // Restore project root plan (T01+T02 [x]) — simulates syncStateToProjectRoot
235
- write(
236
- join(tempDir, planRelPath),
237
- "# S01 Plan\n- [x] **T01:** task one\n- [x] **T02:** task two\n- [ ] **T03:** task three\n",
238
- );
239
-
240
- // Create worktree re-attached to existing milestone branch (T02 still [ ] in branch)
241
- const wtPath = createAutoWorktree(tempDir, "M004");
242
-
243
- try {
244
- const wtPlanPath = join(wtPath, planRelPath);
245
- assertTrue(existsSync(wtPlanPath), "plan file exists in worktree after re-attach");
246
-
247
- const wtPlan = read(wtPlanPath, "utf-8");
248
- assertTrue(wtPlan.includes("- [x] **T02:"), "T02 should be [x] after reconciliation (was [ ] on branch)");
249
- assertTrue(wtPlan.includes("- [x] **T01:"), "T01 stays [x]");
250
- assertTrue(wtPlan.includes("- [ ] **T03:"), "T03 stays [ ] (not in root either)");
251
- } finally {
252
- teardownAutoWorktree(tempDir, "M004");
253
- }
254
- }
201
+ // Verify getMainBranch returns the milestone branch
202
+ const mainBranch = gitService.getMainBranch();
203
+ assert.strictEqual(mainBranch, "milestone/M005", "getMainBranch returns milestone/<MID> in auto-worktree");
255
204
 
256
- } finally {
257
- // Always restore cwd and clean up
258
- process.chdir(savedCwd);
259
- if (tempDir && existsSync(tempDir)) {
260
- rmSync(tempDir, { recursive: true, force: true });
261
- }
262
- }
205
+ // Cleanup
206
+ teardownAutoWorktree(tempDir, "M005");
207
+ });
263
208
 
264
- report();
265
- }
209
+ test("#1713: stale worktree directory without .git file", async () => {
210
+ tempDir = createTempRepo();
211
+ const msDir = join(tempDir, ".gsd", "milestones", "M010");
212
+ mkdirSync(msDir, { recursive: true });
213
+ writeFileSync(join(msDir, "CONTEXT.md"), "# M010 Context\n");
214
+ run("git add .", tempDir);
215
+ run("git commit -m \"add milestone\"", tempDir);
216
+
217
+ // Simulate a crash leaving a stale directory with no .git file.
218
+ const { worktreePath } = await import("../worktree-manager.ts");
219
+ const staleDir = worktreePath(tempDir, "M010");
220
+ mkdirSync(staleDir, { recursive: true });
221
+ writeFileSync(join(staleDir, "orphan.txt"), "stale leftover\n");
222
+ assert.ok(existsSync(staleDir), "stale directory exists before recovery");
223
+ assert.ok(!existsSync(join(staleDir, ".git")), "stale directory has no .git file");
224
+
225
+ // createAutoWorktree should remove the stale dir and create a real worktree
226
+ const recoveredPath = createAutoWorktree(tempDir, "M010");
227
+ assert.ok(existsSync(recoveredPath), "worktree created after stale dir recovery");
228
+ assert.ok(existsSync(join(recoveredPath, ".git")), "recovered worktree has .git file");
229
+ assert.ok(!existsSync(join(recoveredPath, "orphan.txt")), "stale file removed by recovery");
230
+
231
+ teardownAutoWorktree(tempDir, "M010");
232
+ });
233
+
234
+ test("#778: reconcile plan checkboxes on re-attach", async () => {
235
+ tempDir = createTempRepo();
236
+ const msDir = join(tempDir, ".gsd", "milestones", "M003");
237
+ mkdirSync(msDir, { recursive: true });
238
+ writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
239
+ run("git add .", tempDir);
240
+ run("git commit -m \"add milestone\"", tempDir);
241
+
242
+ const planRelPath = join(".gsd", "milestones", "M004", "slices", "S01", "S01-PLAN.md");
243
+ const planDir = join(tempDir, ".gsd", "milestones", "M004", "slices", "S01");
244
+ const { mkdirSync: mkdir, writeFileSync: write, readFileSync: read } = await import("node:fs");
245
+
246
+ // Plan on integration branch (project root): T01 [x], T02 [x]
247
+ mkdir(planDir, { recursive: true });
248
+ write(
249
+ join(tempDir, planRelPath),
250
+ "# S01 Plan\n- [x] **T01:** task one\n- [x] **T02:** task two\n- [ ] **T03:** task three\n",
251
+ );
252
+
253
+ run(`git add .`, tempDir);
254
+ run(`git commit -m "add plan with T01 and T02 checked" --allow-empty`, tempDir);
255
+
256
+ // Create milestone branch with only T01 [x] (simulating crash before T02 commit)
257
+ const milestoneBranch = "milestone/M004";
258
+ run(`git checkout -b ${milestoneBranch}`, tempDir);
259
+ mkdir(planDir, { recursive: true });
260
+ write(
261
+ join(tempDir, planRelPath),
262
+ "# S01 Plan\n- [x] **T01:** task one\n- [ ] **T02:** task two\n- [ ] **T03:** task three\n",
263
+ );
264
+ run(`git add .`, tempDir);
265
+ run(`git commit -m "milestone: only T01 checked"`, tempDir);
266
+ run(`git checkout main`, tempDir);
267
+
268
+ // Restore project root plan (T01+T02 [x])
269
+ write(
270
+ join(tempDir, planRelPath),
271
+ "# S01 Plan\n- [x] **T01:** task one\n- [x] **T02:** task two\n- [ ] **T03:** task three\n",
272
+ );
273
+
274
+ // Create worktree re-attached to existing milestone branch (T02 still [ ] in branch)
275
+ const wtPath = createAutoWorktree(tempDir, "M004");
266
276
 
267
- main();
277
+ try {
278
+ const wtPlanPath = join(wtPath, planRelPath);
279
+ assert.ok(existsSync(wtPlanPath), "plan file exists in worktree after re-attach");
280
+
281
+ const wtPlan = read(wtPlanPath, "utf-8");
282
+ assert.ok(wtPlan.includes("- [x] **T02:"), "T02 should be [x] after reconciliation (was [ ] on branch)");
283
+ assert.ok(wtPlan.includes("- [x] **T01:"), "T01 stays [x]");
284
+ assert.ok(wtPlan.includes("- [ ] **T03:"), "T03 stays [ ] (not in root either)");
285
+ } finally {
286
+ teardownAutoWorktree(tempDir, "M004");
287
+ }
288
+ });
289
+ });
@@ -12,15 +12,14 @@
12
12
  * Pattern: derive state → write file → invalidate cache → derive again → verify update
13
13
  */
14
14
 
15
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync } from 'node:fs';
15
+ import { describe, test, afterEach } from "node:test";
16
+ import assert from "node:assert/strict";
17
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
16
18
  import { join } from 'node:path';
17
19
  import { tmpdir } from 'node:os';
18
20
 
19
21
  import { deriveState, invalidateStateCache } from '../state.ts';
20
22
  import { invalidateAllCaches } from '../cache.ts';
21
- import { createTestContext } from './test-helpers.ts';
22
-
23
- const { assertEq, assertTrue, report } = createTestContext();
24
23
 
25
24
  function createBase(): string {
26
25
  const base = mkdtempSync(join(tmpdir(), 'gsd-cache-stale-'));
@@ -44,11 +43,9 @@ function writeSliceFile(base: string, mid: string, sid: string, suffix: string,
44
43
  writeFileSync(join(dir, `${sid}-${suffix}.md`), content);
45
44
  }
46
45
 
47
- async function main(): Promise<void> {
46
+ describe("cache-staleness-regression", () => {
48
47
 
49
- // ─── 1. Regression #1240: New roadmap detected after cache invalidation
50
- console.log('\n=== 1. #1240: roadmap written after first derive → detected after invalidation ===');
51
- {
48
+ test("#1240: roadmap written after first derive detected after invalidation", async () => {
52
49
  const base = createBase();
53
50
  try {
54
51
  // Step 1: Create milestone with just context (no roadmap)
@@ -57,7 +54,7 @@ async function main(): Promise<void> {
57
54
  invalidateAllCaches();
58
55
  invalidateStateCache();
59
56
  const state1 = await deriveState(base);
60
- assertEq(state1.phase, 'pre-planning', 'initial: pre-planning (no roadmap)');
57
+ assert.strictEqual(state1.phase, 'pre-planning', 'initial: pre-planning (no roadmap)');
61
58
 
62
59
  // Step 2: Write roadmap (simulating what the LLM does during planning)
63
60
  const roadmap = [
@@ -80,16 +77,14 @@ async function main(): Promise<void> {
80
77
  invalidateAllCaches();
81
78
  invalidateStateCache();
82
79
  const state2 = await deriveState(base);
83
- assertEq(state2.phase, 'planning', '#1240: after roadmap write + invalidation → planning phase');
84
- assertEq(state2.activeSlice?.id, 'S01', '#1240: S01 is now the active slice');
80
+ assert.strictEqual(state2.phase, 'planning', '#1240: after roadmap write + invalidation → planning phase');
81
+ assert.strictEqual(state2.activeSlice?.id, 'S01', '#1240: S01 is now the active slice');
85
82
  } finally {
86
83
  cleanup(base);
87
84
  }
88
- }
85
+ });
89
86
 
90
- // ─── 2. Regression #1249: Slice context detected after cache invalidation
91
- console.log('\n=== 2. #1249: slice context written mid-loop → detected after invalidation ===');
92
- {
87
+ test("#1249: slice context written mid-loop → detected after invalidation", async () => {
93
88
  const base = createBase();
94
89
  try {
95
90
  // Create a milestone in needs-discussion phase (CONTEXT-DRAFT, no CONTEXT)
@@ -100,7 +95,7 @@ async function main(): Promise<void> {
100
95
  invalidateAllCaches();
101
96
  invalidateStateCache();
102
97
  const state1 = await deriveState(base);
103
- assertEq(state1.phase, 'needs-discussion', 'initial: needs-discussion');
98
+ assert.strictEqual(state1.phase, 'needs-discussion', 'initial: needs-discussion');
104
99
 
105
100
  // Simulate: discussion completes, CONTEXT.md is written
106
101
  writeMilestoneFile(base, 'M001', 'CONTEXT', '# M001: Test\n\nFull context after discussion.\n');
@@ -112,21 +107,16 @@ async function main(): Promise<void> {
112
107
  invalidateAllCaches();
113
108
  invalidateStateCache();
114
109
  const state2 = await deriveState(base);
115
- // Should now be pre-planning (has context, but no roadmap yet)
116
- // Actually needs-discussion won't trigger because now CONTEXT exists
117
- // The state should advance past needs-discussion
118
- assertTrue(
110
+ assert.ok(
119
111
  state2.phase !== 'needs-discussion',
120
112
  '#1249: after context write + invalidation → not stuck in needs-discussion',
121
113
  );
122
114
  } finally {
123
115
  cleanup(base);
124
116
  }
125
- }
117
+ });
126
118
 
127
- // ─── 3. State cache TTL expires naturally ─────────────────────────────
128
- console.log('\n=== 3. state cache TTL: fresh reads after 100ms ===');
129
- {
119
+ test("state cache TTL: fresh reads after 100ms", async () => {
130
120
  const base = createBase();
131
121
  try {
132
122
  writeMilestoneFile(base, 'M001', 'CONTEXT', '# M001\n\nDesc.\n');
@@ -134,7 +124,7 @@ async function main(): Promise<void> {
134
124
  invalidateAllCaches();
135
125
  invalidateStateCache();
136
126
  const state1 = await deriveState(base);
137
- assertEq(state1.phase, 'pre-planning', 'initial: pre-planning');
127
+ assert.strictEqual(state1.phase, 'pre-planning', 'initial: pre-planning');
138
128
 
139
129
  // Write roadmap immediately
140
130
  writeMilestoneFile(base, 'M001', 'ROADMAP', [
@@ -157,15 +147,13 @@ async function main(): Promise<void> {
157
147
  invalidateAllCaches();
158
148
  invalidateStateCache();
159
149
  const state3 = await deriveState(base);
160
- assertEq(state3.phase, 'planning', 'after TTL expiry + invalidation → planning');
150
+ assert.strictEqual(state3.phase, 'planning', 'after TTL expiry + invalidation → planning');
161
151
  } finally {
162
152
  cleanup(base);
163
153
  }
164
- }
154
+ });
165
155
 
166
- // ─── 4. Task completion detection after file write ────────────────────
167
- console.log('\n=== 4. task marked done in plan → state advances ===');
168
- {
156
+ test("task marked done in plan state advances", async () => {
169
157
  const base = createBase();
170
158
  try {
171
159
  writeMilestoneFile(base, 'M001', 'CONTEXT', '# M001\n\nDesc.\n');
@@ -194,7 +182,7 @@ async function main(): Promise<void> {
194
182
  invalidateAllCaches();
195
183
  invalidateStateCache();
196
184
  const state1 = await deriveState(base);
197
- assertEq(state1.activeTask?.id, 'T01', 'initial: T01 is active task');
185
+ assert.strictEqual(state1.activeTask?.id, 'T01', 'initial: T01 is active task');
198
186
 
199
187
  // Mark T01 as done by rewriting the plan
200
188
  writeSliceFile(base, 'M001', 'S01', 'PLAN', [
@@ -210,15 +198,13 @@ async function main(): Promise<void> {
210
198
  invalidateAllCaches();
211
199
  invalidateStateCache();
212
200
  const state2 = await deriveState(base);
213
- assertEq(state2.activeTask?.id, 'T02', 'after T01 done → T02 is active task');
201
+ assert.strictEqual(state2.activeTask?.id, 'T02', 'after T01 done → T02 is active task');
214
202
  } finally {
215
203
  cleanup(base);
216
204
  }
217
- }
205
+ });
218
206
 
219
- // ─── 5. Slice completion detection ────────────────────────────────────
220
- console.log('\n=== 5. all tasks done → summarizing phase ===');
221
- {
207
+ test("all tasks done summarizing phase", async () => {
222
208
  const base = createBase();
223
209
  try {
224
210
  writeMilestoneFile(base, 'M001', 'CONTEXT', '# M001\n\nDesc.\n');
@@ -245,7 +231,7 @@ async function main(): Promise<void> {
245
231
  invalidateAllCaches();
246
232
  invalidateStateCache();
247
233
  const state1 = await deriveState(base);
248
- assertEq(state1.phase, 'executing', 'initial: executing');
234
+ assert.strictEqual(state1.phase, 'executing', 'initial: executing');
249
235
 
250
236
  // Mark task done
251
237
  writeSliceFile(base, 'M001', 'S01', 'PLAN', [
@@ -260,15 +246,13 @@ async function main(): Promise<void> {
260
246
  invalidateAllCaches();
261
247
  invalidateStateCache();
262
248
  const state2 = await deriveState(base);
263
- assertEq(state2.phase, 'summarizing', 'after all tasks done → summarizing');
249
+ assert.strictEqual(state2.phase, 'summarizing', 'after all tasks done → summarizing');
264
250
  } finally {
265
251
  cleanup(base);
266
252
  }
267
- }
253
+ });
268
254
 
269
- // ─── 6. Roadmap slice marked doneadvance to next slice ─────────────
270
- console.log('\n=== 6. roadmap slice marked [x] → next slice active ===');
271
- {
255
+ test("roadmap slice marked [x] → next slice active", async () => {
272
256
  const base = createBase();
273
257
  try {
274
258
  writeMilestoneFile(base, 'M001', 'CONTEXT', '# M001\n\nDesc.\n');
@@ -285,7 +269,7 @@ async function main(): Promise<void> {
285
269
  invalidateAllCaches();
286
270
  invalidateStateCache();
287
271
  const state1 = await deriveState(base);
288
- assertEq(state1.activeSlice?.id, 'S01', 'initial: S01 active');
272
+ assert.strictEqual(state1.activeSlice?.id, 'S01', 'initial: S01 active');
289
273
 
290
274
  // Mark S01 as done in roadmap
291
275
  writeMilestoneFile(base, 'M001', 'ROADMAP', [
@@ -302,16 +286,9 @@ async function main(): Promise<void> {
302
286
  invalidateAllCaches();
303
287
  invalidateStateCache();
304
288
  const state2 = await deriveState(base);
305
- assertEq(state2.activeSlice?.id, 'S02', 'after S01 done → S02 active');
289
+ assert.strictEqual(state2.activeSlice?.id, 'S02', 'after S01 done → S02 active');
306
290
  } finally {
307
291
  cleanup(base);
308
292
  }
309
- }
310
-
311
- report();
312
- }
313
-
314
- main().catch((error) => {
315
- console.error(error);
316
- process.exit(1);
293
+ });
317
294
  });