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,209 @@
1
+ // ADR-013 follow-up — loadKnowledgeBlock injects only Rules from project
2
+ // KNOWLEDGE.md to avoid duplicating Patterns + Lessons content already
3
+ // injected via loadMemoryBlock (Stage 2b cutover).
4
+ //
5
+ // Global KNOWLEDGE.md (~/.gsd/agent/KNOWLEDGE.md) is NOT memory-projected
6
+ // and still passes through with all three sections intact.
7
+
8
+ import test from "node:test";
9
+ import assert from "node:assert/strict";
10
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { tmpdir } from "node:os";
13
+
14
+ import { loadKnowledgeBlock } from "../bootstrap/system-context.ts";
15
+ import { extractIntroAndRules } from "../knowledge-parser.ts";
16
+
17
+ function makeTmpProject(): string {
18
+ const base = mkdtempSync(join(tmpdir(), "gsd-knowledge-rules-only-"));
19
+ mkdirSync(join(base, ".gsd"), { recursive: true });
20
+ return base;
21
+ }
22
+
23
+ function makeTmpHome(): string {
24
+ const home = mkdtempSync(join(tmpdir(), "gsd-knowledge-home-"));
25
+ mkdirSync(join(home, "agent"), { recursive: true });
26
+ return home;
27
+ }
28
+
29
+ function cleanup(...dirs: string[]): void {
30
+ for (const dir of dirs) {
31
+ try {
32
+ rmSync(dir, { recursive: true, force: true });
33
+ } catch {
34
+ /* noop */
35
+ }
36
+ }
37
+ }
38
+
39
+ const FULL_KNOWLEDGE = `# Project Knowledge
40
+
41
+ Append-only register of project-specific rules, patterns, and lessons learned.
42
+
43
+ ## Rules
44
+
45
+ | # | Scope | Rule | Why | Added |
46
+ |---|-------|------|-----|-------|
47
+ | K001 | project | All timestamps in UTC | clarity | 2026-01-01 |
48
+ | K002 | M001 | Never trust user input | safety | 2026-01-02 |
49
+
50
+ ## Patterns
51
+
52
+ | # | Pattern | Where | Notes |
53
+ |---|---------|-------|-------|
54
+ | P001 | Repository pattern | services/ | guards |
55
+
56
+ ## Lessons Learned
57
+
58
+ | # | What Happened | Root Cause | Fix | Scope |
59
+ |---|--------------|------------|-----|-------|
60
+ | L001 | Cache poisoning | reused key | versioned key | project |
61
+ `;
62
+
63
+ // ─── extractIntroAndRules unit tests ───────────────────────────────────────
64
+
65
+ test("extractIntroAndRules keeps intro + Rules, drops Patterns + Lessons", () => {
66
+ const out = extractIntroAndRules(FULL_KNOWLEDGE);
67
+ assert.match(out, /# Project Knowledge/);
68
+ assert.match(out, /## Rules/);
69
+ assert.match(out, /\| K001 \| project \| All timestamps in UTC/);
70
+ assert.match(out, /\| K002 \| M001 \| Never trust user input/);
71
+
72
+ assert.equal(out.includes("## Patterns"), false, "Patterns heading must be dropped");
73
+ assert.equal(out.includes("P001"), false, "Pattern rows must be dropped");
74
+ assert.equal(out.includes("## Lessons Learned"), false, "Lessons heading must be dropped");
75
+ assert.equal(out.includes("L001"), false, "Lesson rows must be dropped");
76
+ });
77
+
78
+ test("extractIntroAndRules returns content unchanged when no `## Rules` heading", () => {
79
+ const content = "# Notes\n\nfreeform content without standard sections\n";
80
+ assert.equal(extractIntroAndRules(content), content);
81
+ });
82
+
83
+ test("extractIntroAndRules returns empty for empty input", () => {
84
+ assert.equal(extractIntroAndRules(""), "");
85
+ assert.equal(extractIntroAndRules(" \n\n"), "");
86
+ });
87
+
88
+ test("extractIntroAndRules handles Rules as the only section (no Patterns/Lessons to drop)", () => {
89
+ const content = `# Project Knowledge
90
+
91
+ ## Rules
92
+
93
+ | # | Scope | Rule | Why | Added |
94
+ |---|-------|------|-----|-------|
95
+ | K001 | project | only rule | reason | 2026-01-01 |
96
+ `;
97
+ const out = extractIntroAndRules(content);
98
+ assert.match(out, /K001/);
99
+ assert.match(out, /## Rules/);
100
+ });
101
+
102
+ // ─── loadKnowledgeBlock integration ────────────────────────────────────────
103
+
104
+ test("loadKnowledgeBlock trims project KNOWLEDGE.md to intro + Rules", () => {
105
+ const base = makeTmpProject();
106
+ const home = makeTmpHome();
107
+ try {
108
+ writeFileSync(join(base, ".gsd", "KNOWLEDGE.md"), FULL_KNOWLEDGE, "utf-8");
109
+ const { block } = loadKnowledgeBlock(home, base);
110
+
111
+ assert.match(block, /## Project Knowledge/);
112
+ assert.match(block, /K001/);
113
+ assert.match(block, /K002/);
114
+ assert.equal(block.includes("P001"), false, "project Patterns must not appear in the block");
115
+ assert.equal(block.includes("L001"), false, "project Lessons must not appear in the block");
116
+ assert.equal(block.includes("## Patterns"), false);
117
+ assert.equal(block.includes("## Lessons Learned"), false);
118
+ } finally {
119
+ cleanup(base, home);
120
+ }
121
+ });
122
+
123
+ test("loadKnowledgeBlock leaves global KNOWLEDGE.md intact (no memory projection there)", () => {
124
+ const base = makeTmpProject();
125
+ const home = makeTmpHome();
126
+ try {
127
+ writeFileSync(join(home, "agent", "KNOWLEDGE.md"), FULL_KNOWLEDGE, "utf-8");
128
+ const { block, globalSizeKb } = loadKnowledgeBlock(home, base);
129
+
130
+ assert.match(block, /## Global Knowledge/);
131
+ // Global is full-fidelity: all three sections intact.
132
+ assert.match(block, /K001/);
133
+ assert.match(block, /P001/);
134
+ assert.match(block, /L001/);
135
+ assert.match(block, /## Patterns/);
136
+ assert.match(block, /## Lessons Learned/);
137
+ assert.ok(globalSizeKb > 0, "globalSizeKb should report the global file size");
138
+ } finally {
139
+ cleanup(base, home);
140
+ }
141
+ });
142
+
143
+ test("loadKnowledgeBlock with both global and project: global keeps full content, project trimmed", () => {
144
+ const base = makeTmpProject();
145
+ const home = makeTmpHome();
146
+ try {
147
+ writeFileSync(join(home, "agent", "KNOWLEDGE.md"), FULL_KNOWLEDGE, "utf-8");
148
+ writeFileSync(join(base, ".gsd", "KNOWLEDGE.md"), FULL_KNOWLEDGE, "utf-8");
149
+ const { block } = loadKnowledgeBlock(home, base);
150
+
151
+ // Both sections present.
152
+ assert.match(block, /## Global Knowledge/);
153
+ assert.match(block, /## Project Knowledge/);
154
+
155
+ // Project's Patterns/Lessons headings must be gone. But global keeps
156
+ // them, so a substring count of e.g. "## Patterns" should equal 1.
157
+ const patternsCount = (block.match(/## Patterns/g) ?? []).length;
158
+ const lessonsCount = (block.match(/## Lessons Learned/g) ?? []).length;
159
+ assert.equal(patternsCount, 1, "Patterns heading appears exactly once (in global)");
160
+ assert.equal(lessonsCount, 1, "Lessons heading appears exactly once (in global)");
161
+
162
+ // K/P/L rows: K appears twice (global + project), P/L appear once (global).
163
+ const k001Count = (block.match(/K001/g) ?? []).length;
164
+ const p001Count = (block.match(/P001/g) ?? []).length;
165
+ const l001Count = (block.match(/L001/g) ?? []).length;
166
+ assert.equal(k001Count, 2, "K001 in both global and project");
167
+ assert.equal(p001Count, 1, "P001 only in global");
168
+ assert.equal(l001Count, 1, "L001 only in global");
169
+ } finally {
170
+ cleanup(base, home);
171
+ }
172
+ });
173
+
174
+ test("loadKnowledgeBlock returns empty block when neither file exists", () => {
175
+ const base = makeTmpProject();
176
+ const home = makeTmpHome();
177
+ try {
178
+ const result = loadKnowledgeBlock(home, base);
179
+ assert.equal(result.block, "");
180
+ assert.equal(result.globalSizeKb, 0);
181
+ } finally {
182
+ cleanup(base, home);
183
+ }
184
+ });
185
+
186
+ test("loadKnowledgeBlock injects only Rules when project KNOWLEDGE.md has no Patterns/Lessons", () => {
187
+ const base = makeTmpProject();
188
+ const home = makeTmpHome();
189
+ try {
190
+ writeFileSync(
191
+ join(base, ".gsd", "KNOWLEDGE.md"),
192
+ `# Project Knowledge
193
+
194
+ ## Rules
195
+
196
+ | # | Scope | Rule | Why | Added |
197
+ |---|-------|------|-----|-------|
198
+ | K001 | project | rule one | reason | 2026-01-01 |
199
+ `,
200
+ "utf-8",
201
+ );
202
+ const { block } = loadKnowledgeBlock(home, base);
203
+ assert.match(block, /K001/);
204
+ // Block heading reflects the new contract.
205
+ assert.match(block, /Rules from KNOWLEDGE\.md/);
206
+ } finally {
207
+ cleanup(base, home);
208
+ }
209
+ });
@@ -24,8 +24,8 @@ import {
24
24
  renderPlanFromDb,
25
25
  renderTaskPlanFromDb,
26
26
  detectStaleRenders,
27
- repairStaleRenders,
28
27
  } from '../markdown-renderer.ts';
28
+ import { repairStaleRenders } from '../state-reconciliation/drift/stale-render.ts';
29
29
  import {
30
30
  parseRoadmap,
31
31
  parsePlan,
@@ -0,0 +1,316 @@
1
+ // GSD-2 — ADR-013 Phase 6 preflight scanner tests.
2
+ //
3
+ // Locks in the four states the scanner must distinguish:
4
+ // 1. Clean — no gaps, no warning emitted.
5
+ // 2. Decisions gap — active decisions without a migrated memory.
6
+ // 3. KNOWLEDGE.md gap — rows in the legacy markdown without migration.
7
+ // 4. Both gaps — combined summary message.
8
+
9
+ import test from "node:test";
10
+ import assert from "node:assert/strict";
11
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
12
+ import { join } from "node:path";
13
+ import { tmpdir } from "node:os";
14
+
15
+ import {
16
+ openDatabase,
17
+ closeDatabase,
18
+ insertDecision,
19
+ } from "../gsd-db.ts";
20
+ import { createMemory } from "../memory-store.ts";
21
+ import {
22
+ _resetNotificationStore,
23
+ initNotificationStore,
24
+ readNotifications,
25
+ } from "../notification-store.ts";
26
+ import {
27
+ parseKnowledgeRows,
28
+ reportConsolidationGaps,
29
+ scanConsolidationGaps,
30
+ } from "../memory-consolidation-scanner.ts";
31
+
32
+ function makeTmpBase(): string {
33
+ const base = mkdtempSync(join(tmpdir(), "gsd-consolidation-scan-"));
34
+ mkdirSync(join(base, ".gsd"), { recursive: true });
35
+ openDatabase(join(base, ".gsd", "gsd.db"));
36
+ initNotificationStore(base);
37
+ return base;
38
+ }
39
+
40
+ function cleanup(base: string): void {
41
+ try {
42
+ closeDatabase();
43
+ } catch {
44
+ /* noop */
45
+ }
46
+ _resetNotificationStore();
47
+ try {
48
+ rmSync(base, { recursive: true, force: true });
49
+ } catch {
50
+ /* noop */
51
+ }
52
+ }
53
+
54
+ function writeKnowledgeMd(base: string, body: string): void {
55
+ writeFileSync(join(base, ".gsd", "KNOWLEDGE.md"), body, "utf-8");
56
+ }
57
+
58
+ // ─── parseKnowledgeRows ─────────────────────────────────────────────────────
59
+
60
+ test("parseKnowledgeRows extracts entries from the three legacy tables", () => {
61
+ const content = `# Project Knowledge
62
+
63
+ Append-only register.
64
+
65
+ ## Rules
66
+
67
+ | # | Scope | Rule | Why | Added |
68
+ |---|-------|------|-----|-------|
69
+ | K001 | project | Always pin SQLite version | corruption | 2026-01-01 |
70
+ | K002 | M001 | Use UTC | clarity | 2026-01-02 |
71
+
72
+ ## Patterns
73
+
74
+ | # | Pattern | Where | Notes |
75
+ |---|---------|-------|-------|
76
+ | P001 | Repository pattern | services/ | guards |
77
+
78
+ ## Lessons Learned
79
+
80
+ | # | What Happened | Root Cause | Fix | Scope |
81
+ |---|--------------|------------|-----|-------|
82
+ | L001 | Cache poisoning | reused key | versioned key | project |
83
+ `;
84
+
85
+ const rows = parseKnowledgeRows(content);
86
+ assert.equal(rows.length, 4, "should extract 2 rules + 1 pattern + 1 lesson");
87
+ assert.deepEqual(
88
+ rows.map((r) => ({ table: r.table, id: r.id })),
89
+ [
90
+ { table: "rules", id: "K001" },
91
+ { table: "rules", id: "K002" },
92
+ { table: "patterns", id: "P001" },
93
+ { table: "lessons", id: "L001" },
94
+ ],
95
+ );
96
+ });
97
+
98
+ test("parseKnowledgeRows skips header/separator rows and unrecognized sections", () => {
99
+ const content = `## Rules
100
+
101
+ | # | Scope | Rule | Why | Added |
102
+ |---|-------|------|-----|-------|
103
+
104
+ ## Other Section
105
+
106
+ | # | Foo |
107
+ |---|-----|
108
+ | X999 | bar |
109
+ `;
110
+
111
+ // Empty Rules table → 0 rows. Unrecognized "Other Section" is ignored.
112
+ assert.equal(parseKnowledgeRows(content).length, 0);
113
+ });
114
+
115
+ test("parseKnowledgeRows returns empty for empty input", () => {
116
+ assert.deepEqual(parseKnowledgeRows(""), []);
117
+ assert.deepEqual(parseKnowledgeRows(" \n\n"), []);
118
+ });
119
+
120
+ // ─── scanConsolidationGaps ─────────────────────────────────────────────────
121
+
122
+ test("scanConsolidationGaps reports zero gaps when both surfaces are empty", () => {
123
+ const base = makeTmpBase();
124
+ try {
125
+ const report = scanConsolidationGaps(base);
126
+ assert.equal(report.decisions.total, 0);
127
+ assert.equal(report.knowledge.total, 0);
128
+ assert.equal(report.totalGaps, 0);
129
+ assert.match(report.summary, /all decisions and KNOWLEDGE\.md rows are in memories/);
130
+ } finally {
131
+ cleanup(base);
132
+ }
133
+ });
134
+
135
+ test("scanConsolidationGaps detects unmigrated decisions and ignores migrated ones", () => {
136
+ const base = makeTmpBase();
137
+ try {
138
+ insertDecision({
139
+ id: "D001",
140
+ when_context: "2026-01-01",
141
+ scope: "M001",
142
+ decision: "Decision needing migration",
143
+ choice: "A",
144
+ rationale: "because",
145
+ revisable: "yes",
146
+ made_by: "agent",
147
+ superseded_by: null,
148
+ });
149
+ insertDecision({
150
+ id: "D002",
151
+ when_context: "2026-01-02",
152
+ scope: "M001",
153
+ decision: "Already migrated decision",
154
+ choice: "B",
155
+ rationale: "covered",
156
+ revisable: "yes",
157
+ made_by: "agent",
158
+ superseded_by: null,
159
+ });
160
+ // D002 has a corresponding migrated memory; D001 doesn't.
161
+ createMemory({
162
+ category: "architecture",
163
+ content: "Already migrated decision Chose: B. Rationale: covered.",
164
+ scope: "M001",
165
+ structuredFields: { sourceDecisionId: "D002" },
166
+ });
167
+
168
+ const report = scanConsolidationGaps(base);
169
+ assert.equal(report.decisions.total, 2);
170
+ assert.equal(report.decisions.migrated, 1);
171
+ assert.equal(report.decisions.unmigrated, 1);
172
+ assert.equal(report.decisions.samples.length, 1);
173
+ assert.equal(report.decisions.samples[0]?.id, "D001");
174
+ assert.equal(report.totalGaps, 1);
175
+ assert.match(report.summary, /1 of 2 active decisions/);
176
+ } finally {
177
+ cleanup(base);
178
+ }
179
+ });
180
+
181
+ test("scanConsolidationGaps skips superseded decisions (historical record only)", () => {
182
+ const base = makeTmpBase();
183
+ try {
184
+ insertDecision({
185
+ id: "D001",
186
+ when_context: "2026-01-01",
187
+ scope: "M001",
188
+ decision: "Superseded — does not need migration",
189
+ choice: "A",
190
+ rationale: "old",
191
+ revisable: "yes",
192
+ made_by: "agent",
193
+ superseded_by: "D002",
194
+ });
195
+
196
+ const report = scanConsolidationGaps(base);
197
+ assert.equal(report.decisions.total, 0, "superseded decisions excluded from active count");
198
+ assert.equal(report.totalGaps, 0);
199
+ } finally {
200
+ cleanup(base);
201
+ }
202
+ });
203
+
204
+ test("scanConsolidationGaps detects unmigrated KNOWLEDGE.md rows by table", () => {
205
+ const base = makeTmpBase();
206
+ try {
207
+ writeKnowledgeMd(
208
+ base,
209
+ `## Rules
210
+
211
+ | # | Scope | Rule | Why | Added |
212
+ |---|-------|------|-----|-------|
213
+ | K001 | project | Pin SQLite | corruption | 2026-01-01 |
214
+ | K002 | M001 | UTC only | clarity | 2026-01-02 |
215
+
216
+ ## Patterns
217
+
218
+ | # | Pattern | Where | Notes |
219
+ |---|---------|-------|-------|
220
+ | P001 | Repository | services/ | guards |
221
+
222
+ ## Lessons Learned
223
+
224
+ | # | What Happened | Root Cause | Fix | Scope |
225
+ |---|--------------|------------|-----|-------|
226
+ `,
227
+ );
228
+
229
+ const report = scanConsolidationGaps(base);
230
+ assert.equal(report.knowledge.total, 3);
231
+ assert.equal(report.knowledge.unmigrated, 3, "no sourceKnowledgeId markers exist yet");
232
+ assert.deepEqual(report.knowledge.byTable, { rules: 2, patterns: 1, lessons: 0 });
233
+ assert.equal(report.knowledge.samples.length, 3);
234
+ assert.equal(report.totalGaps, 3);
235
+ assert.match(report.summary, /3 of 3 KNOWLEDGE\.md rows/);
236
+ } finally {
237
+ cleanup(base);
238
+ }
239
+ });
240
+
241
+ test("scanConsolidationGaps combines decisions and KNOWLEDGE.md gaps in summary", () => {
242
+ const base = makeTmpBase();
243
+ try {
244
+ insertDecision({
245
+ id: "D001",
246
+ when_context: "2026-01-01",
247
+ scope: "M001",
248
+ decision: "Unmigrated decision",
249
+ choice: "A",
250
+ rationale: "x",
251
+ revisable: "yes",
252
+ made_by: "agent",
253
+ superseded_by: null,
254
+ });
255
+ writeKnowledgeMd(
256
+ base,
257
+ `## Rules
258
+
259
+ | # | Scope | Rule | Why | Added |
260
+ |---|-------|------|-----|-------|
261
+ | K001 | project | Some rule | reason | 2026-01-01 |
262
+ `,
263
+ );
264
+
265
+ const report = scanConsolidationGaps(base);
266
+ assert.equal(report.totalGaps, 2);
267
+ assert.match(report.summary, /1 of 1 active decisions/);
268
+ assert.match(report.summary, /1 of 1 KNOWLEDGE\.md rows/);
269
+ } finally {
270
+ cleanup(base);
271
+ }
272
+ });
273
+
274
+ // ─── reportConsolidationGaps ───────────────────────────────────────────────
275
+
276
+ test("reportConsolidationGaps emits a notification + warning when gaps exist", () => {
277
+ const base = makeTmpBase();
278
+ try {
279
+ insertDecision({
280
+ id: "D001",
281
+ when_context: "2026-01-01",
282
+ scope: "M001",
283
+ decision: "Unmigrated",
284
+ choice: "A",
285
+ rationale: "x",
286
+ revisable: "yes",
287
+ made_by: "agent",
288
+ superseded_by: null,
289
+ });
290
+
291
+ const report = reportConsolidationGaps(base);
292
+ assert.ok(report);
293
+ assert.equal(report.totalGaps, 1);
294
+
295
+ const notifications = readNotifications(base);
296
+ const gapNotifs = notifications.filter((n) => n.message.includes("Memory consolidation"));
297
+ assert.ok(gapNotifs.length >= 1, "a consolidation notification should be persisted");
298
+ assert.equal(gapNotifs[0]?.severity, "warning");
299
+ } finally {
300
+ cleanup(base);
301
+ }
302
+ });
303
+
304
+ test("reportConsolidationGaps stays silent when there are no gaps", () => {
305
+ const base = makeTmpBase();
306
+ try {
307
+ const report = reportConsolidationGaps(base);
308
+ assert.ok(report);
309
+ assert.equal(report.totalGaps, 0);
310
+ const notifications = readNotifications(base);
311
+ const gapNotifs = notifications.filter((n) => n.message.includes("not yet in memories"));
312
+ assert.equal(gapNotifs.length, 0, "no warning notification when clean");
313
+ } finally {
314
+ cleanup(base);
315
+ }
316
+ });
@@ -29,20 +29,25 @@
29
29
 
30
30
  import { describe, test, beforeEach, afterEach } from "node:test";
31
31
  import assert from "node:assert/strict";
32
- import { mkdtempSync, rmSync, mkdirSync } from "node:fs";
32
+ import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from "node:fs";
33
33
  import { join } from "node:path";
34
34
  import { tmpdir } from "node:os";
35
35
 
36
- import { WorktreeLifecycle, type WorktreeLifecycleDeps } from "../worktree-lifecycle.ts";
36
+ import {
37
+ WorktreeLifecycle,
38
+ type WorktreeLifecycleDeps,
39
+ type WorktreeLifecycleTestOverrides,
40
+ } from "../worktree-lifecycle.ts";
37
41
  import { WorktreeStateProjection } from "../worktree-state-projection.ts";
38
42
  import { MergeConflictError } from "../git-service.ts";
39
43
  import type { AutoSession } from "../auto/session.ts";
40
44
 
41
- // Test-local: LegacyTestDeps had three fields Lifecycle does not need
42
- // (shouldUseWorktreeIsolation, syncWorktreeStateBack, captureIntegrationBranch).
43
- // Permit them in test fixtures so existing override patterns keep working —
44
- // Lifecycle ignores the extras via structural typing.
45
- type LegacyTestDeps = WorktreeLifecycleDeps & {
45
+ // Test-local: extras the WorktreeResolver-era fixture passed but Lifecycle
46
+ // does not need (shouldUseWorktreeIsolation, syncWorktreeStateBack,
47
+ // captureIntegrationBranch). Lifecycle ignores them via structural typing.
48
+ // The C1-C4-inlined primitive overrides come from
49
+ // `WorktreeLifecycleTestOverrides`, the test seam exported by the Module.
50
+ type LegacyTestDeps = WorktreeLifecycleDeps & WorktreeLifecycleTestOverrides & {
46
51
  shouldUseWorktreeIsolation?: () => boolean;
47
52
  syncWorktreeStateBack?: (
48
53
  mainBasePath: string,
@@ -50,6 +55,7 @@ type LegacyTestDeps = WorktreeLifecycleDeps & {
50
55
  milestoneId: string,
51
56
  ) => { synced: string[] };
52
57
  captureIntegrationBranch?: (basePath: string, mid: string | undefined) => void;
58
+ GitServiceImpl?: new (basePath: string, gitConfig: unknown) => unknown;
53
59
  };
54
60
 
55
61
  /**
@@ -96,7 +102,12 @@ function makeDeps(
96
102
  enterAutoWorktree: () => "",
97
103
  enterBranchModeForMilestone: () => undefined,
98
104
  getAutoWorktreePath: () => null,
99
- autoCommitCurrentBranch: () => undefined,
105
+ autoCommitCurrentBranch: (
106
+ _basePath: string,
107
+ _unitType: string,
108
+ _unitId: string,
109
+ _taskContext?: unknown,
110
+ ) => null,
100
111
  getCurrentBranch: () => "worktree/M001",
101
112
  checkoutBranch: () => undefined,
102
113
  autoWorktreeBranch: (mid: string) => `worktree/${mid}`,
@@ -109,6 +120,8 @@ function makeDeps(
109
120
  invalidateAllCaches: () => undefined,
110
121
  captureIntegrationBranch: () => undefined,
111
122
  worktreeProjection: new WorktreeStateProjection(),
123
+ // ADR-016 phase 2 / C4 (#5627): GitServiceImpl constructor → factory.
124
+ gitServiceFactory: () => ({}) as never,
112
125
  ...overrides,
113
126
  };
114
127
  }
@@ -128,14 +141,36 @@ function makeNotifyCtx(): {
128
141
 
129
142
  describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", () => {
130
143
  let baseDir: string;
144
+ const savedCwd = process.cwd();
131
145
 
132
146
  beforeEach(() => {
133
147
  baseDir = mkdtempSync(join(tmpdir(), "merge-conflict-stops-loop-"));
134
148
  // Fake out a milestone directory so mergeAndExit reaches mergeMilestoneToMain.
135
149
  mkdirSync(join(baseDir, ".gsd", "milestones", "M001"), { recursive: true });
150
+ // ADR-016 phase 2 / C1 (#5624): worktree-lifecycle.ts now calls
151
+ // node:fs.readFileSync directly (the dep was retired), so the roadmap
152
+ // file must exist on disk for the test to reach mergeMilestoneToMain.
153
+ writeFileSync(
154
+ join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
155
+ "# M001\n",
156
+ );
157
+ // ADR-016 phase 2 / C3 (#5626): `getIsolationMode` is also inlined.
158
+ // Without explicit isolation preferences the mode defaults to "none"
159
+ // and the merge short-circuits before the test's mocked
160
+ // `mergeMilestoneToMain` is reached. Write a preferences file so the
161
+ // standalone routes through worktree-mode merge.
162
+ writeFileSync(
163
+ join(baseDir, ".gsd", "preferences.md"),
164
+ "## Git\n- isolation: worktree\n",
165
+ );
136
166
  });
137
167
 
138
168
  afterEach(() => {
169
+ // ADR-016 phase 2 / C2 (#5625): the inlined `mergeMilestoneStandalone`
170
+ // chdirs into the project root before the merge body runs. Restore
171
+ // cwd before deleting `baseDir` so the next test's `process.cwd()`
172
+ // doesn't fail with ENOENT.
173
+ try { process.chdir(savedCwd); } catch { /* best-effort */ }
139
174
  try {
140
175
  rmSync(baseDir, { recursive: true, force: true });
141
176
  } catch {
@@ -147,7 +182,7 @@ describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", (
147
182
  const conflicted = ["src/feature.ts", "README.md"];
148
183
  const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
149
184
  const deps = makeDeps({
150
- resolveMilestoneFile: (_base, _mid, type) =>
185
+ resolveMilestoneFile: (_base: string, _mid: string, type: string) =>
151
186
  type === "ROADMAP" ? roadmapPath : null,
152
187
  readFileSync: () => "# M001\n",
153
188
  mergeMilestoneToMain: () => {
@@ -178,7 +213,7 @@ describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", (
178
213
  const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
179
214
  class FakePermError extends Error {}
180
215
  const deps = makeDeps({
181
- resolveMilestoneFile: (_base, _mid, type) =>
216
+ resolveMilestoneFile: (_base: string, _mid: string, type: string) =>
182
217
  type === "ROADMAP" ? roadmapPath : null,
183
218
  readFileSync: () => "# M001\n",
184
219
  mergeMilestoneToMain: () => {
@@ -204,7 +239,7 @@ describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", (
204
239
  test("successful merge does not throw", () => {
205
240
  const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
206
241
  const deps = makeDeps({
207
- resolveMilestoneFile: (_base, _mid, type) =>
242
+ resolveMilestoneFile: (_base: string, _mid: string, type: string) =>
208
243
  type === "ROADMAP" ? roadmapPath : null,
209
244
  readFileSync: () => "# M001\n",
210
245
  mergeMilestoneToMain: () => ({ pushed: false, codeFilesChanged: true }),
@@ -497,6 +497,7 @@ test('Scenario 11: Requirements edge cases', () => {
497
497
  makeRequirement('', 'Another No ID', 'validated'),
498
498
  makeRequirement('R005', 'Has ID', 'something-weird'),
499
499
  makeRequirement('R006', 'Deferred One', 'DEFERRED'),
500
+ makeRequirement('AUTH-7', 'Legacy ID', 'active'),
500
501
  ],
501
502
  phases: {
502
503
  '1-req-edge': makePhase('1-req-edge', 1, 'req-edge'),
@@ -510,6 +511,8 @@ test('Scenario 11: Requirements edge cases', () => {
510
511
  assert.deepStrictEqual(result.requirements[2]?.id, 'R005', 'req-edge: existing id preserved');
511
512
  assert.deepStrictEqual(result.requirements[2]?.status, 'active', 'req-edge: unknown status normalized to active');
512
513
  assert.deepStrictEqual(result.requirements[3]?.status, 'deferred', 'req-edge: uppercase DEFERRED normalized');
514
+ assert.deepStrictEqual(result.requirements[4]?.id, 'R003', 'req-edge: non-R legacy id gets next canonical id');
515
+ assert.ok(result.requirements[4]?.description.includes('Legacy ID: AUTH-7'), 'req-edge: original legacy id is preserved in description');
513
516
  });
514
517
 
515
518
  // ─── Scenario 12: Vision derivation ────────────────────────────────────────
@@ -553,6 +556,8 @@ test('Scenario 13: Decisions content', () => {
553
556
  const result = transformToGSD(project);
554
557
 
555
558
  assert.ok(result.decisionsContent.includes('decision-01'), 'decisions: extracts key-decisions from summaries');
559
+ assert.ok(result.decisionsContent.includes('| D001 |'), 'decisions: writes DB-importable decision ID');
560
+ assert.ok(result.decisionsContent.includes('| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |'), 'decisions: writes canonical table header');
556
561
  });
557
562
 
558
563
  // ─── Scenario 14: No undefined values in output ───────────────────────────
@@ -616,4 +621,3 @@ test('Scenario 15: Empty research', () => {
616
621
  });
617
622
 
618
623
  // ─── Results ───────────────────────────────────────────────────────────────
619
-