gsd-pi 2.81.0 → 2.82.0-dev.c22380fc3

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 (521) 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 +371 -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/tools/workflow-tool-executors.js +119 -0
  76. package/dist/resources/extensions/gsd/tui/render-kit.js +74 -0
  77. package/dist/resources/extensions/gsd/watch/header-renderer.js +92 -69
  78. package/dist/resources/extensions/gsd/watch/splash-palette.js +10 -0
  79. package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
  80. package/dist/resources/extensions/gsd/worktree-lifecycle.js +743 -318
  81. package/dist/resources/extensions/gsd/worktree-telemetry.js +3 -1
  82. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  85. package/dist/web/standalone/.next/build-manifest.json +3 -3
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/required-server-files.json +3 -3
  88. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  89. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  99. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  127. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  147. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  157. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  163. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  179. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/index.html +1 -1
  193. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  194. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  195. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  196. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  197. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  198. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  199. package/dist/web/standalone/.next/server/app/page.js +2 -2
  200. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  202. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  203. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  204. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/middleware.js +2 -2
  206. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  208. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  209. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  210. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  211. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  212. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  213. package/dist/web/standalone/.next/static/chunks/app/page-752f1e2ebdaa3e45.js +1 -0
  214. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  215. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  216. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  217. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  218. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  219. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  220. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  221. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  222. package/dist/web/standalone/server.js +1 -1
  223. package/dist/welcome-screen.d.ts +0 -7
  224. package/dist/welcome-screen.js +60 -69
  225. package/package.json +3 -2
  226. package/packages/contracts/dist/rpc.test.js +7 -0
  227. package/packages/contracts/dist/rpc.test.js.map +1 -1
  228. package/packages/contracts/dist/workflow.d.ts +21 -0
  229. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  230. package/packages/contracts/dist/workflow.js +24 -0
  231. package/packages/contracts/dist/workflow.js.map +1 -1
  232. package/packages/contracts/src/rpc.test.ts +8 -0
  233. package/packages/contracts/src/workflow.ts +24 -0
  234. package/packages/daemon/package.json +2 -2
  235. package/packages/mcp-server/README.md +14 -3
  236. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  237. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  238. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  239. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  240. package/packages/mcp-server/package.json +2 -2
  241. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  242. package/packages/mcp-server/src/workflow-tools.test.ts +22 -0
  243. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  244. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  245. package/packages/native/package.json +1 -1
  246. package/packages/pi-agent-core/package.json +1 -1
  247. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  248. package/packages/pi-ai/dist/index.d.ts +2 -2
  249. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  250. package/packages/pi-ai/dist/index.js +1 -1
  251. package/packages/pi-ai/dist/index.js.map +1 -1
  252. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  253. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  254. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  255. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  256. package/packages/pi-ai/package.json +1 -1
  257. package/packages/pi-ai/src/index.ts +7 -2
  258. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  259. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  260. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  261. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts +2 -0
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts.map +1 -0
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js +47 -0
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js.map +1 -0
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +76 -9
  267. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts +2 -0
  269. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts.map +1 -0
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js +40 -0
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js.map +1 -0
  272. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +0 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -1
  274. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +30 -29
  275. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +10 -3
  277. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -1
  278. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  279. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +13 -13
  280. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  281. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +1 -3
  282. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +58 -3
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +2 -2
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +12 -6
  288. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -41
  291. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +0 -1
  293. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  294. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +86 -82
  295. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts +35 -0
  297. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts.map +1 -0
  298. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js +152 -0
  299. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js.map +1 -0
  300. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts +16 -0
  301. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts.map +1 -0
  302. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js +73 -0
  303. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js.map +1 -0
  304. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +1 -1
  305. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +12 -8
  307. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  309. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  310. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  311. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  312. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  313. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +105 -1
  314. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  315. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  316. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +27 -26
  317. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  318. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +9 -6
  319. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  321. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  322. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  323. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  324. package/packages/pi-coding-agent/package.json +1 -1
  325. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  326. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +56 -0
  327. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +113 -9
  328. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +48 -0
  329. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +10 -3
  330. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +43 -42
  331. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +14 -14
  332. package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +64 -3
  333. package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +13 -7
  334. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +15 -42
  335. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -104
  336. package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +196 -0
  337. package/packages/pi-coding-agent/src/modes/interactive/components/tui-style-kit.ts +94 -0
  338. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +14 -9
  339. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
  340. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +106 -1
  341. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +27 -26
  342. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +9 -6
  343. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  344. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  345. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +14 -1
  346. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  347. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
  348. package/packages/pi-tui/dist/overlay-layout.js +9 -6
  349. package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
  350. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  351. package/packages/pi-tui/dist/tui.js +5 -0
  352. package/packages/pi-tui/dist/tui.js.map +1 -1
  353. package/packages/pi-tui/package.json +1 -1
  354. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +20 -1
  355. package/packages/pi-tui/src/overlay-layout.ts +10 -7
  356. package/packages/pi-tui/src/tui.ts +6 -0
  357. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  358. package/packages/rpc-client/package.json +1 -1
  359. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  360. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  361. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  362. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  363. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  364. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  365. package/pkg/dist/modes/interactive/theme/theme.js +105 -1
  366. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  367. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  368. package/pkg/dist/modes/interactive/theme/themes.js +27 -26
  369. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  370. package/pkg/package.json +1 -1
  371. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  372. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  373. package/src/resources/extensions/gsd/auto/contracts.ts +46 -11
  374. package/src/resources/extensions/gsd/auto/loop-deps.ts +9 -5
  375. package/src/resources/extensions/gsd/auto/loop.ts +113 -9
  376. package/src/resources/extensions/gsd/auto/orchestrator.ts +118 -6
  377. package/src/resources/extensions/gsd/auto/phases.ts +158 -19
  378. package/src/resources/extensions/gsd/auto/run-unit.ts +69 -4
  379. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  380. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
  381. package/src/resources/extensions/gsd/auto-dashboard.ts +230 -183
  382. package/src/resources/extensions/gsd/auto-dispatch.ts +15 -1
  383. package/src/resources/extensions/gsd/auto-post-unit.ts +7 -1
  384. package/src/resources/extensions/gsd/auto-prompts.ts +11 -3
  385. package/src/resources/extensions/gsd/auto-recovery.ts +7 -209
  386. package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
  387. package/src/resources/extensions/gsd/auto-start.ts +22 -22
  388. package/src/resources/extensions/gsd/auto-unit-closeout.ts +51 -0
  389. package/src/resources/extensions/gsd/auto-verification.ts +12 -6
  390. package/src/resources/extensions/gsd/auto-worktree.ts +8 -0
  391. package/src/resources/extensions/gsd/auto.ts +411 -106
  392. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -6
  393. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -2
  394. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +5 -8
  395. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  396. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
  397. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +4 -10
  398. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +12 -0
  399. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  400. package/src/resources/extensions/gsd/context-store.ts +120 -1
  401. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  402. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  403. package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
  404. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  405. package/src/resources/extensions/gsd/git-service.ts +2 -0
  406. package/src/resources/extensions/gsd/gsd-db.ts +7 -23
  407. package/src/resources/extensions/gsd/health-widget-core.ts +1 -1
  408. package/src/resources/extensions/gsd/health-widget.ts +6 -10
  409. package/src/resources/extensions/gsd/journal.ts +2 -0
  410. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  411. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  412. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  413. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  414. package/src/resources/extensions/gsd/markdown-renderer.ts +10 -96
  415. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  416. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  417. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  418. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  419. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  420. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  421. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  422. package/src/resources/extensions/gsd/native-git-bridge.ts +14 -13
  423. package/src/resources/extensions/gsd/notification-overlay.ts +50 -46
  424. package/src/resources/extensions/gsd/parallel-merge.ts +61 -34
  425. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +33 -35
  426. package/src/resources/extensions/gsd/prompts/complete-slice.md +14 -12
  427. package/src/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
  428. package/src/resources/extensions/gsd/prompts/discuss.md +20 -2
  429. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  430. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  431. package/src/resources/extensions/gsd/recovery-classification.ts +18 -1
  432. package/src/resources/extensions/gsd/session-lock.ts +41 -0
  433. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
  434. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +337 -0
  435. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +69 -0
  436. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +109 -0
  437. package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
  438. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
  439. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
  440. package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
  441. package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
  442. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
  443. package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +60 -0
  444. package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
  445. package/src/resources/extensions/gsd/state-reconciliation.ts +21 -53
  446. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  447. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
  448. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +99 -0
  449. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +729 -176
  450. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +408 -4
  451. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +292 -4
  452. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +20 -5
  453. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +18 -0
  454. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
  455. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  456. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  457. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +28 -1
  458. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  459. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  460. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  461. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +20 -2
  462. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +44 -0
  463. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  464. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  465. package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
  466. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +10 -0
  467. package/src/resources/extensions/gsd/tests/health-widget.test.ts +14 -4
  468. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  469. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +26 -0
  470. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  471. package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +1 -1
  472. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  473. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +116 -24
  474. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -1
  475. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  476. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  477. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  478. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  479. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1 -1
  480. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  481. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +46 -11
  482. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  483. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  484. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +78 -41
  485. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +44 -0
  486. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +12 -217
  487. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +38 -6
  488. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  489. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +2 -2
  490. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +1 -1
  491. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +32 -1
  492. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  493. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +7 -3
  494. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +6 -3
  495. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  496. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +24 -0
  497. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +71 -58
  498. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +952 -0
  499. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -0
  500. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +121 -1
  501. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +66 -0
  502. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
  503. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +6 -0
  504. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +158 -58
  505. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +597 -118
  506. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +59 -2
  507. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +18 -0
  508. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  509. package/src/resources/extensions/gsd/tui/render-kit.ts +109 -0
  510. package/src/resources/extensions/gsd/watch/header-renderer.ts +121 -79
  511. package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
  512. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  513. package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
  514. package/src/resources/extensions/gsd/worktree-lifecycle.ts +1171 -526
  515. package/src/resources/extensions/gsd/worktree-telemetry.ts +7 -2
  516. package/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +0 -1
  517. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  518. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  519. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +0 -1544
  520. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → Wop3A7KRGyR06H3rla_1-}/_buildManifest.js +0 -0
  521. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → Wop3A7KRGyR06H3rla_1-}/_ssgManifest.js +0 -0
