gsd-pi 2.81.0 → 2.82.0-dev.ed17d078d

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 (503) hide show
  1. package/README.md +60 -30
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
  4. package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
  5. package/dist/resources/extensions/gsd/auto/loop.js +111 -8
  6. package/dist/resources/extensions/gsd/auto/orchestrator.js +113 -6
  7. package/dist/resources/extensions/gsd/auto/phases.js +199 -97
  8. package/dist/resources/extensions/gsd/auto/run-unit.js +66 -3
  9. package/dist/resources/extensions/gsd/auto/session.js +9 -0
  10. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +43 -0
  11. package/dist/resources/extensions/gsd/auto-dashboard.js +182 -178
  12. package/dist/resources/extensions/gsd/auto-dispatch.js +14 -11
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -1
  14. package/dist/resources/extensions/gsd/auto-prompts.js +11 -3
  15. package/dist/resources/extensions/gsd/auto-recovery.js +6 -181
  16. package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -0
  17. package/dist/resources/extensions/gsd/auto-start.js +20 -23
  18. package/dist/resources/extensions/gsd/auto-unit-closeout.js +33 -5
  19. package/dist/resources/extensions/gsd/auto-verification.js +12 -6
  20. package/dist/resources/extensions/gsd/auto-worktree.js +8 -0
  21. package/dist/resources/extensions/gsd/auto.js +386 -106
  22. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +13 -6
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +13 -2
  24. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +4 -8
  25. package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
  26. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -1
  27. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +4 -10
  28. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +9 -0
  29. package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
  30. package/dist/resources/extensions/gsd/context-store.js +112 -0
  31. package/dist/resources/extensions/gsd/db-writer.js +150 -84
  32. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  33. package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
  34. package/dist/resources/extensions/gsd/git-service.js +2 -1
  35. package/dist/resources/extensions/gsd/gsd-db.js +7 -23
  36. package/dist/resources/extensions/gsd/health-widget-core.js +1 -1
  37. package/dist/resources/extensions/gsd/health-widget.js +4 -10
  38. package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
  39. package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
  40. package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
  41. package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
  42. package/dist/resources/extensions/gsd/markdown-renderer.js +6 -96
  43. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  44. package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
  45. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
  46. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  47. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  48. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  49. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  50. package/dist/resources/extensions/gsd/native-git-bridge.js +14 -14
  51. package/dist/resources/extensions/gsd/notification-overlay.js +35 -40
  52. package/dist/resources/extensions/gsd/parallel-merge.js +53 -30
  53. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +25 -33
  54. package/dist/resources/extensions/gsd/prompts/complete-slice.md +14 -12
  55. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
  56. package/dist/resources/extensions/gsd/prompts/discuss.md +20 -2
  57. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  58. package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
  59. package/dist/resources/extensions/gsd/recovery-classification.js +15 -1
  60. package/dist/resources/extensions/gsd/session-lock.js +40 -0
  61. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +131 -0
  62. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +247 -0
  63. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +50 -0
  64. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +87 -0
  65. package/dist/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.js +50 -0
  66. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +124 -0
  67. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +32 -0
  68. package/dist/resources/extensions/gsd/state-reconciliation/errors.js +41 -0
  69. package/dist/resources/extensions/gsd/state-reconciliation/index.js +99 -0
  70. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +24 -0
  71. package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +43 -0
  72. package/dist/resources/extensions/gsd/state-reconciliation/types.js +3 -0
  73. package/dist/resources/extensions/gsd/state-reconciliation.js +5 -26
  74. package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
  75. package/dist/resources/extensions/gsd/tui/render-kit.js +74 -0
  76. package/dist/resources/extensions/gsd/watch/header-renderer.js +92 -69
  77. package/dist/resources/extensions/gsd/watch/splash-palette.js +10 -0
  78. package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
  79. package/dist/resources/extensions/gsd/worktree-lifecycle.js +722 -316
  80. package/dist/resources/extensions/gsd/worktree-telemetry.js +3 -1
  81. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  82. package/dist/web/standalone/.next/BUILD_ID +1 -1
  83. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  84. package/dist/web/standalone/.next/build-manifest.json +3 -3
  85. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  86. package/dist/web/standalone/.next/required-server-files.json +3 -3
  87. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  88. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  98. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  126. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  146. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  156. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  162. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  178. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/index.html +1 -1
  192. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  193. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  194. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  195. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  196. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  197. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  198. package/dist/web/standalone/.next/server/app/page.js +2 -2
  199. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  201. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  202. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  203. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/middleware.js +2 -2
  205. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  207. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  208. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  209. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  210. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  211. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  212. package/dist/web/standalone/.next/static/chunks/app/page-752f1e2ebdaa3e45.js +1 -0
  213. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  214. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  215. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  216. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  217. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  218. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  219. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  220. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  221. package/dist/web/standalone/server.js +1 -1
  222. package/dist/welcome-screen.d.ts +0 -7
  223. package/dist/welcome-screen.js +60 -69
  224. package/package.json +3 -2
  225. package/packages/daemon/package.json +2 -2
  226. package/packages/mcp-server/README.md +2 -0
  227. package/packages/mcp-server/package.json +2 -2
  228. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  229. package/packages/native/package.json +1 -1
  230. package/packages/pi-agent-core/package.json +1 -1
  231. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  232. package/packages/pi-ai/dist/index.d.ts +2 -2
  233. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  234. package/packages/pi-ai/dist/index.js +1 -1
  235. package/packages/pi-ai/dist/index.js.map +1 -1
  236. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  237. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  238. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  239. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  240. package/packages/pi-ai/package.json +1 -1
  241. package/packages/pi-ai/src/index.ts +7 -2
  242. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  243. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  244. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  245. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts +2 -0
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts.map +1 -0
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js +47 -0
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js.map +1 -0
  250. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +76 -9
  251. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts +2 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts.map +1 -0
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js +40 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js.map +1 -0
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +0 -1
  257. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +30 -29
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +10 -3
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +13 -13
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +1 -3
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  267. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +58 -3
  268. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
  269. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +2 -2
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +12 -6
  272. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  274. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -41
  275. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +0 -1
  277. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  278. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +86 -82
  279. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  280. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts +35 -0
  281. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts.map +1 -0
  282. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js +152 -0
  283. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js.map +1 -0
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts +16 -0
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts.map +1 -0
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js +73 -0
  287. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js.map +1 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +1 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +12 -8
  291. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  295. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  296. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +105 -1
  298. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +27 -26
  301. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +9 -6
  303. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  305. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  306. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  307. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  308. package/packages/pi-coding-agent/package.json +1 -1
  309. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  310. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +56 -0
  311. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +113 -9
  312. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +48 -0
  313. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +10 -3
  314. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +43 -42
  315. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +14 -14
  316. package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +64 -3
  317. package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +13 -7
  318. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +15 -42
  319. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -104
  320. package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +196 -0
  321. package/packages/pi-coding-agent/src/modes/interactive/components/tui-style-kit.ts +94 -0
  322. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +14 -9
  323. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
  324. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +106 -1
  325. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +27 -26
  326. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +9 -6
  327. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  328. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  329. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +14 -1
  330. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  331. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
  332. package/packages/pi-tui/dist/overlay-layout.js +9 -6
  333. package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
  334. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  335. package/packages/pi-tui/dist/tui.js +5 -0
  336. package/packages/pi-tui/dist/tui.js.map +1 -1
  337. package/packages/pi-tui/package.json +1 -1
  338. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +20 -1
  339. package/packages/pi-tui/src/overlay-layout.ts +10 -7
  340. package/packages/pi-tui/src/tui.ts +6 -0
  341. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  342. package/packages/rpc-client/package.json +1 -1
  343. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  344. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  345. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  346. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  347. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  348. package/pkg/dist/modes/interactive/theme/theme.js +105 -1
  349. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  350. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  351. package/pkg/dist/modes/interactive/theme/themes.js +27 -26
  352. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  353. package/pkg/package.json +1 -1
  354. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  355. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  356. package/src/resources/extensions/gsd/auto/contracts.ts +46 -11
  357. package/src/resources/extensions/gsd/auto/loop-deps.ts +9 -5
  358. package/src/resources/extensions/gsd/auto/loop.ts +113 -9
  359. package/src/resources/extensions/gsd/auto/orchestrator.ts +118 -6
  360. package/src/resources/extensions/gsd/auto/phases.ts +158 -19
  361. package/src/resources/extensions/gsd/auto/run-unit.ts +69 -4
  362. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  363. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
  364. package/src/resources/extensions/gsd/auto-dashboard.ts +230 -183
  365. package/src/resources/extensions/gsd/auto-dispatch.ts +15 -1
  366. package/src/resources/extensions/gsd/auto-post-unit.ts +7 -1
  367. package/src/resources/extensions/gsd/auto-prompts.ts +11 -3
  368. package/src/resources/extensions/gsd/auto-recovery.ts +7 -209
  369. package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
  370. package/src/resources/extensions/gsd/auto-start.ts +22 -22
  371. package/src/resources/extensions/gsd/auto-unit-closeout.ts +51 -0
  372. package/src/resources/extensions/gsd/auto-verification.ts +12 -6
  373. package/src/resources/extensions/gsd/auto-worktree.ts +8 -0
  374. package/src/resources/extensions/gsd/auto.ts +424 -106
  375. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -6
  376. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -2
  377. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +5 -8
  378. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  379. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
  380. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +4 -10
  381. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +12 -0
  382. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  383. package/src/resources/extensions/gsd/context-store.ts +120 -1
  384. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  385. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  386. package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
  387. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  388. package/src/resources/extensions/gsd/git-service.ts +2 -0
  389. package/src/resources/extensions/gsd/gsd-db.ts +7 -23
  390. package/src/resources/extensions/gsd/health-widget-core.ts +1 -1
  391. package/src/resources/extensions/gsd/health-widget.ts +6 -10
  392. package/src/resources/extensions/gsd/journal.ts +2 -0
  393. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  394. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  395. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  396. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  397. package/src/resources/extensions/gsd/markdown-renderer.ts +10 -96
  398. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  399. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  400. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  401. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  402. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  403. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  404. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  405. package/src/resources/extensions/gsd/native-git-bridge.ts +14 -13
  406. package/src/resources/extensions/gsd/notification-overlay.ts +50 -46
  407. package/src/resources/extensions/gsd/parallel-merge.ts +61 -34
  408. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +33 -35
  409. package/src/resources/extensions/gsd/prompts/complete-slice.md +14 -12
  410. package/src/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
  411. package/src/resources/extensions/gsd/prompts/discuss.md +20 -2
  412. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  413. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  414. package/src/resources/extensions/gsd/recovery-classification.ts +18 -1
  415. package/src/resources/extensions/gsd/session-lock.ts +41 -0
  416. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
  417. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +337 -0
  418. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +69 -0
  419. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +109 -0
  420. package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
  421. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
  422. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
  423. package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
  424. package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
  425. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
  426. package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +60 -0
  427. package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
  428. package/src/resources/extensions/gsd/state-reconciliation.ts +21 -53
  429. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  430. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
  431. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +99 -0
  432. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +729 -176
  433. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +408 -4
  434. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +291 -4
  435. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +20 -5
  436. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +18 -0
  437. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
  438. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  439. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  440. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +28 -1
  441. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  442. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  443. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  444. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +20 -2
  445. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +44 -0
  446. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  447. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  448. package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
  449. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +10 -0
  450. package/src/resources/extensions/gsd/tests/health-widget.test.ts +14 -4
  451. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  452. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +26 -0
  453. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  454. package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +1 -1
  455. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  456. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +116 -24
  457. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -1
  458. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  459. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  460. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  461. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  462. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1 -1
  463. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  464. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +46 -11
  465. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  466. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  467. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +78 -41
  468. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +44 -0
  469. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +12 -217
  470. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +38 -6
  471. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  472. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +2 -2
  473. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +1 -1
  474. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +32 -1
  475. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  476. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +7 -3
  477. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +6 -3
  478. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  479. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +24 -0
  480. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +65 -58
  481. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +952 -0
  482. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -0
  483. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +121 -1
  484. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +66 -0
  485. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
  486. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +6 -0
  487. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +158 -58
  488. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +572 -118
  489. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +59 -2
  490. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +18 -0
  491. package/src/resources/extensions/gsd/tui/render-kit.ts +109 -0
  492. package/src/resources/extensions/gsd/watch/header-renderer.ts +121 -79
  493. package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
  494. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  495. package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
  496. package/src/resources/extensions/gsd/worktree-lifecycle.ts +1151 -524
  497. package/src/resources/extensions/gsd/worktree-telemetry.ts +7 -2
  498. package/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +0 -1
  499. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  500. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  501. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +0 -1544
  502. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → YEvjuT-fsFfYQhDSWtueS}/_buildManifest.js +0 -0
  503. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → YEvjuT-fsFfYQhDSWtueS}/_ssgManifest.js +0 -0
