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
@@ -43,31 +43,36 @@ function makeNoUICtx(cwd: string) {
43
43
 
44
44
  // ─── Scenario 1: No manifest exists ──────────────────────────────────────────
45
45
 
46
- test('secrets gate: no manifest exists — getManifestStatus returns null', async () => {
46
+ test('secrets gate: no manifest exists — getManifestStatus returns null', async (t) => {
47
47
  const tmp = makeTempDir('gate-no-manifest');
48
- try {
49
- // No .gsd directory at all
50
- const result = await getManifestStatus(tmp, 'M001');
51
- assert.strictEqual(result, null, 'should return null when no manifest file exists');
52
- } finally {
53
- rmSync(tmp, { recursive: true, force: true });
54
- }
48
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
49
+
50
+ // No .gsd directory at all
51
+ const result = await getManifestStatus(tmp, 'M001');
52
+ assert.strictEqual(result, null, 'should return null when no manifest file exists');
55
53
  });
56
54
 
57
55
  // ─── Scenario 2: Pending keys exist ─────────────────────────────────────────
58
56
 
59
- test('secrets gate: pending keys exist — gate triggers collection, manifest updated on disk', async () => {
57
+ test('secrets gate: pending keys exist — gate triggers collection, manifest updated on disk', async (t) => {
60
58
  const tmp = makeTempDir('gate-pending');
61
59
  const savedA = process.env.GSD_GATE_TEST_EXISTING;
62
- try {
63
- // Simulate one key already in env
64
- process.env.GSD_GATE_TEST_EXISTING = 'already-here';
65
-
66
- // Ensure pending keys are NOT in env
60
+ t.after(() => {
61
+ delete process.env.GSD_GATE_TEST_EXISTING;
62
+ if (savedA !== undefined) process.env.GSD_GATE_TEST_EXISTING = savedA;
67
63
  delete process.env.GSD_GATE_TEST_PEND_A;
68
64
  delete process.env.GSD_GATE_TEST_PEND_B;
65
+ rmSync(tmp, { recursive: true, force: true });
66
+ });
67
+
68
+ // Simulate one key already in env
69
+ process.env.GSD_GATE_TEST_EXISTING = 'already-here';
70
+
71
+ // Ensure pending keys are NOT in env
72
+ delete process.env.GSD_GATE_TEST_PEND_A;
73
+ delete process.env.GSD_GATE_TEST_PEND_B;
69
74
 
70
- writeManifest(tmp, `# Secrets Manifest
75
+ writeManifest(tmp, `# Secrets Manifest
71
76
 
72
77
  **Milestone:** M001
73
78
  **Generated:** 2025-06-20T10:00:00Z
@@ -97,62 +102,60 @@ test('secrets gate: pending keys exist — gate triggers collection, manifest up
97
102
  1. Already in env
98
103
  `);
99
104
 
100
- // (a) Verify getManifestStatus shows pending keys
101
- const status = await getManifestStatus(tmp, 'M001');
102
- assert.notStrictEqual(status, null, 'manifest should exist');
103
- assert.ok(status!.pending.length > 0, 'should have pending keys');
104
- assert.deepStrictEqual(status!.pending, ['GSD_GATE_TEST_PEND_A', 'GSD_GATE_TEST_PEND_B'], 'pending keys');
105
- assert.deepStrictEqual(status!.existing, ['GSD_GATE_TEST_EXISTING'], 'existing keys');
106
-
107
- // (b) Call collectSecretsFromManifest with no-UI context
108
- // With hasUI: false, collectOneSecret returns null → pending keys become "skipped"
109
- const result = await collectSecretsFromManifest(tmp, 'M001', makeNoUICtx(tmp));
110
-
111
- // (c) Verify return shape
112
- assert.deepStrictEqual(result.applied, [], 'no keys applied (no UI to enter values)');
113
- assert.ok(result.skipped.includes('GSD_GATE_TEST_PEND_A'), 'PEND_A should be skipped');
114
- assert.ok(result.skipped.includes('GSD_GATE_TEST_PEND_B'), 'PEND_B should be skipped');
115
- assert.deepStrictEqual(result.existingSkipped, ['GSD_GATE_TEST_EXISTING']);
116
-
117
- // (d) Verify manifest on disk was updated — pending entries that went through
118
- // collection are now "skipped". The existing-in-env entry retains its manifest
119
- // status ("pending") because collectSecretsFromManifest only updates entries
120
- // that flow through collectOneSecret. At runtime, getManifestStatus overrides
121
- // env-present entries to "existing" regardless of manifest status.
122
- const manifestPath = join(tmp, '.gsd', 'milestones', 'M001', 'M001-SECRETS.md');
123
- const updatedContent = readFileSync(manifestPath, 'utf8');
124
- assert.ok(
125
- updatedContent.includes('**Status:** skipped'),
126
- 'formerly-pending entries should now have status "skipped" in the manifest file',
127
- );
128
- // Count: PEND_A → skipped, PEND_B → skipped, EXISTING stays pending on disk
129
- const skippedMatches = updatedContent.match(/\*\*Status:\*\* skipped/g);
130
- assert.strictEqual(skippedMatches?.length, 2, 'two entries should have status "skipped"');
131
- const pendingMatches = updatedContent.match(/\*\*Status:\*\* pending/g);
132
- assert.strictEqual(pendingMatches?.length, 1, 'one entry (existing-in-env) retains pending on disk');
133
-
134
- // (e) Verify getManifestStatus now shows no pending
135
- const statusAfter = await getManifestStatus(tmp, 'M001');
136
- assert.notStrictEqual(statusAfter, null);
137
- assert.deepStrictEqual(statusAfter!.pending, [], 'no pending keys after collection');
138
- } finally {
139
- delete process.env.GSD_GATE_TEST_EXISTING;
140
- if (savedA !== undefined) process.env.GSD_GATE_TEST_EXISTING = savedA;
141
- delete process.env.GSD_GATE_TEST_PEND_A;
142
- delete process.env.GSD_GATE_TEST_PEND_B;
143
- rmSync(tmp, { recursive: true, force: true });
144
- }
105
+ // (a) Verify getManifestStatus shows pending keys
106
+ const status = await getManifestStatus(tmp, 'M001');
107
+ assert.notStrictEqual(status, null, 'manifest should exist');
108
+ assert.ok(status!.pending.length > 0, 'should have pending keys');
109
+ assert.deepStrictEqual(status!.pending, ['GSD_GATE_TEST_PEND_A', 'GSD_GATE_TEST_PEND_B'], 'pending keys');
110
+ assert.deepStrictEqual(status!.existing, ['GSD_GATE_TEST_EXISTING'], 'existing keys');
111
+
112
+ // (b) Call collectSecretsFromManifest with no-UI context
113
+ // With hasUI: false, collectOneSecret returns null → pending keys become "skipped"
114
+ const result = await collectSecretsFromManifest(tmp, 'M001', makeNoUICtx(tmp));
115
+
116
+ // (c) Verify return shape
117
+ assert.deepStrictEqual(result.applied, [], 'no keys applied (no UI to enter values)');
118
+ assert.ok(result.skipped.includes('GSD_GATE_TEST_PEND_A'), 'PEND_A should be skipped');
119
+ assert.ok(result.skipped.includes('GSD_GATE_TEST_PEND_B'), 'PEND_B should be skipped');
120
+ assert.deepStrictEqual(result.existingSkipped, ['GSD_GATE_TEST_EXISTING']);
121
+
122
+ // (d) Verify manifest on disk was updated — pending entries that went through
123
+ // collection are now "skipped". The existing-in-env entry retains its manifest
124
+ // status ("pending") because collectSecretsFromManifest only updates entries
125
+ // that flow through collectOneSecret. At runtime, getManifestStatus overrides
126
+ // env-present entries to "existing" regardless of manifest status.
127
+ const manifestPath = join(tmp, '.gsd', 'milestones', 'M001', 'M001-SECRETS.md');
128
+ const updatedContent = readFileSync(manifestPath, 'utf8');
129
+ assert.ok(
130
+ updatedContent.includes('**Status:** skipped'),
131
+ 'formerly-pending entries should now have status "skipped" in the manifest file',
132
+ );
133
+ // Count: PEND_A → skipped, PEND_B → skipped, EXISTING stays pending on disk
134
+ const skippedMatches = updatedContent.match(/\*\*Status:\*\* skipped/g);
135
+ assert.strictEqual(skippedMatches?.length, 2, 'two entries should have status "skipped"');
136
+ const pendingMatches = updatedContent.match(/\*\*Status:\*\* pending/g);
137
+ assert.strictEqual(pendingMatches?.length, 1, 'one entry (existing-in-env) retains pending on disk');
138
+
139
+ // (e) Verify getManifestStatus now shows no pending
140
+ const statusAfter = await getManifestStatus(tmp, 'M001');
141
+ assert.notStrictEqual(statusAfter, null);
142
+ assert.deepStrictEqual(statusAfter!.pending, [], 'no pending keys after collection');
145
143
  });
146
144
 
147
145
  // ─── Scenario 3: No pending keys — all collected or in env ──────────────────
148
146
 
149
- test('secrets gate: no pending keys — getManifestStatus shows pending.length === 0', async () => {
147
+ test('secrets gate: no pending keys — getManifestStatus shows pending.length === 0', async (t) => {
150
148
  const tmp = makeTempDir('gate-no-pending');
151
149
  const savedKey = process.env.GSD_GATE_TEST_ENVKEY;
152
- try {
153
- process.env.GSD_GATE_TEST_ENVKEY = 'some-value';
150
+ t.after(() => {
151
+ delete process.env.GSD_GATE_TEST_ENVKEY;
152
+ if (savedKey !== undefined) process.env.GSD_GATE_TEST_ENVKEY = savedKey;
153
+ rmSync(tmp, { recursive: true, force: true });
154
+ });
155
+
156
+ process.env.GSD_GATE_TEST_ENVKEY = 'some-value';
154
157
 
155
- writeManifest(tmp, `# Secrets Manifest
158
+ writeManifest(tmp, `# Secrets Manifest
156
159
 
157
160
  **Milestone:** M001
158
161
  **Generated:** 2025-06-20T10:00:00Z
@@ -182,15 +185,10 @@ test('secrets gate: no pending keys — getManifestStatus shows pending.length =
182
185
  1. In env already
183
186
  `);
184
187
 
185
- const result = await getManifestStatus(tmp, 'M001');
186
- assert.notStrictEqual(result, null, 'manifest should exist');
187
- assert.deepStrictEqual(result!.pending, [], 'no pending keys — gate would skip');
188
- assert.deepStrictEqual(result!.collected, ['ALREADY_COLLECTED']);
189
- assert.deepStrictEqual(result!.skipped, ['ALREADY_SKIPPED']);
190
- assert.deepStrictEqual(result!.existing, ['GSD_GATE_TEST_ENVKEY']);
191
- } finally {
192
- delete process.env.GSD_GATE_TEST_ENVKEY;
193
- if (savedKey !== undefined) process.env.GSD_GATE_TEST_ENVKEY = savedKey;
194
- rmSync(tmp, { recursive: true, force: true });
195
- }
188
+ const result = await getManifestStatus(tmp, 'M001');
189
+ assert.notStrictEqual(result, null, 'manifest should exist');
190
+ assert.deepStrictEqual(result!.pending, [], 'no pending keys — gate would skip');
191
+ assert.deepStrictEqual(result!.collected, ['ALREADY_COLLECTED']);
192
+ assert.deepStrictEqual(result!.skipped, ['ALREADY_SKIPPED']);
193
+ assert.deepStrictEqual(result!.existing, ['GSD_GATE_TEST_ENVKEY']);
196
194
  });
@@ -22,6 +22,8 @@
22
22
  * - The !hasSurvivorBranch block has a needs-discussion handler
23
23
  */
24
24
 
25
+ import { describe, test, afterEach } from "node:test";
26
+ import assert from "node:assert/strict";
25
27
  import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync } from "node:fs";
26
28
  import { join } from "node:path";
27
29
  import { tmpdir } from "node:os";
@@ -30,9 +32,6 @@ import { dirname } from "node:path";
30
32
 
31
33
  import { deriveState } from "../state.ts";
32
34
  import { invalidateAllCaches } from "../cache.ts";
33
- import { createTestContext } from "./test-helpers.ts";
34
-
35
- const { assertEq, assertTrue, report } = createTestContext();
36
35
 
37
36
  // ─── Fixture Helpers ─────────────────────────────────────────────────────────
38
37
 
@@ -76,52 +75,46 @@ function readAutoStartSource(): string {
76
75
  // Tests
77
76
  // ═══════════════════════════════════════════════════════════════════════════════
78
77
 
79
- async function main(): Promise<void> {
78
+ describe("auto-start-needs-discussion (#1726)", () => {
80
79
 
81
- // ─── 1. deriveState returns needs-discussion for CONTEXT-DRAFT only ────────
82
- console.log("\n=== 1. CONTEXT-DRAFT.md only → needs-discussion phase ===");
83
- {
80
+ test("1. CONTEXT-DRAFT.md only needs-discussion phase", async () => {
84
81
  const base = createBase();
85
82
  try {
86
83
  writeContextDraft(base, "M001", "# Draft\nSeed discussion.");
87
84
  invalidateAllCaches();
88
85
  const state = await deriveState(base);
89
- assertEq(state.phase, "needs-discussion",
86
+ assert.strictEqual(state.phase, "needs-discussion",
90
87
  "milestone with only CONTEXT-DRAFT should be needs-discussion");
91
- assertTrue(!!state.activeMilestone,
88
+ assert.ok(!!state.activeMilestone,
92
89
  "activeMilestone should be set for needs-discussion");
93
- assertEq(state.activeMilestone?.id, "M001",
90
+ assert.strictEqual(state.activeMilestone?.id, "M001",
94
91
  "activeMilestone.id should be M001");
95
92
  } finally {
96
93
  cleanup(base);
97
94
  }
98
- }
95
+ });
99
96
 
100
- // ─── 2. Survivor branch filter excludes needs-discussion (#1726 bug 1) ────
101
- console.log("\n=== 2. Survivor branch check excludes needs-discussion ===");
102
- {
97
+ test("2. Survivor branch check excludes needs-discussion", () => {
103
98
  const source = readAutoStartSource();
104
99
 
105
100
  // Find the survivor branch check block (Milestone branch recovery comment)
106
101
  const survivorBlock = source.match(
107
102
  /\/\/ Milestone branch recovery.*?hasSurvivorBranch = nativeBranchExists/s,
108
103
  );
109
- assertTrue(!!survivorBlock,
104
+ assert.ok(!!survivorBlock,
110
105
  "found survivor branch check block in auto-start.ts");
111
106
 
112
107
  if (survivorBlock) {
113
108
  const block = survivorBlock[0];
114
109
  // The condition should only check pre-planning, NOT needs-discussion
115
- assertTrue(!block.includes("needs-discussion"),
110
+ assert.ok(!block.includes("needs-discussion"),
116
111
  "survivor branch filter must NOT include needs-discussion phase");
117
- assertTrue(block.includes("pre-planning"),
112
+ assert.ok(block.includes("pre-planning"),
118
113
  "survivor branch filter should include pre-planning phase");
119
114
  }
120
- }
115
+ });
121
116
 
122
- // ─── 3. needs-discussion handler exists in !hasSurvivorBranch block (#1726 bug 2)
123
- console.log("\n=== 3. needs-discussion handler exists in bootstrap ===");
124
- {
117
+ test("3. needs-discussion handler exists in bootstrap", () => {
125
118
  const source = readAutoStartSource();
126
119
 
127
120
  // After the pre-planning handler, there should be a needs-discussion handler
@@ -129,30 +122,26 @@ async function main(): Promise<void> {
129
122
  const needsDiscussionHandler = source.match(
130
123
  /if\s*\(state\.phase\s*===\s*"needs-discussion"\)\s*\{[^}]*showSmartEntry/s,
131
124
  );
132
- assertTrue(!!needsDiscussionHandler,
125
+ assert.ok(!!needsDiscussionHandler,
133
126
  "needs-discussion handler calling showSmartEntry must exist in !hasSurvivorBranch block");
134
- }
127
+ });
135
128
 
136
- // ─── 4. needs-discussion handler aborts if discussion doesn't promote draft
137
- console.log("\n=== 4. needs-discussion handler has abort path ===");
138
- {
129
+ test("4. needs-discussion handler has abort path", () => {
139
130
  const source = readAutoStartSource();
140
131
 
141
132
  // The handler should check postState.phase !== "needs-discussion" and abort
142
133
  // if discussion didn't promote the draft
143
- assertTrue(
134
+ assert.ok(
144
135
  source.includes('postState.phase !== "needs-discussion"'),
145
136
  "needs-discussion handler must check if phase advanced after showSmartEntry",
146
137
  );
147
- assertTrue(
138
+ assert.ok(
148
139
  source.includes("milestone draft was not promoted"),
149
140
  "needs-discussion handler must have abort message when draft not promoted",
150
141
  );
151
- }
142
+ });
152
143
 
153
- // ─── 5. CONTEXT-DRAFT + CONTEXT + ROADMAP → not needs-discussion ──────────
154
- console.log("\n=== 5. Full context + roadmap → not needs-discussion ===");
155
- {
144
+ test("5. Full context + roadmap → not needs-discussion", async () => {
156
145
  const base = createBase();
157
146
  try {
158
147
  writeContextDraft(base, "M001", "# Draft\nSeed discussion.");
@@ -161,16 +150,14 @@ async function main(): Promise<void> {
161
150
  "# M001: Test\n\n## Slices\n- [ ] **S01: Test Slice** `risk:low` `depends:[]`\n > After this: works\n");
162
151
  invalidateAllCaches();
163
152
  const state = await deriveState(base);
164
- assertTrue(state.phase !== "needs-discussion",
153
+ assert.ok(state.phase !== "needs-discussion",
165
154
  "milestone with full context + roadmap should NOT be needs-discussion");
166
155
  } finally {
167
156
  cleanup(base);
168
157
  }
169
- }
158
+ });
170
159
 
171
- // ─── 6. Verify the two bug conditions cannot produce infinite loop ────────
172
- console.log("\n=== 6. No infinite loop: needs-discussion always routes to showSmartEntry ===");
173
- {
160
+ test("6. No infinite loop: needs-discussion always routes to showSmartEntry", () => {
174
161
  const source = readAutoStartSource();
175
162
 
176
163
  // Verify needs-discussion does NOT appear in auto-dispatch trigger conditions
@@ -180,7 +167,7 @@ async function main(): Promise<void> {
180
167
  /\/\/ Milestone branch recovery.*?let hasSurvivorBranch = false;[\s\S]*?if\s*\([^)]*state\.phase[^)]*\)\s*\{/,
181
168
  );
182
169
  if (survivorSection) {
183
- assertTrue(
170
+ assert.ok(
184
171
  !survivorSection[0].includes("needs-discussion"),
185
172
  "survivor branch phase condition must not mention needs-discussion",
186
173
  );
@@ -190,19 +177,17 @@ async function main(): Promise<void> {
190
177
  const notSurvivorBlock = source.match(
191
178
  /if\s*\(!hasSurvivorBranch\)\s*\{([\s\S]*?)\/\/ Unreachable safety check/,
192
179
  );
193
- assertTrue(!!notSurvivorBlock,
180
+ assert.ok(!!notSurvivorBlock,
194
181
  "found !hasSurvivorBranch block in auto-start.ts");
195
182
  if (notSurvivorBlock) {
196
- assertTrue(
183
+ assert.ok(
197
184
  notSurvivorBlock[1].includes('"needs-discussion"'),
198
185
  "!hasSurvivorBranch block must handle needs-discussion phase",
199
186
  );
200
187
  }
201
- }
188
+ });
202
189
 
203
- // ─── 7. Survivor branch + needs-discussion routes to showSmartEntry (#1726)
204
- console.log("\n=== 7. Survivor branch + needs-discussion routes to showSmartEntry ===");
205
- {
190
+ test("7. Survivor branch + needs-discussion routes to showSmartEntry", () => {
206
191
  const source = readAutoStartSource();
207
192
 
208
193
  // When hasSurvivorBranch is true AND phase is needs-discussion, the code
@@ -210,31 +195,24 @@ async function main(): Promise<void> {
210
195
  const survivorNeedsDiscussion = source.match(
211
196
  /if\s*\(hasSurvivorBranch\s*&&\s*state\.phase\s*===\s*"needs-discussion"\)\s*\{[^}]*showSmartEntry/s,
212
197
  );
213
- assertTrue(!!survivorNeedsDiscussion,
198
+ assert.ok(!!survivorNeedsDiscussion,
214
199
  "hasSurvivorBranch && needs-discussion must route to showSmartEntry");
215
200
 
216
201
  // Verify the handler checks if the discussion succeeded
217
202
  const handlerBlock = source.match(
218
203
  /if\s*\(hasSurvivorBranch\s*&&\s*state\.phase\s*===\s*"needs-discussion"\)\s*\{([\s\S]*?)\n \}/,
219
204
  );
220
- assertTrue(!!handlerBlock,
205
+ assert.ok(!!handlerBlock,
221
206
  "found survivor + needs-discussion handler block");
222
207
  if (handlerBlock) {
223
- assertTrue(
208
+ assert.ok(
224
209
  handlerBlock[1].includes('postState.phase !== "needs-discussion"'),
225
210
  "handler must check if phase advanced after discussion",
226
211
  );
227
- assertTrue(
212
+ assert.ok(
228
213
  handlerBlock[1].includes("releaseLockAndReturn"),
229
214
  "handler must abort if discussion didn't promote draft",
230
215
  );
231
216
  }
232
- }
233
-
234
- report();
235
- }
236
-
237
- main().catch((err) => {
238
- console.error(err);
239
- process.exit(1);
217
+ });
240
218
  });