@@ -306,7 +306,7 @@ function importRequirements(gsdDir: string): number {
306
306
  // ─── Hierarchy Artifact Walker ─────────────────────────────────────────────
307
307
 
308
308
  /** Artifact suffixes to look for at each hierarchy level */
309
- const MILESTONE_SUFFIXES = ['ROADMAP', 'CONTEXT', 'RESEARCH', 'ASSESSMENT'];
309
+ const MILESTONE_SUFFIXES = ['ROADMAP', 'CONTEXT', 'RESEARCH', 'ASSESSMENT', 'SUMMARY', 'VALIDATION'];
310
310
  const SLICE_SUFFIXES = ['PLAN', 'SUMMARY', 'RESEARCH', 'CONTEXT', 'ASSESSMENT', 'UAT'];
311
311
  const TASK_SUFFIXES = ['PLAN', 'SUMMARY', 'CONTINUE', 'CONTEXT', 'RESEARCH'];
312
312
 
@@ -1,9 +1,10 @@
1
1
  // GSD2 — Decisions -> memories backfill (ADR-013 step 5)
2
2
  //
3
- // Idempotent one-shot migration that copies every active decisions row into
4
- // the memories table with category="architecture" and a structured_fields
5
- // payload preserving the original gsd_save_decision schema (when_context,
6
- // scope, decision, choice, rationale, made_by, revisable, sourceDecisionId).
3
+ // Idempotent migration that copies every decisions row (active and
4
+ // superseded — see Stage 2a note below) into the memories table with
5
+ // category="architecture" and a structured_fields payload preserving the
6
+ // original gsd_save_decision schema (when_context, scope, decision, choice,
7
+ // rationale, made_by, revisable, superseded_by, sourceDecisionId).
7
8
  //
8
9
  // The backfill exists so the cutover in ADR-013 step 6 can drop the
9
10
  // decisions table without losing schema fidelity. Idempotency is enforced
@@ -14,6 +15,13 @@
14
15
  // only ever fires once per project. Costs O(N) inserts on first run where
15
16
  // N is the active-decisions count; subsequent runs are an O(N) lookup that
16
17
  // finds existing markers and exits.
18
+ //
19
+ // ADR-013 Stage 2a (PR #5755): backfill now includes superseded rows so the
20
+ // DECISIONS.md projection regen can source from memories without losing
21
+ // historical entries. An auto-heal pass runs after the initial migration to
22
+ // pick up superseded_by changes that occurred after the source decision was
23
+ // already migrated (e.g. a fresh md-importer run that introduced a new
24
+ // supersedes-chain).
17
25
 
18
26
  import { isDbAvailable, _getAdapter } from "./gsd-db.js";
19
27
  import { createMemory } from "./memory-store.js";
@@ -31,8 +39,10 @@ interface DecisionRow {
31
39
  superseded_by: string | null;
32
40
  }
33
41
 
42
+ type DecisionContentFields = Pick<DecisionRow, "decision" | "choice" | "rationale">;
43
+
34
44
  /**
35
- * Backfill active decisions rows into the memories table.
45
+ * Backfill decisions rows into the memories table.
36
46
  *
37
47
  * - Idempotent (per-row): every row written carries
38
48
  * `structured_fields.sourceDecisionId = "<decisionId>"`. Each candidate
@@ -41,13 +51,18 @@ interface DecisionRow {
41
51
  * their own `sourceDecisionId` does NOT abort the backfill.
42
52
  * - Best-effort: never throws. Logs and returns 0 on failure so a broken
43
53
  * backfill cannot block agent startup.
44
- * - Active-only: skips rows where `superseded_by IS NOT NULL`. Superseded
45
- * decisions are historical record; the memory store is for active
46
- * knowledge.
54
+ * - Full migration (ADR-013 Stage 2a): both active and superseded rows are
55
+ * migrated. `structured_fields.superseded_by` preserves the supersedes
56
+ * chain so the DECISIONS.md projection regen can source from memories
57
+ * without losing historical entries.
58
+ * - Drift auto-heal: after the initial insert pass, the function updates
59
+ * any pre-existing memory whose `structured_fields.superseded_by` drifted
60
+ * from the source decision (e.g. a fresh md-importer run introduced a
61
+ * new supersedes annotation after the initial migration).
47
62
  *
48
63
  * Returns the number of memories written (0 when already backfilled or
49
- * when the DB has no decisions). Callers can log the result or surface it
50
- * to the user.
64
+ * when the DB has no decisions). Drift-heal updates are not counted in
65
+ * this return — they are logged separately.
51
66
  */
52
67
  export function backfillDecisionsToMemories(): number {
53
68
  if (!isDbAvailable()) return 0;
@@ -56,7 +71,7 @@ export function backfillDecisionsToMemories(): number {
56
71
 
57
72
  try {
58
73
  const decisions = adapter
59
- .prepare("SELECT id, when_context, scope, decision, choice, rationale, made_by, revisable, superseded_by FROM decisions WHERE superseded_by IS NULL")
74
+ .prepare("SELECT id, when_context, scope, decision, choice, rationale, made_by, revisable, superseded_by FROM decisions ORDER BY seq")
60
75
  .all() as Array<Record<string, unknown>>;
61
76
 
62
77
  if (decisions.length === 0) return 0;
@@ -67,10 +82,14 @@ export function backfillDecisionsToMemories(): number {
67
82
  // sentinel would silently abort the backfill if a user manually called
68
83
  // capture_thought with their own structuredFields.sourceDecisionId.
69
84
  const checkExisting = adapter.prepare(
70
- "SELECT 1 FROM memories WHERE structured_fields LIKE :pattern LIMIT 1",
85
+ "SELECT id, structured_fields FROM memories WHERE structured_fields LIKE :pattern LIMIT 1",
86
+ );
87
+ const updateStructuredFields = adapter.prepare(
88
+ "UPDATE memories SET structured_fields = :sf, updated_at = :ts WHERE id = :id",
71
89
  );
72
90
 
73
91
  let written = 0;
92
+ let healed = 0;
74
93
  for (const raw of decisions) {
75
94
  const row: DecisionRow = {
76
95
  id: String(raw["id"] ?? ""),
@@ -85,11 +104,48 @@ export function backfillDecisionsToMemories(): number {
85
104
  };
86
105
  if (!row.id) continue;
87
106
 
88
- // Pattern is anchored to the JSON-stringified shape and the exact
89
- // decision id to avoid prefix collisions (e.g. "D1" vs "D10").
90
- if (checkExisting.get({ ":pattern": `%"sourceDecisionId":"${row.id}"%` })) continue;
107
+ const pattern = `%"sourceDecisionId":"${row.id}"%`;
108
+ const existing = checkExisting.get({ ":pattern": pattern }) as
109
+ | { id: string; structured_fields: string | null }
110
+ | undefined;
91
111
 
92
- const content = synthesizeContent(row);
112
+ if (existing) {
113
+ // Drift auto-heal: if the source decision's superseded_by has changed
114
+ // since the original migration, update the memory in place. Read-side
115
+ // queries reconstruct Decision.superseded_by from this field, so the
116
+ // DECISIONS.md projection stays accurate without us having to track
117
+ // supersedes events at the write site.
118
+ const parsedSf = existing.structured_fields
119
+ ? safeParse(existing.structured_fields)
120
+ : {};
121
+ if (existing.structured_fields && !parsedSf) {
122
+ logWarning(
123
+ "memory-backfill",
124
+ `decisions->memories drift heal skipped for ${row.id}: invalid structured_fields JSON`,
125
+ );
126
+ continue;
127
+ }
128
+ const currentSf = parsedSf ?? {};
129
+ const memorySuperseded =
130
+ typeof currentSf["superseded_by"] === "string" || currentSf["superseded_by"] === null
131
+ ? (currentSf["superseded_by"] as string | null | undefined)
132
+ : null;
133
+ if (memorySuperseded !== row.superseded_by) {
134
+ const merged = {
135
+ ...currentSf,
136
+ superseded_by: row.superseded_by,
137
+ };
138
+ updateStructuredFields.run({
139
+ ":id": existing.id,
140
+ ":sf": JSON.stringify(merged),
141
+ ":ts": new Date().toISOString(),
142
+ });
143
+ healed += 1;
144
+ }
145
+ continue;
146
+ }
147
+
148
+ const content = synthesizeDecisionMemoryContent(row);
93
149
  const id = createMemory({
94
150
  category: "architecture",
95
151
  content,
@@ -104,11 +160,19 @@ export function backfillDecisionsToMemories(): number {
104
160
  rationale: row.rationale,
105
161
  made_by: row.made_by,
106
162
  revisable: row.revisable,
163
+ superseded_by: row.superseded_by,
107
164
  },
108
165
  });
109
166
  if (id) written += 1;
110
167
  }
111
168
 
169
+ if (healed > 0) {
170
+ logWarning(
171
+ "memory-backfill",
172
+ `decisions->memories drift healed: ${healed} row${healed === 1 ? "" : "s"} updated superseded_by`,
173
+ );
174
+ }
175
+
112
176
  return written;
113
177
  } catch (e) {
114
178
  logWarning("memory-backfill", `decisions->memories backfill failed: ${(e as Error).message}`);
@@ -116,6 +180,14 @@ export function backfillDecisionsToMemories(): number {
116
180
  }
117
181
  }
118
182
 
183
+ function safeParse(raw: string): Record<string, unknown> | null {
184
+ try {
185
+ return JSON.parse(raw) as Record<string, unknown>;
186
+ } catch {
187
+ return null;
188
+ }
189
+ }
190
+
119
191
  /**
120
192
  * Combine the decision's structured fields into a 1-3 sentence content
121
193
  * string suitable for keyword retrieval and human review.
@@ -124,7 +196,7 @@ export function backfillDecisionsToMemories(): number {
124
196
  * Truncates each field to keep the synthesized line under ~600 chars so
125
197
  * memory_query rendering stays readable.
126
198
  */
127
- function synthesizeContent(row: DecisionRow): string {
199
+ export function synthesizeDecisionMemoryContent(row: DecisionContentFields): string {
128
200
  const trim = (value: string, max: number): string => {
129
201
  const cleaned = value.replace(/\s+/g, " ").trim();
130
202
  return cleaned.length > max ? cleaned.slice(0, max - 1) + "\u2026" : cleaned;
@@ -0,0 +1,277 @@
1
+ // GSD-2 — ADR-013 Phase 6 preflight scanner.
2
+ //
3
+ // Read-only detection of rows in the legacy knowledge surfaces (decisions
4
+ // table, `.gsd/KNOWLEDGE.md`) that lack a corresponding `memories` row.
5
+ // Runs on session start (and on demand via doctor); never mutates state.
6
+ //
7
+ // The scanner exists so the destructive Phase 6 cutover (#5755) can prove
8
+ // the migration is complete before any tables are dropped. Today's
9
+ // `backfillDecisionsToMemories` writes a `structured_fields.sourceDecisionId`
10
+ // marker on each migrated row; the scanner uses that marker for decisions
11
+ // detection. A `sourceKnowledgeId` marker is reserved for the parallel
12
+ // KNOWLEDGE.md backfill that Phase 6 will introduce — until that ships,
13
+ // every KNOWLEDGE.md row is reported as unmigrated, which is the honest
14
+ // state of the consolidation.
15
+
16
+ import { existsSync, readFileSync } from "node:fs";
17
+
18
+ import { _getAdapter, isDbAvailable } from "./gsd-db.js";
19
+ import { appendNotification } from "./notification-store.js";
20
+ import { resolveGsdRootFile } from "./paths.js";
21
+ import { logWarning } from "./workflow-logger.js";
22
+
23
+ // ─── Types ──────────────────────────────────────────────────────────────────
24
+
25
+ export interface KnowledgeSurfaceReport {
26
+ total: number;
27
+ migrated: number;
28
+ unmigrated: number;
29
+ byTable: { rules: number; patterns: number; lessons: number };
30
+ /** Up to 5 sample row IDs/content for diagnosing what's unmigrated. */
31
+ samples: Array<{ table: "rules" | "patterns" | "lessons"; id: string; row: string }>;
32
+ }
33
+
34
+ export interface DecisionsSurfaceReport {
35
+ total: number;
36
+ migrated: number;
37
+ unmigrated: number;
38
+ /** Up to 5 sample decision IDs with a short content excerpt. */
39
+ samples: Array<{ id: string; decision: string }>;
40
+ }
41
+
42
+ export interface ConsolidationGapReport {
43
+ decisions: DecisionsSurfaceReport;
44
+ knowledge: KnowledgeSurfaceReport;
45
+ /** Sum of unmigrated rows across both surfaces. Zero ⇒ clean preflight. */
46
+ totalGaps: number;
47
+ /** Human-readable single-line summary suitable for notifications + logs. */
48
+ summary: string;
49
+ }
50
+
51
+ // ─── KNOWLEDGE.md parsing ────────────────────────────────────────────────────
52
+
53
+ const KNOWLEDGE_SECTIONS = [
54
+ { table: "rules" as const, heading: "## Rules", idPrefix: "K" },
55
+ { table: "patterns" as const, heading: "## Patterns", idPrefix: "P" },
56
+ { table: "lessons" as const, heading: "## Lessons Learned", idPrefix: "L" },
57
+ ];
58
+
59
+ interface KnowledgeRow {
60
+ table: "rules" | "patterns" | "lessons";
61
+ id: string;
62
+ row: string;
63
+ }
64
+
65
+ /**
66
+ * Parse `.gsd/KNOWLEDGE.md` into rows, one per table entry. Skips the table
67
+ * header and separator lines; ignores rows from unrecognized sections.
68
+ *
69
+ * The format is locked in `files.ts:appendKnowledge` — three `## ` sections
70
+ * (Rules, Patterns, Lessons Learned), each a Markdown table. Row IDs are
71
+ * `K###` / `P###` / `L###`.
72
+ */
73
+ export function parseKnowledgeRows(content: string): KnowledgeRow[] {
74
+ const rows: KnowledgeRow[] = [];
75
+ if (!content.trim()) return rows;
76
+
77
+ // Slice the content into sections by heading. The leading text before the
78
+ // first ## heading is intro prose — ignored.
79
+ const lines = content.split("\n");
80
+ let activeSection: typeof KNOWLEDGE_SECTIONS[number] | undefined;
81
+
82
+ for (const line of lines) {
83
+ const trimmed = line.trim();
84
+ if (trimmed.startsWith("## ")) {
85
+ activeSection = KNOWLEDGE_SECTIONS.find((s) => s.heading === trimmed);
86
+ continue;
87
+ }
88
+ if (!activeSection) continue;
89
+ if (!trimmed.startsWith("|")) continue;
90
+
91
+ // Skip the table header rows: the column-titles line and the |---|---| separator.
92
+ // Real data rows start with `| <prefix>### |`.
93
+ const idMatch = new RegExp(`^\\|\\s*(${activeSection.idPrefix}\\d+)\\s*\\|`).exec(trimmed);
94
+ if (!idMatch) continue;
95
+
96
+ rows.push({
97
+ table: activeSection.table,
98
+ id: idMatch[1] ?? "",
99
+ row: trimmed,
100
+ });
101
+ }
102
+
103
+ return rows;
104
+ }
105
+
106
+ function knowledgeMdContent(basePath: string): string {
107
+ const path = resolveGsdRootFile(basePath, "KNOWLEDGE");
108
+ if (!existsSync(path)) return "";
109
+ try {
110
+ return readFileSync(path, "utf-8");
111
+ } catch {
112
+ return "";
113
+ }
114
+ }
115
+
116
+ // ─── DB queries ──────────────────────────────────────────────────────────────
117
+
118
+ interface DecisionRow {
119
+ id: string;
120
+ decision: string;
121
+ }
122
+
123
+ function getActiveDecisions(): DecisionRow[] {
124
+ if (!isDbAvailable()) return [];
125
+ const adapter = _getAdapter();
126
+ if (!adapter) return [];
127
+ try {
128
+ const rows = adapter
129
+ .prepare(
130
+ "SELECT id, decision FROM decisions WHERE superseded_by IS NULL",
131
+ )
132
+ .all() as Array<Record<string, unknown>>;
133
+ return rows
134
+ .map((row): DecisionRow => ({
135
+ id: String(row["id"] ?? ""),
136
+ decision: String(row["decision"] ?? ""),
137
+ }))
138
+ .filter((row) => row.id.length > 0);
139
+ } catch {
140
+ return [];
141
+ }
142
+ }
143
+
144
+ /**
145
+ * True when a memory row has a `structured_fields` JSON payload containing
146
+ * the given `markerKey: "value"` pair. Matches the LIKE pattern used by
147
+ * `backfillDecisionsToMemories` so the scanner is consistent with the
148
+ * backfill's idempotency check.
149
+ */
150
+ function memoryHasSourceMarker(markerKey: string, value: string): boolean {
151
+ if (!isDbAvailable()) return false;
152
+ const adapter = _getAdapter();
153
+ if (!adapter) return false;
154
+ try {
155
+ const pattern = `%"${markerKey}":"${value}"%`;
156
+ const row = adapter
157
+ .prepare("SELECT 1 FROM memories WHERE structured_fields LIKE :pattern LIMIT 1")
158
+ .get({ ":pattern": pattern });
159
+ return row !== undefined;
160
+ } catch {
161
+ return false;
162
+ }
163
+ }
164
+
165
+ // ─── Public API ──────────────────────────────────────────────────────────────
166
+
167
+ const SAMPLE_LIMIT = 5;
168
+
169
+ /**
170
+ * Scan the legacy knowledge surfaces and return a structured report of what's
171
+ * already in the `memories` table vs what's still unmigrated. Pure detection
172
+ * — no DB writes, no file writes, no notifications.
173
+ */
174
+ export function scanConsolidationGaps(basePath: string): ConsolidationGapReport {
175
+ // ── Decisions ────────────────────────────────────────────────────────
176
+ const decisions = getActiveDecisions();
177
+ const decisionSamples: DecisionsSurfaceReport["samples"] = [];
178
+ let decisionMigrated = 0;
179
+ for (const decision of decisions) {
180
+ if (memoryHasSourceMarker("sourceDecisionId", decision.id)) {
181
+ decisionMigrated += 1;
182
+ continue;
183
+ }
184
+ if (decisionSamples.length < SAMPLE_LIMIT) {
185
+ decisionSamples.push({
186
+ id: decision.id,
187
+ decision: decision.decision.length > 80 ? decision.decision.slice(0, 79) + "…" : decision.decision,
188
+ });
189
+ }
190
+ }
191
+
192
+ // ── KNOWLEDGE.md ─────────────────────────────────────────────────────
193
+ const knowledgeRows = parseKnowledgeRows(knowledgeMdContent(basePath));
194
+ const knowledgeByTable = { rules: 0, patterns: 0, lessons: 0 };
195
+ const knowledgeSamples: KnowledgeSurfaceReport["samples"] = [];
196
+ let knowledgeMigrated = 0;
197
+ for (const row of knowledgeRows) {
198
+ knowledgeByTable[row.table] += 1;
199
+ // Phase 6 will introduce a `sourceKnowledgeId` marker as part of the
200
+ // KNOWLEDGE.md backfill. Until that path ships, this check returns
201
+ // false for every row, which is the honest state of the consolidation.
202
+ if (memoryHasSourceMarker("sourceKnowledgeId", row.id)) {
203
+ knowledgeMigrated += 1;
204
+ continue;
205
+ }
206
+ if (knowledgeSamples.length < SAMPLE_LIMIT) {
207
+ knowledgeSamples.push({
208
+ table: row.table,
209
+ id: row.id,
210
+ row: row.row.length > 100 ? row.row.slice(0, 99) + "…" : row.row,
211
+ });
212
+ }
213
+ }
214
+
215
+ const decisionsReport: DecisionsSurfaceReport = {
216
+ total: decisions.length,
217
+ migrated: decisionMigrated,
218
+ unmigrated: decisions.length - decisionMigrated,
219
+ samples: decisionSamples,
220
+ };
221
+ const knowledgeReport: KnowledgeSurfaceReport = {
222
+ total: knowledgeRows.length,
223
+ migrated: knowledgeMigrated,
224
+ unmigrated: knowledgeRows.length - knowledgeMigrated,
225
+ byTable: knowledgeByTable,
226
+ samples: knowledgeSamples,
227
+ };
228
+
229
+ const totalGaps = decisionsReport.unmigrated + knowledgeReport.unmigrated;
230
+
231
+ // Summary line is intentionally short so it fits in a single notification
232
+ // (notification-store truncates messages over 500 chars). Detail is
233
+ // accessible via getProviderSwitchStats-style callers, not embedded here.
234
+ const parts: string[] = [];
235
+ if (decisionsReport.unmigrated > 0) {
236
+ parts.push(`${decisionsReport.unmigrated} of ${decisionsReport.total} active decisions`);
237
+ }
238
+ if (knowledgeReport.unmigrated > 0) {
239
+ parts.push(`${knowledgeReport.unmigrated} of ${knowledgeReport.total} KNOWLEDGE.md rows`);
240
+ }
241
+ const summary =
242
+ parts.length === 0
243
+ ? "Memory consolidation: all decisions and KNOWLEDGE.md rows are in memories."
244
+ : `Memory consolidation: ${parts.join(" and ")} not yet in memories table. Run /doctor for details.`;
245
+
246
+ return { decisions: decisionsReport, knowledge: knowledgeReport, totalGaps, summary };
247
+ }
248
+
249
+ /**
250
+ * Run the scanner and emit a persistent notification + workflow-logger
251
+ * warning when gaps exist. Best-effort: never throws; a broken scanner
252
+ * cannot block agent startup.
253
+ *
254
+ * Returns the full {@link ConsolidationGapReport} regardless of whether gaps
255
+ * exist (including when `totalGaps === 0`). Returns `null` only when
256
+ * `scanConsolidationGaps` itself throws. `appendNotification` and
257
+ * `logWarning` are called only when `report.totalGaps > 0`.
258
+ *
259
+ * Idempotent at the surface: the notification store applies its own
260
+ * 30-second dedup window keyed on (severity, source, message), so repeated
261
+ * boots with identical gaps produce one notification, not a flood.
262
+ */
263
+ export function reportConsolidationGaps(basePath: string): ConsolidationGapReport | null {
264
+ try {
265
+ const report = scanConsolidationGaps(basePath);
266
+ if (report.totalGaps === 0) return report;
267
+ appendNotification(report.summary, "warning", "workflow-logger");
268
+ logWarning("memory-consolidation", report.summary);
269
+ return report;
270
+ } catch (e) {
271
+ logWarning(
272
+ "memory-consolidation",
273
+ `scanner failed: ${(e as Error).message}`,
274
+ );
275
+ return null;
276
+ }
277
+ }
@@ -34,6 +34,9 @@ export type MigrationImportCounts = ReturnType<typeof migrateFromMarkdown>;
34
34
 
35
35
  function assertMigrationImportMatchesPreview(imported: MigrationImportCounts, preview: MigrationPreview): void {
36
36
  const mismatches: string[] = [];
37
+ if (imported.decisions !== preview.decisions.total) {
38
+ mismatches.push(`decisions ${imported.decisions}/${preview.decisions.total}`);
39
+ }
37
40
  if (imported.hierarchy.milestones !== preview.milestoneCount) {
38
41
  mismatches.push(`milestones ${imported.hierarchy.milestones}/${preview.milestoneCount}`);
39
42
  }
@@ -73,6 +76,7 @@ export async function importWrittenMigrationToDb(
73
76
  /** Format preview stats for embedding in the review prompt. */
74
77
  function formatPreviewStats(preview: MigrationPreview): string {
75
78
  const lines = [
79
+ `- Decisions: ${preview.decisions.total}`,
76
80
  `- Milestones: ${preview.milestoneCount}`,
77
81
  `- Slices: ${preview.totalSlices} (${preview.doneSlices} done — ${preview.sliceCompletionPct}%)`,
78
82
  `- Tasks: ${preview.totalTasks} (${preview.doneTasks} done — ${preview.taskCompletionPct}%)`,
@@ -179,6 +183,7 @@ export async function handleMigrate(
179
183
 
180
184
  // ── Build preview text ─────────────────────────────────────────────────────
181
185
  const lines: string[] = [
186
+ `Decisions: ${preview.decisions.total}`,
182
187
  `Milestones: ${preview.milestoneCount}`,
183
188
  `Slices: ${preview.totalSlices} (${preview.doneSlices} done — ${preview.sliceCompletionPct}%)`,
184
189
  `Tasks: ${preview.totalTasks} (${preview.doneTasks} done — ${preview.taskCompletionPct}%)`,
@@ -4,6 +4,13 @@
4
4
  import type { GSDProject } from './types.js';
5
5
  import type { MigrationPreview } from './writer.js';
6
6
 
7
+ function countCanonicalDecisionRows(content: string): number {
8
+ return content
9
+ .split('\n')
10
+ .filter((line) => /^\|\s*D\d+\s*\|/.test(line.trim()))
11
+ .length;
12
+ }
13
+
7
14
  /**
8
15
  * Compute pre-write statistics from a GSDProject without performing I/O.
9
16
  * Used to show the user what a migration will produce before writing anything.
@@ -36,6 +43,9 @@ export function generatePreview(project: GSDProject): MigrationPreview {
36
43
  }
37
44
 
38
45
  return {
46
+ decisions: {
47
+ total: countCanonicalDecisionRows(project.decisionsContent),
48
+ },
39
49
  milestoneCount: project.milestones.length,
40
50
  totalSlices,
41
51
  totalTasks,
@@ -238,16 +238,53 @@ function normalizeStatus(status: string): 'active' | 'validated' | 'deferred' {
238
238
  return 'active';
239
239
  }
240
240
 
241
+ function normalizeRequirementId(id: string): string | null {
242
+ const match = id.trim().match(/^R(\d+)$/i);
243
+ if (!match) return null;
244
+ return `R${match[1].padStart(3, '0')}`;
245
+ }
246
+
241
247
  function mapRequirements(reqs: PlanningRequirement[]): GSDRequirement[] {
242
248
  let autoId = 0;
249
+ const reservedIds = new Set(
250
+ reqs
251
+ .map((req) => normalizeRequirementId(req.id))
252
+ .filter((id): id is string => id !== null),
253
+ );
254
+ const usedIds = new Set<string>();
255
+
256
+ function nextRequirementId(): string {
257
+ let id = '';
258
+ do {
259
+ autoId++;
260
+ id = padId('R', autoId, 3);
261
+ } while (usedIds.has(id) || reservedIds.has(id));
262
+ usedIds.add(id);
263
+ return id;
264
+ }
265
+
243
266
  return reqs.map((req) => {
244
- autoId++;
267
+ const originalId = req.id.trim();
268
+ const canonicalId = normalizeRequirementId(originalId);
269
+ let id: string;
270
+ let description = req.description;
271
+
272
+ if (canonicalId && !usedIds.has(canonicalId)) {
273
+ id = canonicalId;
274
+ usedIds.add(id);
275
+ } else {
276
+ id = nextRequirementId();
277
+ if (originalId) {
278
+ description = `Legacy ID: ${originalId}\n\n${description}`;
279
+ }
280
+ }
281
+
245
282
  return {
246
- id: req.id && req.id.trim() !== '' ? req.id : padId('R', autoId, 3),
283
+ id,
247
284
  title: req.title,
248
285
  class: 'core-capability',
249
286
  status: normalizeStatus(req.status),
250
- description: req.description,
287
+ description,
251
288
  source: 'inferred',
252
289
  primarySlice: 'none yet',
253
290
  };
@@ -286,7 +323,24 @@ function deriveDecisions(parsed: PlanningProject): string {
286
323
  }
287
324
  }
288
325
  if (decisions.length === 0) return '';
289
- return decisions.map((d) => `- ${d}`).join('\n');
326
+ const lines = [
327
+ '# Decisions Register',
328
+ '',
329
+ '<!-- Append-only. Never edit or remove existing rows.',
330
+ ' To reverse a decision, add a new row that supersedes it.',
331
+ ' Read this file at the start of any planning or research phase. -->',
332
+ '',
333
+ '| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |',
334
+ '|---|------|-------|----------|--------|-----------|------------|---------|',
335
+ ];
336
+
337
+ decisions.forEach((decision, index) => {
338
+ const id = padId('D', index + 1, 3);
339
+ const escaped = decision.replace(/\|/g, '\\|');
340
+ lines.push(`| ${id} | migration | migrated-summary | ${escaped} | ${escaped} | Migrated from legacy summary key-decisions | Yes | agent |`);
341
+ });
342
+
343
+ return lines.join('\n') + '\n';
290
344
  }
291
345
 
292
346
  // ─── Main Entry Point ──────────────────────────────────────────────────────
@@ -37,6 +37,9 @@ export interface WrittenFiles {
37
37
 
38
38
  /** Pre-write statistics computed from a GSDProject without I/O. */
39
39
  export interface MigrationPreview {
40
+ decisions: {
41
+ total: number;
42
+ };
40
43
  milestoneCount: number;
41
44
  totalSlices: number;
42
45
  totalTasks: number;
@@ -374,7 +377,17 @@ export function formatProject(content: string): string {
374
377
  */
375
378
  export function formatDecisions(content: string): string {
376
379
  if (!content || !content.trim()) {
377
- return '# Decisions\n\n<!-- Append-only register of architectural and pattern decisions -->\n\n| ID | Decision | Rationale | Date |\n|----|----------|-----------|------|\n';
380
+ return [
381
+ '# Decisions Register',
382
+ '',
383
+ '<!-- Append-only. Never edit or remove existing rows.',
384
+ ' To reverse a decision, add a new row that supersedes it.',
385
+ ' Read this file at the start of any planning or research phase. -->',
386
+ '',
387
+ '| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |',
388
+ '|---|------|-------|----------|--------|-----------|------------|---------|',
389
+ '',
390
+ ].join('\n');
378
391
  }
379
392
  return content.endsWith('\n') ? content : content + '\n';
380
393
  }
@@ -705,20 +705,21 @@ export function nativeAddTracked(basePath: string): void {
705
705
  gitFileExec(basePath, ["add", "-u"]);
706
706
  }
707
707
 
708
- function isDotGsdIgnored(basePath: string): boolean {
709
- for (const path of [".gsd", ".gsd/"]) {
710
- try {
711
- execFileSync("git", ["check-ignore", "-q", path], {
712
- cwd: basePath,
713
- stdio: "pipe",
714
- env: GIT_NO_PROMPT_ENV,
715
- });
716
- return true;
717
- } catch {
718
- // exit 1 means this form is not ignored; try the next variant
719
- }
708
+ export function nativeIsIgnored(basePath: string, path: string): boolean {
709
+ try {
710
+ execFileSync("git", ["check-ignore", "-q", "--", path], {
711
+ cwd: basePath,
712
+ stdio: "pipe",
713
+ env: GIT_NO_PROMPT_ENV,
714
+ });
715
+ return true;
716
+ } catch {
717
+ return false;
720
718
  }
721
- return false;
719
+ }
720
+
721
+ function isDotGsdIgnored(basePath: string): boolean {
722
+ return [".gsd", ".gsd/"].some(path => nativeIsIgnored(basePath, path));
722
723
  }
723
724
 
724
725
  /**