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,323 @@
1
+ // ADR-013 Stage 2b — KNOWLEDGE.md backfill + hybrid projection tests.
2
+ //
3
+ // Covers four behaviors:
4
+ // 1. parser: splits cells correctly, skips header/separator rows, respects
5
+ // section boundaries
6
+ // 2. backfill: Patterns -> memories(category=pattern), Lessons ->
7
+ // memories(category=gotcha), Rules NOT migrated, idempotent
8
+ // 3. projection: hybrid output preserves manual Rules verbatim while
9
+ // projecting Patterns + Lessons from memories
10
+ // 4. bootstrap path: backfill + projection round-trip produces a stable
11
+ // file that re-reading reconstitutes the same memory set
12
+
13
+ import test from "node:test";
14
+ import assert from "node:assert/strict";
15
+ import {
16
+ existsSync,
17
+ mkdirSync,
18
+ mkdtempSync,
19
+ readFileSync,
20
+ rmSync,
21
+ writeFileSync,
22
+ } from "node:fs";
23
+ import { join } from "node:path";
24
+ import { tmpdir } from "node:os";
25
+
26
+ import {
27
+ _getAdapter,
28
+ closeDatabase,
29
+ openDatabase,
30
+ } from "../gsd-db.ts";
31
+ import { backfillKnowledgeToMemories } from "../knowledge-backfill.ts";
32
+ import {
33
+ knowledgeMdPath,
34
+ parseKnowledgeRows,
35
+ splitPipeRow,
36
+ } from "../knowledge-parser.ts";
37
+ import { renderKnowledgeProjection } from "../knowledge-projection.ts";
38
+
39
+ function makeTmpBase(): string {
40
+ const base = mkdtempSync(join(tmpdir(), "gsd-knowledge-stage2b-"));
41
+ mkdirSync(join(base, ".gsd"), { recursive: true });
42
+ openDatabase(join(base, ".gsd", "gsd.db"));
43
+ return base;
44
+ }
45
+
46
+ function cleanup(base: string): void {
47
+ try {
48
+ closeDatabase();
49
+ } catch {
50
+ /* noop */
51
+ }
52
+ try {
53
+ rmSync(base, { recursive: true, force: true });
54
+ } catch {
55
+ /* noop */
56
+ }
57
+ }
58
+
59
+ function writeKnowledgeMd(base: string, body: string): void {
60
+ writeFileSync(join(base, ".gsd", "KNOWLEDGE.md"), body, "utf-8");
61
+ }
62
+
63
+ const FIXTURE = `# Project Knowledge
64
+
65
+ Append-only register of project-specific rules, patterns, and lessons learned.
66
+ Agents read this before every unit. Add entries when you discover something worth remembering.
67
+
68
+ ## Rules
69
+
70
+ | # | Scope | Rule | Why | Added |
71
+ |---|-------|------|-----|-------|
72
+ | K001 | project | All timestamps in UTC | clarity | 2026-01-01 |
73
+ | K002 | M001 | Never trust user input | safety | 2026-01-02 |
74
+
75
+ ## Patterns
76
+
77
+ | # | Pattern | Where | Notes |
78
+ |---|---------|-------|-------|
79
+ | P001 | Repository pattern | services/ | guards |
80
+ | P002 | Adapter at the seam | packages/pi-ai/ | observability |
81
+
82
+ ## Lessons Learned
83
+
84
+ | # | What Happened | Root Cause | Fix | Scope |
85
+ |---|--------------|------------|-----|-------|
86
+ | L001 | Cache poisoning | reused key | versioned key | project |
87
+ `;
88
+
89
+ // ─── splitPipeRow ──────────────────────────────────────────────────────────
90
+
91
+ test("splitPipeRow extracts cells from a standard table row", () => {
92
+ const cells = splitPipeRow("| K001 | project | All timestamps in UTC | clarity | 2026-01-01 |");
93
+ assert.deepEqual(cells, ["K001", "project", "All timestamps in UTC", "clarity", "2026-01-01"]);
94
+ });
95
+
96
+ test("splitPipeRow preserves escaped pipes inside a cell", () => {
97
+ const cells = splitPipeRow(`| K001 | project | Use A \\| B operator | safety | 2026-01-01 |`);
98
+ assert.equal(cells[2], "Use A | B operator");
99
+ });
100
+
101
+ // ─── parseKnowledgeRows ────────────────────────────────────────────────────
102
+
103
+ test("parseKnowledgeRows returns rows per section with the correct table tag", () => {
104
+ const rows = parseKnowledgeRows(FIXTURE);
105
+ assert.equal(rows.length, 5, "two rules + two patterns + one lesson");
106
+ const tables = rows.map((r) => r.table);
107
+ assert.deepEqual(tables, ["rules", "rules", "patterns", "patterns", "lessons"]);
108
+ });
109
+
110
+ test("parseKnowledgeRows captures cell values aligned with the section schema", () => {
111
+ const rows = parseKnowledgeRows(FIXTURE);
112
+ const p1 = rows.find((r) => r.id === "P001");
113
+ assert.ok(p1);
114
+ assert.equal(p1.cells[1], "Repository pattern");
115
+ assert.equal(p1.cells[2], "services/");
116
+ });
117
+
118
+ // ─── backfillKnowledgeToMemories ───────────────────────────────────────────
119
+
120
+ test("backfill migrates Patterns + Lessons but skips Rules", () => {
121
+ const base = makeTmpBase();
122
+ try {
123
+ writeKnowledgeMd(base, FIXTURE);
124
+ const written = backfillKnowledgeToMemories(base);
125
+ assert.equal(written, 3, "P001 + P002 + L001 should migrate; K rows skipped");
126
+
127
+ const adapter = _getAdapter();
128
+ assert.ok(adapter);
129
+
130
+ const knowledgeMemories = adapter
131
+ .prepare(
132
+ "SELECT category, structured_fields FROM memories WHERE structured_fields LIKE '%\"sourceKnowledgeId\":\"%' ORDER BY seq",
133
+ )
134
+ .all() as Array<{ category: string; structured_fields: string }>;
135
+
136
+ assert.equal(knowledgeMemories.length, 3);
137
+ const categoriesById: Record<string, string> = {};
138
+ for (const m of knowledgeMemories) {
139
+ const sf = JSON.parse(m.structured_fields) as { sourceKnowledgeId: string };
140
+ categoriesById[sf.sourceKnowledgeId] = m.category;
141
+ }
142
+ assert.equal(categoriesById["P001"], "pattern");
143
+ assert.equal(categoriesById["P002"], "pattern");
144
+ assert.equal(categoriesById["L001"], "gotcha");
145
+ assert.equal(categoriesById["K001"], undefined, "K001 must NOT be in memories");
146
+ } finally {
147
+ cleanup(base);
148
+ }
149
+ });
150
+
151
+ test("backfill is idempotent — second run on the same file is a no-op", () => {
152
+ const base = makeTmpBase();
153
+ try {
154
+ writeKnowledgeMd(base, FIXTURE);
155
+ const first = backfillKnowledgeToMemories(base);
156
+ assert.equal(first, 3);
157
+ const second = backfillKnowledgeToMemories(base);
158
+ assert.equal(second, 0, "already-migrated rows must not be re-inserted");
159
+ } finally {
160
+ cleanup(base);
161
+ }
162
+ });
163
+
164
+ test("backfill returns 0 when KNOWLEDGE.md is absent", () => {
165
+ const base = makeTmpBase();
166
+ try {
167
+ assert.equal(backfillKnowledgeToMemories(base), 0);
168
+ } finally {
169
+ cleanup(base);
170
+ }
171
+ });
172
+
173
+ // ─── renderKnowledgeProjection ─────────────────────────────────────────────
174
+
175
+ test("projection preserves the manual Rules section verbatim", () => {
176
+ const base = makeTmpBase();
177
+ try {
178
+ writeKnowledgeMd(base, FIXTURE);
179
+ backfillKnowledgeToMemories(base);
180
+ renderKnowledgeProjection(base);
181
+
182
+ const rendered = readFileSync(knowledgeMdPath(base), "utf-8");
183
+ // Both K-rows must appear unchanged.
184
+ assert.match(rendered, /\| K001 \| project \| All timestamps in UTC \| clarity \| 2026-01-01 \|/);
185
+ assert.match(rendered, /\| K002 \| M001 \| Never trust user input \| safety \| 2026-01-02 \|/);
186
+ } finally {
187
+ cleanup(base);
188
+ }
189
+ });
190
+
191
+ test("projection renders Patterns + Lessons from memories", () => {
192
+ const base = makeTmpBase();
193
+ try {
194
+ writeKnowledgeMd(base, FIXTURE);
195
+ backfillKnowledgeToMemories(base);
196
+ // Wipe the original Patterns/Lessons table rows from the file so the
197
+ // projection's output can ONLY come from memories. Keep Rules intact.
198
+ writeKnowledgeMd(
199
+ base,
200
+ `# Project Knowledge
201
+
202
+ ## Rules
203
+
204
+ | # | Scope | Rule | Why | Added |
205
+ |---|-------|------|-----|-------|
206
+ | K001 | project | All timestamps in UTC | clarity | 2026-01-01 |
207
+ | K002 | M001 | Never trust user input | safety | 2026-01-02 |
208
+ `,
209
+ );
210
+
211
+ renderKnowledgeProjection(base);
212
+ const rendered = readFileSync(knowledgeMdPath(base), "utf-8");
213
+
214
+ assert.match(rendered, /\| P001 \| Repository pattern \| services\/ \| guards \|/);
215
+ assert.match(rendered, /\| P002 \| Adapter at the seam \| packages\/pi-ai\/ \| observability \|/);
216
+ assert.match(rendered, /\| L001 \| Cache poisoning \| reused key \| versioned key \| project \|/);
217
+
218
+ // Section structure must still be the canonical three headings, in order.
219
+ const rulesIdx = rendered.indexOf("## Rules");
220
+ const patternsIdx = rendered.indexOf("## Patterns");
221
+ const lessonsIdx = rendered.indexOf("## Lessons Learned");
222
+ assert.ok(rulesIdx >= 0 && patternsIdx > rulesIdx && lessonsIdx > patternsIdx, "headings must appear in canonical order");
223
+ } finally {
224
+ cleanup(base);
225
+ }
226
+ });
227
+
228
+ test("projection is idempotent when nothing has changed", () => {
229
+ const base = makeTmpBase();
230
+ try {
231
+ // Seed a file the projection will *change* (no canonical headers yet, so
232
+ // the first render must rewrite to add structure).
233
+ writeKnowledgeMd(
234
+ base,
235
+ `# Project Knowledge
236
+
237
+ ## Rules
238
+
239
+ | # | Scope | Rule | Why | Added |
240
+ |---|-------|------|-----|-------|
241
+ | K001 | project | manual rule | reason | 2026-01-01 |
242
+ `,
243
+ );
244
+
245
+ const first = renderKnowledgeProjection(base);
246
+ assert.equal(first.written, true, "first render adds the missing Patterns + Lessons section scaffolding");
247
+
248
+ const second = renderKnowledgeProjection(base);
249
+ assert.equal(second.written, false, "second render is a no-op when content already matches");
250
+ } finally {
251
+ cleanup(base);
252
+ }
253
+ });
254
+
255
+ test("projection emits empty section tables when no rows exist for that category", () => {
256
+ const base = makeTmpBase();
257
+ try {
258
+ writeKnowledgeMd(
259
+ base,
260
+ `# Project Knowledge
261
+
262
+ ## Rules
263
+
264
+ | # | Scope | Rule | Why | Added |
265
+ |---|-------|------|-----|-------|
266
+ `,
267
+ );
268
+ renderKnowledgeProjection(base);
269
+ const rendered = readFileSync(knowledgeMdPath(base), "utf-8");
270
+
271
+ assert.match(rendered, /## Patterns/);
272
+ assert.match(rendered, /## Lessons Learned/);
273
+ // The empty-table headers must be present.
274
+ assert.match(rendered, /\| # \| Pattern \| Where \| Notes \|/);
275
+ assert.match(rendered, /\| # \| What Happened \| Root Cause \| Fix \| Scope \|/);
276
+ } finally {
277
+ cleanup(base);
278
+ }
279
+ });
280
+
281
+ test("projection escapes pipes in memory content", () => {
282
+ const base = makeTmpBase();
283
+ try {
284
+ writeKnowledgeMd(
285
+ base,
286
+ `## Patterns
287
+
288
+ | # | Pattern | Where | Notes |
289
+ |---|---------|-------|-------|
290
+ | P001 | Use A \\| B fallback | adapters/ | watch out |
291
+ `,
292
+ );
293
+ backfillKnowledgeToMemories(base);
294
+ renderKnowledgeProjection(base);
295
+ const rendered = readFileSync(knowledgeMdPath(base), "utf-8");
296
+
297
+ // Pipe MUST stay escaped in the rendered output so the table doesn't break.
298
+ assert.match(rendered, /\| P001 \| Use A \\\| B fallback \| adapters\/ \| watch out \|/);
299
+ } finally {
300
+ cleanup(base);
301
+ }
302
+ });
303
+
304
+ // ─── End-to-end round-trip ─────────────────────────────────────────────────
305
+
306
+ test("backfill + projection round-trip: re-running backfill on rendered file is a no-op", () => {
307
+ const base = makeTmpBase();
308
+ try {
309
+ writeKnowledgeMd(base, FIXTURE);
310
+ const initial = backfillKnowledgeToMemories(base);
311
+ assert.equal(initial, 3);
312
+
313
+ renderKnowledgeProjection(base);
314
+ assert.ok(existsSync(knowledgeMdPath(base)));
315
+
316
+ // The rendered file contains the same P/L IDs as the source. A second
317
+ // backfill pass must NOT re-insert them.
318
+ const second = backfillKnowledgeToMemories(base);
319
+ assert.equal(second, 0, "round-trip rendered file must remain idempotent for backfill");
320
+ } finally {
321
+ cleanup(base);
322
+ }
323
+ });
@@ -0,0 +1,242 @@
1
+ // ADR-013 Stage 2c — /gsd knowledge write-side redirect tests.
2
+ //
3
+ // Locks in four properties of captureKnowledgeEntry / nextKnowledgeId:
4
+ // 1. Pattern entries write a memory row with category="pattern" and a
5
+ // sourceKnowledgeId marker — but do NOT touch KNOWLEDGE.md.
6
+ // 2. Lesson entries write a memory row with category="gotcha" — same
7
+ // file-vs-memory split.
8
+ // 3. Next-ID is monotonic across both surfaces: a P004 in the file plus a
9
+ // P007 in memories yields P008 next.
10
+ // 4. The legacy appendKnowledge stays the canonical path for Rules
11
+ // (covered indirectly via no-memory side effect on type="rule").
12
+
13
+ import test from "node:test";
14
+ import assert from "node:assert/strict";
15
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
16
+ import { join } from "node:path";
17
+ import { tmpdir } from "node:os";
18
+
19
+ import {
20
+ _getAdapter,
21
+ closeDatabase,
22
+ openDatabase,
23
+ } from "../gsd-db.ts";
24
+ import { captureKnowledgeEntry, nextKnowledgeId } from "../knowledge-capture.ts";
25
+ import { knowledgeMdPath } from "../knowledge-parser.ts";
26
+
27
+ function makeTmpBase(): string {
28
+ const base = mkdtempSync(join(tmpdir(), "gsd-knowledge-capture-"));
29
+ mkdirSync(join(base, ".gsd"), { recursive: true });
30
+ openDatabase(join(base, ".gsd", "gsd.db"));
31
+ return base;
32
+ }
33
+
34
+ function cleanup(base: string): void {
35
+ try {
36
+ closeDatabase();
37
+ } catch {
38
+ /* noop */
39
+ }
40
+ try {
41
+ rmSync(base, { recursive: true, force: true });
42
+ } catch {
43
+ /* noop */
44
+ }
45
+ }
46
+
47
+ function readMemoriesWithMarker(prefix: "P" | "L"): Array<{ category: string; sf: Record<string, unknown> }> {
48
+ const adapter = _getAdapter();
49
+ if (!adapter) return [];
50
+ const rows = adapter
51
+ .prepare(
52
+ "SELECT category, structured_fields FROM memories WHERE structured_fields LIKE :pattern ORDER BY seq",
53
+ )
54
+ .all({ ":pattern": `%"sourceKnowledgeId":"${prefix}%` }) as Array<{
55
+ category: string;
56
+ structured_fields: string;
57
+ }>;
58
+ return rows.map((r) => ({ category: r.category, sf: JSON.parse(r.structured_fields) }));
59
+ }
60
+
61
+ // ─── Pattern path ───────────────────────────────────────────────────────────
62
+
63
+ test("pattern entry creates a memory and assigns the next P### id", () => {
64
+ const base = makeTmpBase();
65
+ try {
66
+ const result = captureKnowledgeEntry(base, "pattern", "Repository pattern at the seam", "M001");
67
+ assert.equal(result.id, "P001", "first pattern on a fresh project should be P001");
68
+ assert.equal(result.written, true);
69
+
70
+ const memories = readMemoriesWithMarker("P");
71
+ assert.equal(memories.length, 1);
72
+ assert.equal(memories[0]?.category, "pattern");
73
+ assert.equal(memories[0]?.sf.sourceKnowledgeId, "P001");
74
+ assert.equal(memories[0]?.sf.pattern, "Repository pattern at the seam");
75
+ assert.equal(memories[0]?.sf.where, "");
76
+ assert.equal(memories[0]?.sf.notes, "");
77
+ } finally {
78
+ cleanup(base);
79
+ }
80
+ });
81
+
82
+ test("pattern entry does NOT write to KNOWLEDGE.md (memory-only)", () => {
83
+ const base = makeTmpBase();
84
+ try {
85
+ captureKnowledgeEntry(base, "pattern", "Adapter at the seam", "project");
86
+ assert.equal(
87
+ existsSync(knowledgeMdPath(base)),
88
+ false,
89
+ "KNOWLEDGE.md should remain untouched — projection re-renders on next session start",
90
+ );
91
+ } finally {
92
+ cleanup(base);
93
+ }
94
+ });
95
+
96
+ test("repeated pattern captures advance the ID monotonically", () => {
97
+ const base = makeTmpBase();
98
+ try {
99
+ const a = captureKnowledgeEntry(base, "pattern", "First", "project");
100
+ const b = captureKnowledgeEntry(base, "pattern", "Second", "project");
101
+ const c = captureKnowledgeEntry(base, "pattern", "Third", "project");
102
+ assert.deepEqual([a.id, b.id, c.id], ["P001", "P002", "P003"]);
103
+ } finally {
104
+ cleanup(base);
105
+ }
106
+ });
107
+
108
+ // ─── Lesson path ────────────────────────────────────────────────────────────
109
+
110
+ test("lesson entry creates a memory with category=gotcha and L### id", () => {
111
+ const base = makeTmpBase();
112
+ try {
113
+ const result = captureKnowledgeEntry(base, "lesson", "Cache poisoning via reused key", "M001/S01");
114
+ assert.equal(result.id, "L001");
115
+ assert.equal(result.written, true);
116
+
117
+ const memories = readMemoriesWithMarker("L");
118
+ assert.equal(memories.length, 1);
119
+ assert.equal(memories[0]?.category, "gotcha");
120
+ assert.equal(memories[0]?.sf.sourceKnowledgeId, "L001");
121
+ assert.equal(memories[0]?.sf.whatHappened, "Cache poisoning via reused key");
122
+ assert.equal(memories[0]?.sf.scopeText, "M001/S01");
123
+ } finally {
124
+ cleanup(base);
125
+ }
126
+ });
127
+
128
+ // ─── Empty input ────────────────────────────────────────────────────────────
129
+
130
+ test("empty entry text does NOT create a memory but still assigns an id", () => {
131
+ const base = makeTmpBase();
132
+ try {
133
+ const result = captureKnowledgeEntry(base, "pattern", " ", "project");
134
+ assert.equal(result.written, false);
135
+ assert.equal(readMemoriesWithMarker("P").length, 0);
136
+ } finally {
137
+ cleanup(base);
138
+ }
139
+ });
140
+
141
+ // ─── nextKnowledgeId — cross-surface monotonicity ───────────────────────────
142
+
143
+ test("nextKnowledgeId takes max of file and memory surfaces", () => {
144
+ const base = makeTmpBase();
145
+ try {
146
+ // Pre-existing patterns in KNOWLEDGE.md and one new pattern in memories.
147
+ // The legacy appendKnowledge format starts P at 001 — we simulate higher
148
+ // existing IDs to verify the take-max-then-+1 rule.
149
+ writeFileSync(
150
+ knowledgeMdPath(base),
151
+ `## Patterns
152
+
153
+ | # | Pattern | Where | Notes |
154
+ |---|---------|-------|-------|
155
+ | P004 | Legacy pattern | services/ | preserved |
156
+ `,
157
+ "utf-8",
158
+ );
159
+
160
+ // Capture jumps the memory ID forward.
161
+ captureKnowledgeEntry(base, "pattern", "Memory-only pattern", "project");
162
+ captureKnowledgeEntry(base, "pattern", "Another memory-only pattern", "project");
163
+ captureKnowledgeEntry(base, "pattern", "And another", "project");
164
+
165
+ // After: file has P004 (max=4); memories have P005, P006, P007 (max=7).
166
+ // Next must be P008.
167
+ assert.equal(nextKnowledgeId(base, "P"), "P008");
168
+ } finally {
169
+ cleanup(base);
170
+ }
171
+ });
172
+
173
+ test("nextKnowledgeId works per-prefix without cross-talk", () => {
174
+ const base = makeTmpBase();
175
+ try {
176
+ captureKnowledgeEntry(base, "pattern", "P entry", "project");
177
+ captureKnowledgeEntry(base, "pattern", "P entry 2", "project");
178
+ captureKnowledgeEntry(base, "lesson", "L entry", "project");
179
+
180
+ assert.equal(nextKnowledgeId(base, "P"), "P003");
181
+ assert.equal(nextKnowledgeId(base, "L"), "L002");
182
+ // K has no entries on this project — first one should be K001.
183
+ assert.equal(nextKnowledgeId(base, "K"), "K001");
184
+ } finally {
185
+ cleanup(base);
186
+ }
187
+ });
188
+
189
+ test("nextKnowledgeId pads to three digits even at the rollover", () => {
190
+ const base = makeTmpBase();
191
+ try {
192
+ writeFileSync(
193
+ knowledgeMdPath(base),
194
+ `## Patterns
195
+
196
+ | # | Pattern | Where | Notes |
197
+ |---|---------|-------|-------|
198
+ | P099 | high water mark | — | — |
199
+ `,
200
+ "utf-8",
201
+ );
202
+ assert.equal(nextKnowledgeId(base, "P"), "P100");
203
+ } finally {
204
+ cleanup(base);
205
+ }
206
+ });
207
+
208
+ // ─── Sanity: file-side reads still see existing rows after capture ─────────
209
+
210
+ test("after pattern capture, KNOWLEDGE.md untouched but next id reflects memory state", () => {
211
+ const base = makeTmpBase();
212
+ try {
213
+ captureKnowledgeEntry(base, "pattern", "First", "project");
214
+ // KNOWLEDGE.md still absent.
215
+ assert.equal(existsSync(knowledgeMdPath(base)), false);
216
+ // Next-ID logic sees the new memory.
217
+ assert.equal(nextKnowledgeId(base, "P"), "P002");
218
+ } finally {
219
+ cleanup(base);
220
+ }
221
+ });
222
+
223
+ test("rule writes still flow through appendKnowledge (file-canonical) — memory unchanged", async () => {
224
+ const base = makeTmpBase();
225
+ try {
226
+ // We invoke the legacy file path directly here; the command handler
227
+ // dispatch is verified separately at the integration level. The point
228
+ // of this test is to lock in that captureKnowledgeEntry is NOT the
229
+ // rule path — rules must go through appendKnowledge.
230
+ const { appendKnowledge } = await import("../files.ts");
231
+ await appendKnowledge(base, "rule", "Always pin SQLite version", "project");
232
+
233
+ const md = readFileSync(knowledgeMdPath(base), "utf-8");
234
+ assert.match(md, /\| K001 \| project \| Always pin SQLite version /);
235
+
236
+ // No pattern/lesson memories should exist as a side effect.
237
+ assert.equal(readMemoriesWithMarker("P").length, 0);
238
+ assert.equal(readMemoriesWithMarker("L").length, 0);
239
+ } finally {
240
+ cleanup(base);
241
+ }
242
+ });
@@ -187,7 +187,7 @@ test('loadKnowledgeBlock: uses project knowledge alone when no global file', ()
187
187
  writeFileSync(join(cwd, '.gsd', 'KNOWLEDGE.md'), 'K001: Use real DB');
188
188
 
189
189
  const result = loadKnowledgeBlock(gsdHome, cwd);
190
- assert.ok(result.block.includes('[KNOWLEDGE — Rules, patterns, and lessons learned]'));
190
+ assert.ok(result.block.includes('[KNOWLEDGE — Rules from KNOWLEDGE.md'));
191
191
  assert.ok(result.block.includes('## Project Knowledge'));
192
192
  assert.ok(result.block.includes('K001: Use real DB'));
193
193
  assert.ok(!result.block.includes('## Global Knowledge'));
@@ -205,7 +205,7 @@ test('loadKnowledgeBlock: uses global knowledge alone when no project file', ()
205
205
  writeFileSync(join(gsdHome, 'agent', 'KNOWLEDGE.md'), 'G001: Respond in English');
206
206
 
207
207
  const result = loadKnowledgeBlock(gsdHome, cwd);
208
- assert.ok(result.block.includes('[KNOWLEDGE — Rules, patterns, and lessons learned]'));
208
+ assert.ok(result.block.includes('[KNOWLEDGE — Rules from KNOWLEDGE.md'));
209
209
  assert.ok(result.block.includes('## Global Knowledge'));
210
210
  assert.ok(result.block.includes('G001: Respond in English'));
211
211
  assert.ok(!result.block.includes('## Project Knowledge'));
@@ -234,6 +234,51 @@ test('loadKnowledgeBlock: merges global before project when both exist', () => {
234
234
  rmSync(tmp, { recursive: true, force: true });
235
235
  });
236
236
 
237
+ test('loadKnowledgeBlock: strips patterns and lessons from project knowledge', () => {
238
+ const tmp = realpathSync(mkdtempSync(join(tmpdir(), 'gsd-kb-strip-')));
239
+ const gsdHome = join(tmp, 'home');
240
+ const cwd = join(tmp, 'project');
241
+ mkdirSync(join(cwd, '.gsd'), { recursive: true });
242
+ mkdirSync(join(gsdHome, 'agent'), { recursive: true });
243
+ writeFileSync(
244
+ join(cwd, '.gsd', 'KNOWLEDGE.md'),
245
+ [
246
+ '# Project Knowledge',
247
+ '',
248
+ 'Intro note that should stay with manual rules.',
249
+ '',
250
+ '## Rules',
251
+ '',
252
+ '| ID | Rule | Notes |',
253
+ '|---|---|---|',
254
+ '| K001 | Use real DB | - |',
255
+ '',
256
+ '## Patterns',
257
+ '',
258
+ '| ID | Pattern | Where | Notes |',
259
+ '|---|---|---|---|',
260
+ '| P001 | Prefer async | server | - |',
261
+ '',
262
+ '## Lessons Learned',
263
+ '',
264
+ '| ID | What Happened | Root Cause | Fix | Scope |',
265
+ '|---|---|---|---|---|',
266
+ '| L001 | Missed cache | N/A | Add TTL | project |',
267
+ ].join('\n'),
268
+ );
269
+
270
+ const result = loadKnowledgeBlock(gsdHome, cwd);
271
+ assert.ok(result.block.includes('[KNOWLEDGE — Rules from KNOWLEDGE.md'));
272
+ assert.ok(result.block.includes('Intro note that should stay with manual rules.'));
273
+ assert.ok(result.block.includes('K001'), 'rules entry should be present');
274
+ assert.ok(!result.block.includes('P001'), 'patterns should be stripped and injected via memories');
275
+ assert.ok(!result.block.includes('L001'), 'lessons should be stripped and injected via memories');
276
+ assert.ok(!result.block.includes('## Patterns'), 'Patterns heading should not appear');
277
+ assert.ok(!result.block.includes('## Lessons Learned'), 'Lessons heading should not appear');
278
+
279
+ rmSync(tmp, { recursive: true, force: true });
280
+ });
281
+
237
282
  test('loadKnowledgeBlock: reports globalSizeKb above 4KB threshold', () => {
238
283
  const tmp = realpathSync(mkdtempSync(join(tmpdir(), 'gsd-kb-')));
239
284
  const gsdHome = join(tmp, 'home');