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
@@ -1,4 +1,5 @@
1
- import { createTestContext } from './test-helpers.ts';
1
+ import { describe, test } from 'node:test';
2
+ import assert from 'node:assert/strict';
2
3
  import * as path from 'node:path';
3
4
  import * as os from 'node:os';
4
5
  import * as fs from 'node:fs';
@@ -13,8 +14,6 @@ import {
13
14
  saveDecisionToDb,
14
15
  } from '../db-writer.ts';
15
16
 
16
- const { assertEq, assertTrue, report } = createTestContext();
17
-
18
17
  // ═══════════════════════════════════════════════════════════════════════════
19
18
  // Helpers
20
19
  // ═══════════════════════════════════════════════════════════════════════════
@@ -35,206 +34,199 @@ function cleanupDir(dir: string): void {
35
34
  // Bug reproduction: freeform DECISIONS.md content destroyed (#2301)
36
35
  // ═══════════════════════════════════════════════════════════════════════════
37
36
 
38
- console.log('\n── parseDecisionsTable silently drops freeform content ──');
39
-
40
- {
41
- const freeform = `# Project Decisions
42
-
43
- ## Architecture
44
- We decided to use a microservices architecture because monoliths don't scale.
45
-
46
- ## Database
47
- PostgreSQL was chosen for its reliability and JSONB support.
48
-
49
- ## Deployment
50
- - Kubernetes for orchestration
51
- - Helm charts for packaging
52
- `;
53
-
54
- const parsed = parseDecisionsTable(freeform);
55
- assertEq(parsed.length, 0, 'freeform content yields zero parsed decisions (expected — it is not a table)');
56
- }
57
-
58
- console.log('\n── saveDecisionToDb destroys freeform DECISIONS.md content ──');
59
-
60
- {
61
- const tmpDir = makeTmpDir();
62
- const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
63
- const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
64
- openDatabase(dbPath);
65
-
66
- const freeformContent = `# Project Decisions
67
-
68
- ## Architecture
69
- We decided to use a microservices architecture because monoliths don't scale.
70
-
71
- ## Database
72
- PostgreSQL was chosen for its reliability and JSONB support.
73
-
74
- ## Deployment
75
- - Kubernetes for orchestration
76
- - Helm charts for packaging
77
- `;
78
-
79
- // Pre-populate DECISIONS.md with freeform content
80
- fs.writeFileSync(mdPath, freeformContent, 'utf-8');
81
-
82
- try {
83
- // Save a new decision this should NOT destroy the freeform content
84
- const result = await saveDecisionToDb({
85
- scope: 'testing',
86
- decision: 'Use Jest for unit tests',
87
- choice: 'Jest',
88
- rationale: 'Well-known, good DX',
89
- when_context: 'M001',
90
- }, tmpDir);
91
-
92
- assertEq(result.id, 'D001', 'decision ID assigned correctly');
93
-
94
- // Read back the file
95
- const afterContent = fs.readFileSync(mdPath, 'utf-8');
96
-
97
- // The freeform content MUST still be present
98
- assertTrue(
99
- afterContent.includes('microservices architecture'),
100
- 'freeform architecture section preserved after saveDecisionToDb',
101
- );
102
- assertTrue(
103
- afterContent.includes('PostgreSQL was chosen'),
104
- 'freeform database section preserved after saveDecisionToDb',
105
- );
106
- assertTrue(
107
- afterContent.includes('Kubernetes for orchestration'),
108
- 'freeform deployment section preserved after saveDecisionToDb',
109
- );
110
-
111
- // The new decision MUST also be present
112
- assertTrue(
113
- afterContent.includes('D001'),
114
- 'new decision D001 present in file',
115
- );
116
- assertTrue(
117
- afterContent.includes('Use Jest for unit tests'),
118
- 'new decision text present in file',
119
- );
120
-
121
- // Save a second decision freeform content must still survive
122
- const result2 = await saveDecisionToDb({
123
- scope: 'ci',
124
- decision: 'Use GitHub Actions for CI',
125
- choice: 'GitHub Actions',
126
- rationale: 'Native integration',
127
- when_context: 'M001',
128
- }, tmpDir);
129
-
130
- assertEq(result2.id, 'D002', 'second decision ID assigned correctly');
131
-
132
- const afterContent2 = fs.readFileSync(mdPath, 'utf-8');
133
-
134
- assertTrue(
135
- afterContent2.includes('microservices architecture'),
136
- 'freeform content still preserved after second save',
137
- );
138
- assertTrue(
139
- afterContent2.includes('D001'),
140
- 'first decision still present after second save',
141
- );
142
- assertTrue(
143
- afterContent2.includes('D002'),
144
- 'second decision present after second save',
145
- );
146
- assertTrue(
147
- afterContent2.includes('Use GitHub Actions for CI'),
148
- 'second decision text present in file',
149
- );
150
- } finally {
151
- closeDatabase();
152
- cleanupDir(tmpDir);
153
- }
154
- }
155
-
156
- console.log('\n── saveDecisionToDb with table-format DECISIONS.md still regenerates normally ──');
157
-
158
- {
159
- const tmpDir = makeTmpDir();
160
- const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
161
- const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
162
- openDatabase(dbPath);
163
-
164
- // Pre-populate with canonical table format
165
- const tableContent = `# Decisions Register
166
-
167
- <!-- Append-only. Never edit or remove existing rows.
168
- To reverse a decision, add a new row that supersedes it.
169
- Read this file at the start of any planning or research phase. -->
170
-
171
- | # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |
172
- |---|------|-------|----------|--------|-----------|------------|---------|
173
- | D001 | M001 | arch | Use REST API | REST | Simpler | Yes | human |
174
- `;
175
-
176
- fs.writeFileSync(mdPath, tableContent, 'utf-8');
177
-
178
- try {
179
- const result = await saveDecisionToDb({
180
- scope: 'testing',
181
- decision: 'Use Vitest',
182
- choice: 'Vitest',
183
- rationale: 'Fast',
184
- when_context: 'M001',
185
- }, tmpDir);
186
-
187
- // The pre-existing table decision was NOT in DB, so it won't appear after regen.
188
- // But the new decision should be there.
189
- assertEq(result.id, 'D001', 'gets D001 since DB was empty');
190
-
191
- const afterContent = fs.readFileSync(mdPath, 'utf-8');
192
- // Table-format file gets fully regenerated — this is the normal path
193
- assertTrue(
194
- afterContent.includes('# Decisions Register'),
195
- 'table-format file still has header after save',
196
- );
197
- assertTrue(
198
- afterContent.includes('Use Vitest'),
199
- 'new decision present in regenerated table',
200
- );
201
- } finally {
202
- closeDatabase();
203
- cleanupDir(tmpDir);
204
- }
205
- }
206
-
207
- console.log('\n── saveDecisionToDb with no existing DECISIONS.md creates table ──');
208
-
209
- {
210
- const tmpDir = makeTmpDir();
211
- const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
212
- const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
213
- openDatabase(dbPath);
214
-
215
- // No DECISIONS.md exists at all
216
- assertTrue(!fs.existsSync(mdPath), 'DECISIONS.md does not exist initially');
217
-
218
- try {
219
- const result = await saveDecisionToDb({
220
- scope: 'arch',
221
- decision: 'Brand new decision',
222
- choice: 'Option A',
223
- rationale: 'Best fit',
224
- }, tmpDir);
225
-
226
- assertEq(result.id, 'D001', 'first decision gets D001');
227
- assertTrue(fs.existsSync(mdPath), 'DECISIONS.md created');
228
-
229
- const content = fs.readFileSync(mdPath, 'utf-8');
230
- assertTrue(content.includes('# Decisions Register'), 'new file has header');
231
- assertTrue(content.includes('Brand new decision'), 'new file has decision');
232
- } finally {
233
- closeDatabase();
234
- cleanupDir(tmpDir);
235
- }
236
- }
237
-
238
- // ═══════════════════════════════════════════════════════════════════════════
239
-
240
- report();
37
+ describe('freeform-decisions', () => {
38
+ test('parseDecisionsTable silently drops freeform content', () => {
39
+ const freeform = `# Project Decisions
40
+
41
+ ## Architecture
42
+ We decided to use a microservices architecture because monoliths don't scale.
43
+
44
+ ## Database
45
+ PostgreSQL was chosen for its reliability and JSONB support.
46
+
47
+ ## Deployment
48
+ - Kubernetes for orchestration
49
+ - Helm charts for packaging
50
+ `;
51
+
52
+ const parsed = parseDecisionsTable(freeform);
53
+ assert.deepStrictEqual(parsed.length, 0, 'freeform content yields zero parsed decisions (expected — it is not a table)');
54
+ });
55
+
56
+ test('saveDecisionToDb destroys freeform DECISIONS.md content', async () => {
57
+ const tmpDir = makeTmpDir();
58
+ const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
59
+ const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
60
+ openDatabase(dbPath);
61
+
62
+ const freeformContent = `# Project Decisions
63
+
64
+ ## Architecture
65
+ We decided to use a microservices architecture because monoliths don't scale.
66
+
67
+ ## Database
68
+ PostgreSQL was chosen for its reliability and JSONB support.
69
+
70
+ ## Deployment
71
+ - Kubernetes for orchestration
72
+ - Helm charts for packaging
73
+ `;
74
+
75
+ // Pre-populate DECISIONS.md with freeform content
76
+ fs.writeFileSync(mdPath, freeformContent, 'utf-8');
77
+
78
+ try {
79
+ // Save a new decision — this should NOT destroy the freeform content
80
+ const result = await saveDecisionToDb({
81
+ scope: 'testing',
82
+ decision: 'Use Jest for unit tests',
83
+ choice: 'Jest',
84
+ rationale: 'Well-known, good DX',
85
+ when_context: 'M001',
86
+ }, tmpDir);
87
+
88
+ assert.deepStrictEqual(result.id, 'D001', 'decision ID assigned correctly');
89
+
90
+ // Read back the file
91
+ const afterContent = fs.readFileSync(mdPath, 'utf-8');
92
+
93
+ // The freeform content MUST still be present
94
+ assert.ok(
95
+ afterContent.includes('microservices architecture'),
96
+ 'freeform architecture section preserved after saveDecisionToDb',
97
+ );
98
+ assert.ok(
99
+ afterContent.includes('PostgreSQL was chosen'),
100
+ 'freeform database section preserved after saveDecisionToDb',
101
+ );
102
+ assert.ok(
103
+ afterContent.includes('Kubernetes for orchestration'),
104
+ 'freeform deployment section preserved after saveDecisionToDb',
105
+ );
106
+
107
+ // The new decision MUST also be present
108
+ assert.ok(
109
+ afterContent.includes('D001'),
110
+ 'new decision D001 present in file',
111
+ );
112
+ assert.ok(
113
+ afterContent.includes('Use Jest for unit tests'),
114
+ 'new decision text present in file',
115
+ );
116
+
117
+ // Save a second decision freeform content must still survive
118
+ const result2 = await saveDecisionToDb({
119
+ scope: 'ci',
120
+ decision: 'Use GitHub Actions for CI',
121
+ choice: 'GitHub Actions',
122
+ rationale: 'Native integration',
123
+ when_context: 'M001',
124
+ }, tmpDir);
125
+
126
+ assert.deepStrictEqual(result2.id, 'D002', 'second decision ID assigned correctly');
127
+
128
+ const afterContent2 = fs.readFileSync(mdPath, 'utf-8');
129
+
130
+ assert.ok(
131
+ afterContent2.includes('microservices architecture'),
132
+ 'freeform content still preserved after second save',
133
+ );
134
+ assert.ok(
135
+ afterContent2.includes('D001'),
136
+ 'first decision still present after second save',
137
+ );
138
+ assert.ok(
139
+ afterContent2.includes('D002'),
140
+ 'second decision present after second save',
141
+ );
142
+ assert.ok(
143
+ afterContent2.includes('Use GitHub Actions for CI'),
144
+ 'second decision text present in file',
145
+ );
146
+ } finally {
147
+ closeDatabase();
148
+ cleanupDir(tmpDir);
149
+ }
150
+ });
151
+
152
+ test('saveDecisionToDb with table-format DECISIONS.md still regenerates normally', async () => {
153
+ const tmpDir = makeTmpDir();
154
+ const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
155
+ const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
156
+ openDatabase(dbPath);
157
+
158
+ // Pre-populate with canonical table format
159
+ const tableContent = `# Decisions Register
160
+
161
+ <!-- Append-only. Never edit or remove existing rows.
162
+ To reverse a decision, add a new row that supersedes it.
163
+ Read this file at the start of any planning or research phase. -->
164
+
165
+ | # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |
166
+ |---|------|-------|----------|--------|-----------|------------|---------|
167
+ | D001 | M001 | arch | Use REST API | REST | Simpler | Yes | human |
168
+ `;
169
+
170
+ fs.writeFileSync(mdPath, tableContent, 'utf-8');
171
+
172
+ try {
173
+ const result = await saveDecisionToDb({
174
+ scope: 'testing',
175
+ decision: 'Use Vitest',
176
+ choice: 'Vitest',
177
+ rationale: 'Fast',
178
+ when_context: 'M001',
179
+ }, tmpDir);
180
+
181
+ // The pre-existing table decision was NOT in DB, so it won't appear after regen.
182
+ // But the new decision should be there.
183
+ assert.deepStrictEqual(result.id, 'D001', 'gets D001 since DB was empty');
184
+
185
+ const afterContent = fs.readFileSync(mdPath, 'utf-8');
186
+ // Table-format file gets fully regenerated this is the normal path
187
+ assert.ok(
188
+ afterContent.includes('# Decisions Register'),
189
+ 'table-format file still has header after save',
190
+ );
191
+ assert.ok(
192
+ afterContent.includes('Use Vitest'),
193
+ 'new decision present in regenerated table',
194
+ );
195
+ } finally {
196
+ closeDatabase();
197
+ cleanupDir(tmpDir);
198
+ }
199
+ });
200
+
201
+ test('saveDecisionToDb with no existing DECISIONS.md creates table', async () => {
202
+ const tmpDir = makeTmpDir();
203
+ const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
204
+ const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
205
+ openDatabase(dbPath);
206
+
207
+ // No DECISIONS.md exists at all
208
+ assert.ok(!fs.existsSync(mdPath), 'DECISIONS.md does not exist initially');
209
+
210
+ try {
211
+ const result = await saveDecisionToDb({
212
+ scope: 'arch',
213
+ decision: 'Brand new decision',
214
+ choice: 'Option A',
215
+ rationale: 'Best fit',
216
+ }, tmpDir);
217
+
218
+ assert.deepStrictEqual(result.id, 'D001', 'first decision gets D001');
219
+ assert.ok(fs.existsSync(mdPath), 'DECISIONS.md created');
220
+
221
+ const content = fs.readFileSync(mdPath, 'utf-8');
222
+ assert.ok(content.includes('# Decisions Register'), 'new file has header');
223
+ assert.ok(content.includes('Brand new decision'), 'new file has decision');
224
+ } finally {
225
+ closeDatabase();
226
+ cleanupDir(tmpDir);
227
+ }
228
+ });
229
+
230
+ // ═══════════════════════════════════════════════════════════════════════════
231
+
232
+ });
@@ -1,3 +1,5 @@
1
+ import { describe, test } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  /**
2
4
  * Regression tests for #1997: git locale not forced to C.
3
5
  *
@@ -13,10 +15,6 @@ import { execFileSync } from "node:child_process";
13
15
  import { GIT_NO_PROMPT_ENV } from "../git-constants.ts";
14
16
  import { nativeAddAllWithExclusions } from "../native-git-bridge.ts";
15
17
  import { RUNTIME_EXCLUSION_PATHS } from "../git-service.ts";
16
- import { createTestContext } from "./test-helpers.ts";
17
-
18
- const { assertEq, assertTrue, report } = createTestContext();
19
-
20
18
  function git(cwd: string, ...args: string[]): string {
21
19
  return execFileSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
22
20
  }
@@ -39,27 +37,24 @@ function createFile(base: string, relPath: string, content: string): void {
39
37
  writeFileSync(full, content);
40
38
  }
41
39
 
42
- async function main(): Promise<void> {
40
+ describe('git-locale', async () => {
43
41
  // ─── GIT_NO_PROMPT_ENV includes LC_ALL=C ─────────────────────────────
44
42
 
45
- console.log("\n=== GIT_NO_PROMPT_ENV includes LC_ALL=C ===");
46
43
 
47
- assertEq(
44
+ assert.deepStrictEqual(
48
45
  GIT_NO_PROMPT_ENV.LC_ALL,
49
46
  "C",
50
47
  "GIT_NO_PROMPT_ENV must set LC_ALL to 'C' to force English git output"
51
48
  );
52
49
 
53
- assertTrue(
50
+ assert.ok(
54
51
  "GIT_TERMINAL_PROMPT" in GIT_NO_PROMPT_ENV,
55
52
  "GIT_NO_PROMPT_ENV still contains GIT_TERMINAL_PROMPT"
56
53
  );
57
54
 
58
55
  // ─── nativeAddAllWithExclusions: non-English locale does not throw ───
59
56
 
60
- console.log("\n=== nativeAddAllWithExclusions: non-English locale does not throw ===");
61
-
62
- {
57
+ test('nativeAddAllWithExclusions: non-English locale does not throw', () => {
63
58
  // Simulate what happens on a German system: .gsd is gitignored,
64
59
  // exclusion pathspecs trigger an advisory warning exit code 1.
65
60
  // With LC_ALL=C the English stderr guard should match and suppress.
@@ -89,22 +84,20 @@ async function main(): Promise<void> {
89
84
  if (origLang !== undefined) process.env.LANG = origLang;
90
85
  else delete process.env.LANG;
91
86
 
92
- assertTrue(
87
+ assert.ok(
93
88
  !threw,
94
89
  "nativeAddAllWithExclusions must not throw on non-English locale when .gsd is gitignored (#1997)"
95
90
  );
96
91
 
97
92
  const staged = git(repo, "diff", "--cached", "--name-only");
98
- assertTrue(staged.includes("src/app.ts"), "real file staged despite German locale");
93
+ assert.ok(staged.includes("src/app.ts"), "real file staged despite German locale");
99
94
 
100
95
  rmSync(repo, { recursive: true, force: true });
101
- }
96
+ });
102
97
 
103
98
  // ─── nativeMergeSquash: env is passed (merge-squash stderr is English) ─
104
99
 
105
- console.log("\n=== nativeMergeSquash fallback uses GIT_NO_PROMPT_ENV ===");
106
-
107
- {
100
+ test('nativeMergeSquash fallback uses GIT_NO_PROMPT_ENV', () => {
108
101
  // We verify indirectly: the source code must pass env: GIT_NO_PROMPT_ENV.
109
102
  // Read the source and check for the pattern. This is a static check.
110
103
  const src = readFileSync(
@@ -114,20 +107,13 @@ async function main(): Promise<void> {
114
107
 
115
108
  // Find the nativeMergeSquash function and check it uses GIT_NO_PROMPT_ENV
116
109
  const fnStart = src.indexOf("export function nativeMergeSquash");
117
- assertTrue(fnStart !== -1, "nativeMergeSquash function exists in source");
110
+ assert.ok(fnStart !== -1, "nativeMergeSquash function exists in source");
118
111
 
119
112
  const fnBody = src.slice(fnStart, src.indexOf("\nexport function", fnStart + 1));
120
113
  const hasEnv = fnBody.includes("env: GIT_NO_PROMPT_ENV");
121
- assertTrue(
114
+ assert.ok(
122
115
  hasEnv,
123
116
  "nativeMergeSquash fallback must pass env: GIT_NO_PROMPT_ENV to execFileSync (#1997)"
124
117
  );
125
- }
126
-
127
- report();
128
- }
129
-
130
- main().catch((error) => {
131
- console.error(error);
132
- process.exit(1);
118
+ });
133
119
  });