@@ -0,0 +1,348 @@
1
+ // ADR-013 Phase 6 cutover (Stage 3) — destructive lock-in.
2
+ //
3
+ // After this stage, new decisions written via gsd_save_decision land ONLY in
4
+ // the memories table. The decisions table receives no new rows; its existing
5
+ // rows remain for backwards-compat reads until #5756 drops the table.
6
+ //
7
+ // Tests cover five properties:
8
+ // 1. New saveDecisionToDb call does NOT insert into the decisions table
9
+ // 2. The new decision DOES appear as a memory row with sourceDecisionId
10
+ // 3. The rendered DECISIONS.md projection includes the new decision
11
+ // 4. Pre-existing decisions-table rows are untouched
12
+ // 5. Decision IDs are monotonic across both surfaces (max of either + 1)
13
+
14
+ import test from "node:test";
15
+ import assert from "node:assert/strict";
16
+ import {
17
+ existsSync,
18
+ mkdirSync,
19
+ mkdtempSync,
20
+ readFileSync,
21
+ rmSync,
22
+ } from "node:fs";
23
+ import { join } from "node:path";
24
+ import { tmpdir } from "node:os";
25
+
26
+ import {
27
+ _getAdapter,
28
+ closeDatabase,
29
+ insertDecision,
30
+ openDatabase,
31
+ } from "../gsd-db.ts";
32
+ import { saveDecisionToDb } from "../db-writer.ts";
33
+ import {
34
+ getAllDecisionsFromMemories,
35
+ queryDecisions,
36
+ } from "../context-store.ts";
37
+
38
+ function makeTmpBase(): string {
39
+ const base = mkdtempSync(join(tmpdir(), "gsd-decisions-stage3-"));
40
+ mkdirSync(join(base, ".gsd"), { recursive: true });
41
+ openDatabase(join(base, ".gsd", "gsd.db"));
42
+ return base;
43
+ }
44
+
45
+ function cleanup(base: string): void {
46
+ try {
47
+ closeDatabase();
48
+ } catch {
49
+ /* noop */
50
+ }
51
+ try {
52
+ rmSync(base, { recursive: true, force: true });
53
+ } catch {
54
+ /* noop */
55
+ }
56
+ }
57
+
58
+ function countDecisionRows(): number {
59
+ const adapter = _getAdapter();
60
+ if (!adapter) return 0;
61
+ const row = adapter
62
+ .prepare("SELECT COUNT(*) as n FROM decisions")
63
+ .get() as { n: number };
64
+ return row.n;
65
+ }
66
+
67
+ function seedLegacyDecision(args: {
68
+ id: string;
69
+ when_context: string;
70
+ scope: string;
71
+ decision: string;
72
+ choice: string;
73
+ rationale: string;
74
+ superseded_by?: string | null;
75
+ }): void {
76
+ insertDecision({
77
+ id: args.id,
78
+ when_context: args.when_context,
79
+ scope: args.scope,
80
+ decision: args.decision,
81
+ choice: args.choice,
82
+ rationale: args.rationale,
83
+ revisable: "Yes",
84
+ made_by: "agent",
85
+ superseded_by: args.superseded_by ?? null,
86
+ });
87
+ }
88
+
89
+ // ─── Core invariants ────────────────────────────────────────────────────────
90
+
91
+ test("saveDecisionToDb no longer writes to the decisions table", async () => {
92
+ const base = makeTmpBase();
93
+ try {
94
+ const before = countDecisionRows();
95
+ assert.equal(before, 0);
96
+
97
+ await saveDecisionToDb(
98
+ {
99
+ when_context: "M001 discuss",
100
+ scope: "M001",
101
+ decision: "Stage 3 destructive: memories-only writes",
102
+ choice: "Drop the upsertDecision call",
103
+ rationale: "Cutover step required by ADR-013 Phase 6",
104
+ revisable: "Yes",
105
+ made_by: "agent",
106
+ },
107
+ base,
108
+ );
109
+
110
+ const after = countDecisionRows();
111
+ assert.equal(after, 0, "decisions table must remain empty after Stage 3 save");
112
+ } finally {
113
+ cleanup(base);
114
+ }
115
+ });
116
+
117
+ test("saveDecisionToDb writes the new decision into memories with sourceDecisionId", async () => {
118
+ const base = makeTmpBase();
119
+ try {
120
+ const { id } = await saveDecisionToDb(
121
+ {
122
+ when_context: "M001 discuss",
123
+ scope: "M001",
124
+ decision: "Use atomic file writes",
125
+ choice: "atomicWriteSync",
126
+ rationale: "crash-safe markdown projections",
127
+ revisable: "Yes",
128
+ made_by: "agent",
129
+ },
130
+ base,
131
+ );
132
+
133
+ const fromMemories = getAllDecisionsFromMemories();
134
+ assert.equal(fromMemories.length, 1);
135
+ assert.equal(fromMemories[0]?.id, id);
136
+ assert.equal(fromMemories[0]?.decision, "Use atomic file writes");
137
+ } finally {
138
+ cleanup(base);
139
+ }
140
+ });
141
+
142
+ test("DECISIONS.md projection includes the memory-only decision", async () => {
143
+ const base = makeTmpBase();
144
+ try {
145
+ await saveDecisionToDb(
146
+ {
147
+ when_context: "M001 discuss",
148
+ scope: "M001",
149
+ decision: "Adopt SQLite",
150
+ choice: "better-sqlite3",
151
+ rationale: "synchronous + native",
152
+ revisable: "Yes",
153
+ made_by: "agent",
154
+ },
155
+ base,
156
+ );
157
+
158
+ const md = readFileSync(join(base, ".gsd", "DECISIONS.md"), "utf-8");
159
+ assert.match(md, /\| D001 \|/);
160
+ assert.match(md, /Adopt SQLite/);
161
+ assert.match(md, /# Decisions Register/);
162
+ } finally {
163
+ cleanup(base);
164
+ }
165
+ });
166
+
167
+ // ─── Existing decisions table is preserved ──────────────────────────────────
168
+
169
+ test("pre-existing decisions-table rows are untouched by Stage 3 saves", async () => {
170
+ const base = makeTmpBase();
171
+ try {
172
+ // Seed two legacy decisions directly into the table — simulates a
173
+ // pre-cutover project.
174
+ seedLegacyDecision({
175
+ id: "D001",
176
+ when_context: "M001 historical",
177
+ scope: "M001",
178
+ decision: "Legacy decision one",
179
+ choice: "A",
180
+ rationale: "r1",
181
+ });
182
+ seedLegacyDecision({
183
+ id: "D002",
184
+ when_context: "M001 historical",
185
+ scope: "M001",
186
+ decision: "Legacy decision two",
187
+ choice: "B",
188
+ rationale: "r2",
189
+ });
190
+ assert.equal(countDecisionRows(), 2);
191
+
192
+ // New save via the cutover path.
193
+ await saveDecisionToDb(
194
+ {
195
+ when_context: "M001 today",
196
+ scope: "M001",
197
+ decision: "Post-cutover decision",
198
+ choice: "C",
199
+ rationale: "r3",
200
+ revisable: "Yes",
201
+ made_by: "agent",
202
+ },
203
+ base,
204
+ );
205
+
206
+ // Decisions table unchanged.
207
+ assert.equal(countDecisionRows(), 2);
208
+
209
+ // Legacy reads still see the pre-existing rows.
210
+ const fromLegacy = queryDecisions();
211
+ assert.equal(fromLegacy.length, 2);
212
+ assert.deepEqual(
213
+ fromLegacy.map((d) => d.id).sort(),
214
+ ["D001", "D002"],
215
+ );
216
+ } finally {
217
+ cleanup(base);
218
+ }
219
+ });
220
+
221
+ // ─── Cross-surface ID monotonicity ─────────────────────────────────────────
222
+
223
+ test("decision IDs are monotonic across legacy table + memory surfaces", async () => {
224
+ const base = makeTmpBase();
225
+ try {
226
+ // Pre-cutover project with D001..D005 in the legacy table (no memory
227
+ // backfill yet — simulates an upgrade that hasn't run backfill).
228
+ for (let i = 1; i <= 5; i++) {
229
+ seedLegacyDecision({
230
+ id: `D${String(i).padStart(3, "0")}`,
231
+ when_context: "historical",
232
+ scope: "M001",
233
+ decision: `Decision ${i}`,
234
+ choice: "x",
235
+ rationale: "y",
236
+ });
237
+ }
238
+ assert.equal(countDecisionRows(), 5);
239
+
240
+ // First Stage 3 save: must pick the next-after-table ID.
241
+ const a = await saveDecisionToDb(
242
+ {
243
+ when_context: "M001 today",
244
+ scope: "M001",
245
+ decision: "First post-cutover",
246
+ choice: "A",
247
+ rationale: "r",
248
+ revisable: "Yes",
249
+ made_by: "agent",
250
+ },
251
+ base,
252
+ );
253
+ assert.equal(a.id, "D006", "first cutover save must follow the legacy table max (D005 -> D006)");
254
+
255
+ // Second save: must pick the next-after-memory ID.
256
+ const b = await saveDecisionToDb(
257
+ {
258
+ when_context: "M001 today",
259
+ scope: "M001",
260
+ decision: "Second post-cutover",
261
+ choice: "B",
262
+ rationale: "r",
263
+ revisable: "Yes",
264
+ made_by: "agent",
265
+ },
266
+ base,
267
+ );
268
+ assert.equal(b.id, "D007", "second cutover save must follow memory max (D006 -> D007)");
269
+
270
+ // Decisions table still has only the original five.
271
+ assert.equal(countDecisionRows(), 5);
272
+ } finally {
273
+ cleanup(base);
274
+ }
275
+ });
276
+
277
+ test("next-ID falls back to D001 when both surfaces are empty", async () => {
278
+ const base = makeTmpBase();
279
+ try {
280
+ const { id } = await saveDecisionToDb(
281
+ {
282
+ when_context: "M001",
283
+ scope: "M001",
284
+ decision: "First ever",
285
+ choice: "A",
286
+ rationale: "r",
287
+ revisable: "Yes",
288
+ made_by: "agent",
289
+ },
290
+ base,
291
+ );
292
+ assert.equal(id, "D001");
293
+ } finally {
294
+ cleanup(base);
295
+ }
296
+ });
297
+
298
+ test("next-ID skips beyond memory-only entries when the legacy table is empty", async () => {
299
+ const base = makeTmpBase();
300
+ try {
301
+ // Three memory-only saves on a fresh project.
302
+ const a = await saveDecisionToDb(
303
+ { when_context: "M001", scope: "M001", decision: "A", choice: "1", rationale: "r", revisable: "Yes", made_by: "agent" },
304
+ base,
305
+ );
306
+ const b = await saveDecisionToDb(
307
+ { when_context: "M001", scope: "M001", decision: "B", choice: "2", rationale: "r", revisable: "Yes", made_by: "agent" },
308
+ base,
309
+ );
310
+ const c = await saveDecisionToDb(
311
+ { when_context: "M001", scope: "M001", decision: "C", choice: "3", rationale: "r", revisable: "Yes", made_by: "agent" },
312
+ base,
313
+ );
314
+
315
+ assert.deepEqual([a.id, b.id, c.id], ["D001", "D002", "D003"]);
316
+ assert.equal(countDecisionRows(), 0, "no decisions-table writes despite three saves");
317
+ } finally {
318
+ cleanup(base);
319
+ }
320
+ });
321
+
322
+ // ─── Defensive: malformed structured_fields don't break next-ID ────────────
323
+
324
+ test("malformed structuredFields in memories are silently skipped during next-ID computation", async () => {
325
+ const base = makeTmpBase();
326
+ try {
327
+ // Insert a memory with broken JSON in structured_fields. The next-ID
328
+ // logic must not throw.
329
+ const adapter = _getAdapter();
330
+ assert.ok(adapter);
331
+ adapter
332
+ .prepare(
333
+ "INSERT INTO memories (id, category, content, confidence, created_at, updated_at, structured_fields) VALUES ('mem-broken', 'architecture', 'oops', 0.5, datetime('now'), datetime('now'), '{\"sourceDecisionId\":\"D999\"')",
334
+ )
335
+ .run();
336
+
337
+ const { id } = await saveDecisionToDb(
338
+ { when_context: "M001", scope: "M001", decision: "Survivor", choice: "x", rationale: "y", revisable: "Yes", made_by: "agent" },
339
+ base,
340
+ );
341
+
342
+ // Broken JSON for D999 doesn't parse, so the surfaced max stays at 0.
343
+ // The new save must still produce a valid sequential ID.
344
+ assert.equal(id, "D001");
345
+ } finally {
346
+ cleanup(base);
347
+ }
348
+ });
@@ -273,7 +273,16 @@ test("deep project setup: bootstrap can start auto-mode without an active milest
273
273
  shouldUseWorktreeIsolation: () => false,
274
274
  registerSigtermHandler: () => {},
275
275
  lockBase: () => base,
276
- buildLifecycle: () => ({}) as any,
276
+ buildLifecycle: () => ({
277
+ adoptSessionRoot: (sessionBase: string, originalBase?: string) => {
278
+ s.basePath = sessionBase;
279
+ if (originalBase !== undefined) {
280
+ s.originalBasePath = originalBase;
281
+ } else if (!s.originalBasePath) {
282
+ s.originalBasePath = sessionBase;
283
+ }
284
+ },
285
+ }) as any,
277
286
  },
278
287
  {
279
288
  classification: "none",
@@ -378,7 +387,16 @@ test("deep project setup: bootstrap continues queued M002 without milestone cont
378
387
  shouldUseWorktreeIsolation: () => false,
379
388
  registerSigtermHandler: () => {},
380
389
  lockBase: () => base,
381
- buildLifecycle: () => ({}) as any,
390
+ buildLifecycle: () => ({
391
+ adoptSessionRoot: (sessionBase: string, originalBase?: string) => {
392
+ s.basePath = sessionBase;
393
+ if (originalBase !== undefined) {
394
+ s.originalBasePath = originalBase;
395
+ } else if (!s.originalBasePath) {
396
+ s.originalBasePath = sessionBase;
397
+ }
398
+ },
399
+ }) as any,
382
400
  },
383
401
  {
384
402
  classification: "none",
@@ -1,3 +1,6 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Regression tests for complete-milestone dispatch guards.
3
+
1
4
  /**
2
5
  * dispatch-complete-milestone-guard.test.ts — #4324
3
6
  */
@@ -74,3 +77,44 @@ describe("completing-milestone dispatch guard (#4324)", () => {
74
77
  assert.equal(result?.unitId, "M001");
75
78
  });
76
79
  });
80
+
81
+ describe("complete phase dispatch guard (#5683)", () => {
82
+ let base = "";
83
+ const rule = DISPATCH_RULES.find((candidate) => candidate.name === "complete → stop");
84
+ assert.ok(rule, "complete phase terminal rule should exist");
85
+
86
+ afterEach(() => {
87
+ try { closeDatabase(); } catch { /* ignore */ }
88
+ if (base) rmSync(base, { recursive: true, force: true });
89
+ base = "";
90
+ });
91
+
92
+ test("dispatches complete-milestone when derived state is complete but DB milestone is still open", async () => {
93
+ base = makeBase();
94
+ openDatabase(join(base, ".gsd", "gsd.db"));
95
+ insertMilestone({ id: "M001", title: "Milestone One", status: "in_progress" });
96
+
97
+ const ctx = buildDispatchCtx(base);
98
+ ctx.state.phase = "complete";
99
+
100
+ const result = await rule.match(ctx);
101
+
102
+ assert.equal(result?.action, "dispatch");
103
+ assert.equal(result?.unitType, "complete-milestone");
104
+ assert.equal(result?.unitId, "M001");
105
+ });
106
+
107
+ test("stops when derived state is complete and DB milestone is closed", async () => {
108
+ base = makeBase();
109
+ openDatabase(join(base, ".gsd", "gsd.db"));
110
+ insertMilestone({ id: "M001", title: "Milestone One", status: "complete" });
111
+
112
+ const ctx = buildDispatchCtx(base);
113
+ ctx.state.phase = "complete";
114
+
115
+ const result = await rule.match(ctx);
116
+
117
+ assert.equal(result?.action, "stop");
118
+ assert.equal(result?.reason, "All milestones complete.");
119
+ });
120
+ });
@@ -14,6 +14,7 @@ import {
14
14
  import {
15
15
  saveDecisionToDb,
16
16
  } from '../db-writer.ts';
17
+ import { getAllDecisionsFromMemories } from '../context-store.ts';
17
18
 
18
19
  // ═══════════════════════════════════════════════════════════════════════════
19
20
  // Helpers
@@ -31,11 +32,14 @@ function cleanupDir(dir: string): void {
31
32
  } catch { /* swallow */ }
32
33
  }
33
34
 
34
- /** Query all decisions from the DB ordered by seq. */
35
+ /**
36
+ * Query all decisions. ADR-013 Stage 3 (PR #5755): decisions are written
37
+ * exclusively to memories; this helper returns the same Decision shape the
38
+ * previous SELECT * FROM decisions produced so the assertions below stay
39
+ * one-line lookups.
40
+ */
35
41
  function queryAllDecisions(): Array<Record<string, unknown>> {
36
- const adapter = _getAdapter();
37
- if (!adapter) return [];
38
- return adapter.prepare('SELECT * FROM decisions ORDER BY seq').all();
42
+ return getAllDecisionsFromMemories().map((d) => ({ ...d }));
39
43
  }
40
44
 
41
45
  // ═══════════════════════════════════════════════════════════════════════════
@@ -14,7 +14,6 @@ import {
14
14
  isDbAvailable,
15
15
  upsertRequirement,
16
16
  getRequirementById,
17
- getDecisionById,
18
17
  _getAdapter,
19
18
  insertArtifact,
20
19
  } from '../gsd-db.ts';
@@ -26,6 +25,7 @@ import {
26
25
  nextDecisionId,
27
26
  nextRequirementId,
28
27
  } from '../db-writer.ts';
28
+ import { getAllDecisionsFromMemories } from '../context-store.ts';
29
29
  import type { Requirement } from '../types.ts';
30
30
 
31
31
  // ═══════════════════════════════════════════════════════════════════════════
@@ -73,12 +73,16 @@ describe('gsd-tools', () => {
73
73
 
74
74
  assert.deepStrictEqual(result.id, 'D001', 'First decision should be D001');
75
75
 
76
- // Verify DB row exists
77
- const row = getDecisionById('D001');
78
- assert.ok(row !== null, 'Decision D001 should exist in DB');
79
- assert.deepStrictEqual(row!.scope, 'architecture', 'Decision scope should match');
80
- assert.deepStrictEqual(row!.decision, 'Use SQLite for metadata', 'Decision text should match');
81
- assert.deepStrictEqual(row!.choice, 'SQLite', 'Decision choice should match');
76
+ // ADR-013 Stage 3: decisions land in memories, not the legacy decisions
77
+ // table. Verify the memory row carries the same content.
78
+ const memoryDecisions = getAllDecisionsFromMemories();
79
+ assert.equal(memoryDecisions.length, 1, 'one memory row exists after save');
80
+ const memDecision = memoryDecisions[0];
81
+ assert.ok(memDecision, 'memory decision exists after save');
82
+ assert.equal(memDecision.id, 'D001');
83
+ assert.deepStrictEqual(memDecision.scope, 'architecture', 'memory decision scope should match');
84
+ assert.deepStrictEqual(memDecision.decision, 'Use SQLite for metadata', 'memory decision text should match');
85
+ assert.deepStrictEqual(memDecision.choice, 'SQLite', 'memory decision choice should match');
82
86
 
83
87
  // Verify DECISIONS.md was generated
84
88
  const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
@@ -0,0 +1,40 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Visual contract tests for the GSD watch header renderer.
3
+
4
+ import test from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { stripVTControlCharacters } from "node:util";
7
+ import { renderHeaderLines } from "../watch/header-renderer.ts";
8
+ import { splashPalette } from "../watch/splash-palette.ts";
9
+
10
+ function rgbPattern(hex: string): RegExp {
11
+ const cleaned = hex.replace("#", "");
12
+ const r = Number.parseInt(cleaned.slice(0, 2), 16);
13
+ const g = Number.parseInt(cleaned.slice(2, 4), 16);
14
+ const b = Number.parseInt(cleaned.slice(4, 6), 16);
15
+ return new RegExp(`\\x1b\\[38;2;${r};${g};${b}m`);
16
+ }
17
+
18
+ test("renderHeaderLines uses the command-center splash layout", () => {
19
+ const lines = renderHeaderLines(
20
+ {
21
+ model: "claude-sonnet-4-6",
22
+ provider: "anthropic",
23
+ directory: "~/Github/gsd-2",
24
+ branch: "feat/tui-refresh",
25
+ mcpServers: ["context7"],
26
+ },
27
+ 120,
28
+ );
29
+
30
+ const raw = lines.join("\n");
31
+ const plain = stripVTControlCharacters(raw);
32
+
33
+ assert.match(raw, rgbPattern(splashPalette.border), "logo and divider should use the recommended olive border");
34
+ assert.match(raw, rgbPattern(splashPalette.accent), "header accents should use the recommended blue");
35
+ assert.match(plain, /Project Console/);
36
+ assert.match(plain, /\/gsd start/);
37
+ assert.match(plain, /\/gsd templates/);
38
+ assert.match(plain, /claude-sonnet-4-6/);
39
+ assert.match(plain, /Context7 ✓/);
40
+ });
@@ -85,6 +85,11 @@ describe("headless milestone bootstrap — parity with interactive flow", () =>
85
85
  /Do not announce the ready phrase as something you are "about to" do/.test(section),
86
86
  "single-milestone pre-condition must include the 'do not announce intent' guard",
87
87
  );
88
+ assert.ok(/Next steps:/.test(section), "single-milestone handoff must include next steps");
89
+ assert.ok(/\/gsd auto/.test(section), "single-milestone handoff must mention /gsd auto");
90
+ assert.ok(/\/gsd status/.test(section), "single-milestone handoff must mention /gsd status");
91
+ assert.ok(/\/gsd visualize/.test(section), "single-milestone handoff must mention /gsd visualize");
92
+ assert.ok(/\/gsd notifications/.test(section), "single-milestone handoff must mention /gsd notifications");
88
93
  });
89
94
 
90
95
  test("discuss-headless multi-milestone pre-condition uses the non-bypassable checkbox format", () => {
@@ -113,5 +118,10 @@ describe("headless milestone bootstrap — parity with interactive flow", () =>
113
118
  /gates_completed === total/.test(multiSection),
114
119
  "multi-milestone pre-condition must still enforce gates_completed === total",
115
120
  );
121
+ assert.ok(/Next steps:/.test(multiSection), "multi-milestone handoff must include next steps");
122
+ assert.ok(/\/gsd auto/.test(multiSection), "multi-milestone handoff must mention /gsd auto");
123
+ assert.ok(/\/gsd status/.test(multiSection), "multi-milestone handoff must mention /gsd status");
124
+ assert.ok(/\/gsd visualize/.test(multiSection), "multi-milestone handoff must mention /gsd visualize");
125
+ assert.ok(/\/gsd notifications/.test(multiSection), "multi-milestone handoff must mention /gsd notifications");
116
126
  });
117
127
  });
@@ -1,3 +1,6 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Tests for the GSD health widget state and footer hint rendering.
3
+
1
4
  import test from "node:test";
2
5
  import assert from "node:assert/strict";
3
6
  import { mkdirSync, rmSync, writeFileSync } from "node:fs";
@@ -9,6 +12,7 @@ import {
9
12
  formatRelativeTime,
10
13
  type HealthWidgetData,
11
14
  } from "../health-widget-core.ts";
15
+ import { HEALTH_WIDGET_ACTIVE_HINTS } from "../health-widget.ts";
12
16
  import { registerHooks } from "../bootstrap/register-hooks.ts";
13
17
 
14
18
  function makeTempDir(prefix: string): string {
@@ -75,13 +79,11 @@ test("buildHealthLines: none state shows single onboarding line pointing at /gsd
75
79
  assert.match(lines[0]!, /\/gsd/);
76
80
  });
77
81
 
78
- test("buildHealthLines: initialized state shows single setup line pointing at /gsd", (t) => {
82
+ test("buildHealthLines: initialized state shows concise initialized line", (t) => {
79
83
  const lines = buildHealthLines(activeData({ projectState: "initialized" }));
80
84
  assert.equal(lines.length, 1, "renders exactly one line");
81
85
  assert.ok(!/System OK|Budget|Last commit/.test(lines[0]!), "no active-project chrome");
82
- // Distinct from "none" — must mention initialized/setup language and /gsd.
83
- assert.match(lines[0]!, /\/gsd/);
84
- assert.match(lines[0]!, /initiali[sz]ed|setup/i);
86
+ assert.equal(lines[0], " GSD Project Initialized");
85
87
  });
86
88
 
87
89
  test("buildHealthLines: active state with ledger-driven spend shows spent summary", (t) => {
@@ -91,6 +93,14 @@ test("buildHealthLines: active state with ledger-driven spend shows spent summar
91
93
  assert.match(lines[0]!, /Spent: 42\.0¢/);
92
94
  });
93
95
 
96
+ test("health widget active hints include visualization and notifications", () => {
97
+ assert.match(HEALTH_WIDGET_ACTIVE_HINTS, /\/gsd auto to run/);
98
+ assert.match(HEALTH_WIDGET_ACTIVE_HINTS, /\/gsd status for overview/);
99
+ assert.match(HEALTH_WIDGET_ACTIVE_HINTS, /\/gsd visualize to inspect/);
100
+ assert.match(HEALTH_WIDGET_ACTIVE_HINTS, /\/gsd notifications for history/);
101
+ assert.match(HEALTH_WIDGET_ACTIVE_HINTS, /\/gsd help/);
102
+ });
103
+
94
104
  test("buildHealthLines: active state with budget ceiling shows percent summary", (t) => {
95
105
  const lines = buildHealthLines(activeData({ budgetSpent: 2.5, budgetCeiling: 10 }));
96
106
  assert.equal(lines.length, 1);
@@ -1,3 +1,4 @@
1
+ // GSD-2 doctor git integration tests
1
2
  import { describe, test } from 'node:test';
2
3
  import assert from 'node:assert/strict';
3
4
  /**
@@ -761,6 +762,49 @@ describe('doctor-git', async () => {
761
762
  assert.ok(log.includes("gsd snapshot"), "commit is tagged with gsd snapshot");
762
763
  });
763
764
 
765
+ test('stale_uncommitted_changes (skips snapshot when tracked changes contain conflict markers)', async () => {
766
+ const dir = createRepoWithActiveMilestone();
767
+ cleanups.push(dir);
768
+
769
+ const pastDate = new Date(Date.now() - 45 * 60 * 1000).toISOString();
770
+ run(`git commit --amend --no-edit --date="${pastDate}"`, dir);
771
+ execSync(`git commit --amend --no-edit`, {
772
+ cwd: dir,
773
+ stdio: ["ignore", "pipe", "pipe"],
774
+ encoding: "utf-8",
775
+ env: { ...process.env, GIT_COMMITTER_DATE: pastDate },
776
+ });
777
+
778
+ writeFileSync(join(dir, "README.md"), [
779
+ "# test",
780
+ "<<<<<<< Updated upstream",
781
+ "modified content",
782
+ "=======",
783
+ "stashed content",
784
+ ">>>>>>> Stashed changes",
785
+ "",
786
+ ].join("\n"));
787
+
788
+ const commitsBefore = run("git rev-list --count HEAD", dir);
789
+ const fixed = await runGSDDoctor(dir, { fix: true });
790
+ const conflictIssues = fixed.issues.filter(
791
+ i => i.code === ("conflict_markers_in_tracked_files" as typeof i.code),
792
+ );
793
+
794
+ assert.equal(conflictIssues.length, 1, "detects conflict markers before snapshotting");
795
+ assert.equal(conflictIssues[0]?.severity, "error", "conflict marker issue blocks automation");
796
+ assert.equal(conflictIssues[0]?.fixable, false, "conflict marker issue requires manual resolution");
797
+ assert.ok(
798
+ fixed.fixesApplied.some(f => f.includes("gsd snapshot skipped")),
799
+ "fix reports skipped snapshot",
800
+ );
801
+
802
+ const commitsAfter = run("git rev-list --count HEAD", dir);
803
+ assert.equal(commitsAfter, commitsBefore, "no snapshot commit is created");
804
+ assert.equal(run("git diff --cached --name-only", dir), "", "no files are staged");
805
+ assert.match(run("git status --short", dir), /M README\.md/m, "tracked file remains modified");
806
+ });
807
+
764
808
  // ─── Test: stale_uncommitted_changes NOT flagged when recent commit ──
765
809
  test('stale_uncommitted_changes (no false positive on recent commit)', async () => {
766
810
  const dir = createRepoWithActiveMilestone();