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,160 @@
1
+ // GSD2 — KNOWLEDGE.md write-side cutover (ADR-013 Stage 2c).
2
+ //
3
+ // Replaces the legacy `appendKnowledge` file-append path for Patterns and
4
+ // Lessons with `createMemory` calls. Rules (K###) continue to flow through
5
+ // the legacy file-append because they are intentionally not migrated to
6
+ // memories per ADR-013 line 39.
7
+ //
8
+ // Next-ID assignment is the cross-surface stable rule: read the existing
9
+ // `.gsd/KNOWLEDGE.md` for the highest <prefix>### in that section, AND read
10
+ // the memories table for the highest `sourceKnowledgeId` with the matching
11
+ // prefix, take the max, and increment. This stays stable across the
12
+ // knowledge backfill mid-run (when some rows exist only in the file and
13
+ // others only in memories) and on a fresh project where neither has any
14
+ // entries yet.
15
+
16
+ import { _getAdapter, isDbAvailable } from "./gsd-db.js";
17
+ import { createMemory } from "./memory-store.js";
18
+ import { parseKnowledgeRows, readKnowledgeMd } from "./knowledge-parser.js";
19
+ import { logWarning } from "./workflow-logger.js";
20
+
21
+ export type PatternLessonType = "pattern" | "lesson";
22
+
23
+ export interface CaptureKnowledgeResult {
24
+ /** The assigned <prefix>### identifier (e.g. "P004"). */
25
+ id: string;
26
+ /** Whether the memory row was actually written. False only when the
27
+ * DB is unavailable or the createMemory call returned undefined. */
28
+ written: boolean;
29
+ }
30
+
31
+ /**
32
+ * Append a new Pattern or Lesson by writing it as a memory row carrying a
33
+ * `sourceKnowledgeId` marker. The next session's KNOWLEDGE.md projection
34
+ * render (`knowledge-projection.ts`) picks it up and emits the row into the
35
+ * appropriate section.
36
+ *
37
+ * `entryText` is treated as the row's primary description cell (Pattern for
38
+ * patterns, "What Happened" for lessons). Auxiliary cells (Where/Notes for
39
+ * patterns; Root Cause/Fix/Scope for lessons) are left empty — the projection
40
+ * renders `—` for empty cells. Users who need richer structure can call
41
+ * `capture_thought` directly with a fuller `structuredFields` payload.
42
+ */
43
+ export function captureKnowledgeEntry(
44
+ basePath: string,
45
+ type: PatternLessonType,
46
+ entryText: string,
47
+ scope: string,
48
+ ): CaptureKnowledgeResult {
49
+ const cleaned = entryText.trim();
50
+ const idPrefix = type === "pattern" ? "P" : "L";
51
+ const id = nextKnowledgeId(basePath, idPrefix);
52
+
53
+ if (!cleaned) {
54
+ return { id, written: false };
55
+ }
56
+
57
+ if (!isDbAvailable()) {
58
+ logWarning("knowledge-capture", "DB unavailable; cannot persist knowledge entry");
59
+ return { id, written: false };
60
+ }
61
+
62
+ try {
63
+ const category = type === "pattern" ? "pattern" : "gotcha";
64
+ const structuredFields: Record<string, unknown> =
65
+ type === "pattern"
66
+ ? {
67
+ sourceKnowledgeId: id,
68
+ sourceKnowledgeTable: "patterns",
69
+ pattern: cleaned,
70
+ where: "",
71
+ notes: "",
72
+ }
73
+ : {
74
+ sourceKnowledgeId: id,
75
+ sourceKnowledgeTable: "lessons",
76
+ whatHappened: cleaned,
77
+ rootCause: "",
78
+ fix: "",
79
+ scopeText: scope,
80
+ };
81
+
82
+ const memoryId = createMemory({
83
+ category,
84
+ content: cleaned,
85
+ scope: scope || "project",
86
+ confidence: 0.85,
87
+ structuredFields,
88
+ });
89
+
90
+ return { id, written: !!memoryId };
91
+ } catch (e) {
92
+ logWarning(
93
+ "knowledge-capture",
94
+ `failed to persist ${type} entry as memory: ${(e as Error).message}`,
95
+ );
96
+ return { id, written: false };
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Compute the next <prefix>### identifier across both the legacy
102
+ * `.gsd/KNOWLEDGE.md` and the `memories.structured_fields.sourceKnowledgeId`
103
+ * surface. Takes the max numeric suffix from either side and increments.
104
+ *
105
+ * Padded to three digits to match the existing `appendKnowledge` convention.
106
+ * Exported for tests; production callers go through `captureKnowledgeEntry`.
107
+ */
108
+ export function nextKnowledgeId(basePath: string, prefix: "K" | "P" | "L"): string {
109
+ const fromFile = maxIdInFile(basePath, prefix);
110
+ const fromMemories = maxIdInMemories(prefix);
111
+ const next = Math.max(fromFile, fromMemories) + 1;
112
+ return `${prefix}${String(next).padStart(3, "0")}`;
113
+ }
114
+
115
+ function maxIdInFile(basePath: string, prefix: "K" | "P" | "L"): number {
116
+ const content = readKnowledgeMd(basePath);
117
+ if (!content.trim()) return 0;
118
+ const expectedTable =
119
+ prefix === "K" ? "rules" : prefix === "P" ? "patterns" : "lessons";
120
+
121
+ let max = 0;
122
+ for (const row of parseKnowledgeRows(content)) {
123
+ if (row.table !== expectedTable) continue;
124
+ const num = parseInt(row.id.slice(1), 10);
125
+ if (Number.isFinite(num) && num > max) max = num;
126
+ }
127
+ return max;
128
+ }
129
+
130
+ function maxIdInMemories(prefix: "K" | "P" | "L"): number {
131
+ if (!isDbAvailable()) return 0;
132
+ const adapter = _getAdapter();
133
+ if (!adapter) return 0;
134
+ try {
135
+ const rows = adapter
136
+ .prepare(
137
+ "SELECT structured_fields FROM memories WHERE structured_fields LIKE :pattern",
138
+ )
139
+ .all({ ":pattern": `%"sourceKnowledgeId":"${prefix}%` }) as Array<{
140
+ structured_fields: string | null;
141
+ }>;
142
+ let max = 0;
143
+ for (const row of rows) {
144
+ if (!row.structured_fields) continue;
145
+ let sf: Record<string, unknown>;
146
+ try {
147
+ sf = JSON.parse(row.structured_fields) as Record<string, unknown>;
148
+ } catch {
149
+ continue;
150
+ }
151
+ const sourceId = sf["sourceKnowledgeId"];
152
+ if (typeof sourceId !== "string" || !sourceId.startsWith(prefix)) continue;
153
+ const num = parseInt(sourceId.slice(1), 10);
154
+ if (Number.isFinite(num) && num > max) max = num;
155
+ }
156
+ return max;
157
+ } catch {
158
+ return 0;
159
+ }
160
+ }
@@ -0,0 +1,174 @@
1
+ // GSD-2 — KNOWLEDGE.md parsing helpers shared by the consolidation scanner,
2
+ // the Patterns/Lessons backfill, and the hybrid projection renderer
3
+ // (ADR-013 Stage 2a/2b).
4
+ //
5
+ // The KNOWLEDGE.md format is locked in `files.ts:appendKnowledge`:
6
+ //
7
+ // # Project Knowledge
8
+ //
9
+ // <optional intro prose>
10
+ //
11
+ // ## Rules
12
+ //
13
+ // | # | Scope | Rule | Why | Added |
14
+ // |---|-------|------|-----|-------|
15
+ // | K001 | project | <rule text> | <reason> | <date> |
16
+ //
17
+ // ## Patterns
18
+ //
19
+ // | # | Pattern | Where | Notes |
20
+ // |---|---------|-------|-------|
21
+ // | P001 | <pattern> | <location> | <notes> |
22
+ //
23
+ // ## Lessons Learned
24
+ //
25
+ // | # | What Happened | Root Cause | Fix | Scope |
26
+ // |---|--------------|------------|-----|-------|
27
+ // | L001 | <what> | <cause> | <fix> | <scope> |
28
+ //
29
+ // Row IDs use a strict <prefix><digits> format (K001, P001, L001 …). Parsers
30
+ // skip the column-title and separator rows; only rows whose first cell
31
+ // matches the expected prefix are emitted.
32
+
33
+ import { existsSync, readFileSync } from "node:fs";
34
+
35
+ import { resolveGsdRootFile } from "./paths.js";
36
+
37
+ export type KnowledgeTable = "rules" | "patterns" | "lessons";
38
+
39
+ export interface KnowledgeRow {
40
+ table: KnowledgeTable;
41
+ id: string;
42
+ /** Full table row, trimmed. Useful as a sample for diagnostic surfaces. */
43
+ raw: string;
44
+ /** Pipe-split cell values (excluding the leading/trailing empty cells from `| ... |`). */
45
+ cells: string[];
46
+ }
47
+
48
+ export const KNOWLEDGE_SECTIONS: ReadonlyArray<{
49
+ table: KnowledgeTable;
50
+ heading: string;
51
+ idPrefix: string;
52
+ }> = [
53
+ { table: "rules", heading: "## Rules", idPrefix: "K" },
54
+ { table: "patterns", heading: "## Patterns", idPrefix: "P" },
55
+ { table: "lessons", heading: "## Lessons Learned", idPrefix: "L" },
56
+ ];
57
+
58
+ /** Read `.gsd/KNOWLEDGE.md` content if present. Returns "" when absent or unreadable. */
59
+ export function readKnowledgeMd(basePath: string): string {
60
+ const path = resolveGsdRootFile(basePath, "KNOWLEDGE");
61
+ if (!existsSync(path)) return "";
62
+ try {
63
+ return readFileSync(path, "utf-8");
64
+ } catch {
65
+ return "";
66
+ }
67
+ }
68
+
69
+ /** Resolve the canonical `.gsd/KNOWLEDGE.md` path. */
70
+ export function knowledgeMdPath(basePath: string): string {
71
+ return resolveGsdRootFile(basePath, "KNOWLEDGE");
72
+ }
73
+
74
+ /**
75
+ * Parse KNOWLEDGE.md into row records. Skips intro prose, table headers,
76
+ * separator lines, and rows from unrecognized sections. Each row's first
77
+ * cell must match the section's expected prefix (K/P/L + digits).
78
+ */
79
+ export function parseKnowledgeRows(content: string): KnowledgeRow[] {
80
+ const rows: KnowledgeRow[] = [];
81
+ if (!content.trim()) return rows;
82
+
83
+ const lines = content.split("\n");
84
+ let activeSection: (typeof KNOWLEDGE_SECTIONS)[number] | undefined;
85
+
86
+ for (const line of lines) {
87
+ const trimmed = line.trim();
88
+ if (trimmed.startsWith("## ")) {
89
+ activeSection = KNOWLEDGE_SECTIONS.find((s) => s.heading === trimmed);
90
+ continue;
91
+ }
92
+ if (!activeSection) continue;
93
+ if (!trimmed.startsWith("|")) continue;
94
+
95
+ const idMatch = new RegExp(`^\\|\\s*(${activeSection.idPrefix}\\d+)\\s*\\|`).exec(trimmed);
96
+ if (!idMatch) continue;
97
+
98
+ rows.push({
99
+ table: activeSection.table,
100
+ id: idMatch[1] ?? "",
101
+ raw: trimmed,
102
+ cells: splitPipeRow(trimmed),
103
+ });
104
+ }
105
+
106
+ return rows;
107
+ }
108
+
109
+ /**
110
+ * Slice the KNOWLEDGE.md content to just the intro prose plus the `## Rules`
111
+ * section, dropping `## Patterns` and `## Lessons Learned`. Used by
112
+ * `loadKnowledgeBlock` to avoid double-injecting Patterns and Lessons —
113
+ * those reach the LLM via `loadMemoryBlock` after the ADR-013 Stage 2b
114
+ * cutover, so re-emitting them through the KNOWLEDGE.md block is pure
115
+ * token-cost overhead.
116
+ *
117
+ * Returns the full content unchanged when no `## Rules` heading exists
118
+ * (legacy projects or unusual layouts — better to over-inject than drop
119
+ * unfamiliar content silently).
120
+ */
121
+ export function extractIntroAndRules(content: string): string {
122
+ if (!content.trim()) return "";
123
+ const lines = content.split("\n");
124
+ const rulesIdx = lines.findIndex((l) => l.trim() === "## Rules");
125
+ if (rulesIdx === -1) return content;
126
+
127
+ // End of the Rules section is the next `## ` heading (Patterns or
128
+ // Lessons Learned) or end-of-file. Drop trailing blank lines so the
129
+ // caller can join the slice without producing a triple newline.
130
+ let endIdx = lines.length;
131
+ for (let i = rulesIdx + 1; i < lines.length; i++) {
132
+ if (lines[i]!.startsWith("## ")) {
133
+ endIdx = i;
134
+ break;
135
+ }
136
+ }
137
+ const slice = lines.slice(0, endIdx);
138
+ while (slice.length > 0 && slice[slice.length - 1]!.trim() === "") {
139
+ slice.pop();
140
+ }
141
+ return slice.join("\n") + "\n";
142
+ }
143
+
144
+ /**
145
+ * Split a Markdown table row on un-escaped pipes. Returns the cell values
146
+ * (without the leading/trailing empty fragments from `| ... |`), each
147
+ * trimmed. Escaped pipes (`\|`) inside a cell are preserved as `|` in the
148
+ * output.
149
+ */
150
+ export function splitPipeRow(row: string): string[] {
151
+ const cells: string[] = [];
152
+ let current = "";
153
+ for (let i = 0; i < row.length; i++) {
154
+ const ch = row[i];
155
+ if (ch === "\\" && row[i + 1] === "|") {
156
+ current += "|";
157
+ i += 1;
158
+ continue;
159
+ }
160
+ if (ch === "|") {
161
+ cells.push(current.trim());
162
+ current = "";
163
+ continue;
164
+ }
165
+ current += ch;
166
+ }
167
+ if (current.trim().length > 0) {
168
+ cells.push(current.trim());
169
+ }
170
+ // Drop the leading empty fragment from `|<cell>|...|` — the first split
171
+ // produces an empty string before the first pipe.
172
+ if (cells.length > 0 && cells[0] === "") cells.shift();
173
+ return cells;
174
+ }
@@ -0,0 +1,241 @@
1
+ // GSD2 — KNOWLEDGE.md hybrid projection renderer (ADR-013 Stage 2b).
2
+ //
3
+ // Renders `.gsd/KNOWLEDGE.md` as a hybrid file:
4
+ // - Rules section: read directly from the existing KNOWLEDGE.md (manual,
5
+ // per ADR-013 line 39 — Rules are not migrated to memories).
6
+ // - Patterns section: read from `memories` where `category = "pattern"`
7
+ // AND `structured_fields.sourceKnowledgeId` is set (matches the marker
8
+ // written by knowledge-backfill.ts).
9
+ // - Lessons Learned section: read from `memories` where
10
+ // `category = "gotcha"` AND `structured_fields.sourceKnowledgeId` is set.
11
+ //
12
+ // Triggered opportunistically by `buildBeforeAgentStartResult` after the
13
+ // knowledge backfill runs. Output is byte-stable when nothing has changed
14
+ // (atomic write). The Rules section is preserved verbatim — including
15
+ // indentation, trailing whitespace, and comments — so manual edits to that
16
+ // section continue to round-trip through `/gsd knowledge`.
17
+ //
18
+ // Memories captured directly via `capture_thought` (without a
19
+ // `sourceKnowledgeId` marker) are intentionally NOT rendered into
20
+ // KNOWLEDGE.md. They remain accessible via the loadMemoryBlock auto-injection
21
+ // surface; KNOWLEDGE.md projects only the KNOWLEDGE.md-originating subset.
22
+
23
+ import { atomicWriteSync } from "./atomic-write.js";
24
+ import { _getAdapter, isDbAvailable } from "./gsd-db.js";
25
+ import {
26
+ KNOWLEDGE_SECTIONS,
27
+ knowledgeMdPath,
28
+ readKnowledgeMd,
29
+ } from "./knowledge-parser.js";
30
+ import { logWarning } from "./workflow-logger.js";
31
+
32
+ const RULES_HEADING = "## Rules";
33
+ const PATTERNS_HEADING = "## Patterns";
34
+ const LESSONS_HEADING = "## Lessons Learned";
35
+
36
+ const PATTERNS_HEADER = "| # | Pattern | Where | Notes |";
37
+ const PATTERNS_SEPARATOR = "|---|---------|-------|-------|";
38
+
39
+ const LESSONS_HEADER = "| # | What Happened | Root Cause | Fix | Scope |";
40
+ const LESSONS_SEPARATOR = "|---|--------------|------------|-----|-------|";
41
+
42
+ const DEFAULT_INTRO = [
43
+ "# Project Knowledge",
44
+ "",
45
+ "Append-only register of project-specific rules, patterns, and lessons learned.",
46
+ "Agents read this before every unit. Add entries when you discover something worth remembering.",
47
+ "",
48
+ ].join("\n");
49
+
50
+ interface KnowledgeMemoryRow {
51
+ sourceId: string;
52
+ structured: Record<string, unknown>;
53
+ }
54
+
55
+ interface KnowledgeMemoryReadResult {
56
+ ok: boolean;
57
+ rows: KnowledgeMemoryRow[];
58
+ }
59
+
60
+ export interface KnowledgeProjectionResult {
61
+ written: boolean;
62
+ content: string;
63
+ }
64
+
65
+ /**
66
+ * Read pattern memories that originated from KNOWLEDGE.md, ordered by
67
+ * `sourceKnowledgeId` (lexicographic — P001 < P002 < P010). Memories whose
68
+ * structuredFields fail to parse are skipped silently; they are diagnosed
69
+ * separately by the memory-consolidation scanner.
70
+ */
71
+ function readKnowledgeMemories(category: "pattern" | "gotcha"): KnowledgeMemoryReadResult {
72
+ if (!isDbAvailable()) return { ok: false, rows: [] };
73
+ const adapter = _getAdapter();
74
+ if (!adapter) return { ok: false, rows: [] };
75
+ try {
76
+ const rows = adapter
77
+ .prepare(
78
+ "SELECT structured_fields FROM memories WHERE category = :cat AND structured_fields IS NOT NULL",
79
+ )
80
+ .all({ ":cat": category }) as Array<{ structured_fields: string | null }>;
81
+
82
+ const out: KnowledgeMemoryRow[] = [];
83
+ for (const row of rows) {
84
+ if (!row.structured_fields) continue;
85
+ let sf: Record<string, unknown>;
86
+ try {
87
+ sf = JSON.parse(row.structured_fields) as Record<string, unknown>;
88
+ } catch {
89
+ continue;
90
+ }
91
+ const sourceId = sf["sourceKnowledgeId"];
92
+ if (typeof sourceId !== "string" || sourceId.length === 0) continue;
93
+ out.push({ sourceId, structured: sf });
94
+ }
95
+ // Lexicographic sort matches the docstring contract (P001 < P002 < P010).
96
+ // DB seq order is creation-time; sorting by sourceId stabilizes the
97
+ // rendered output across reruns.
98
+ out.sort((a, b) => a.sourceId.localeCompare(b.sourceId));
99
+ return { ok: true, rows: out };
100
+ } catch {
101
+ return { ok: false, rows: [] };
102
+ }
103
+ }
104
+
105
+ function escapeCell(value: string | undefined): string {
106
+ return (value ?? "")
107
+ .replace(/\s+/g, " ")
108
+ .replace(/\|/g, "\\|")
109
+ .trim();
110
+ }
111
+
112
+ function renderPatternsSection(memories: KnowledgeMemoryRow[]): string[] {
113
+ const lines = [PATTERNS_HEADING, "", PATTERNS_HEADER, PATTERNS_SEPARATOR];
114
+ for (const m of memories) {
115
+ const pattern = escapeCell(typeof m.structured["pattern"] === "string" ? (m.structured["pattern"] as string) : "");
116
+ const where = escapeCell(typeof m.structured["where"] === "string" ? (m.structured["where"] as string) : "");
117
+ const notes = escapeCell(typeof m.structured["notes"] === "string" ? (m.structured["notes"] as string) : "");
118
+ lines.push(`| ${m.sourceId} | ${pattern} | ${where || "—"} | ${notes || "—"} |`);
119
+ }
120
+ lines.push("");
121
+ return lines;
122
+ }
123
+
124
+ function renderLessonsSection(memories: KnowledgeMemoryRow[]): string[] {
125
+ const lines = [LESSONS_HEADING, "", LESSONS_HEADER, LESSONS_SEPARATOR];
126
+ for (const m of memories) {
127
+ const what = escapeCell(typeof m.structured["whatHappened"] === "string" ? (m.structured["whatHappened"] as string) : "");
128
+ const rootCause = escapeCell(typeof m.structured["rootCause"] === "string" ? (m.structured["rootCause"] as string) : "");
129
+ const fix = escapeCell(typeof m.structured["fix"] === "string" ? (m.structured["fix"] as string) : "");
130
+ const scope = escapeCell(typeof m.structured["scopeText"] === "string" ? (m.structured["scopeText"] as string) : "");
131
+ lines.push(`| ${m.sourceId} | ${what} | ${rootCause || "—"} | ${fix || "—"} | ${scope || "project"} |`);
132
+ }
133
+ lines.push("");
134
+ return lines;
135
+ }
136
+
137
+ /**
138
+ * Extract the Rules section (heading + table) from the existing
139
+ * `KNOWLEDGE.md` content, verbatim. Returns an empty default section
140
+ * (heading + empty table) when the source has no `## Rules` heading.
141
+ */
142
+ function extractRulesSection(existing: string): string[] {
143
+ const lines = existing.split("\n");
144
+ const startIdx = lines.findIndex((l) => l.trim() === RULES_HEADING);
145
+ if (startIdx === -1) {
146
+ return [
147
+ RULES_HEADING,
148
+ "",
149
+ "| # | Scope | Rule | Why | Added |",
150
+ "|---|-------|------|-----|-------|",
151
+ "",
152
+ ];
153
+ }
154
+
155
+ // Find the next H2 heading that ends the Rules section.
156
+ let endIdx = lines.length;
157
+ for (let i = startIdx + 1; i < lines.length; i++) {
158
+ if (lines[i]!.startsWith("## ")) {
159
+ endIdx = i;
160
+ break;
161
+ }
162
+ }
163
+
164
+ // Strip trailing blank lines from the captured slice — the assembled
165
+ // output adds its own separator blank line between sections.
166
+ const slice = lines.slice(startIdx, endIdx);
167
+ while (slice.length > 0 && slice[slice.length - 1]!.trim() === "") {
168
+ slice.pop();
169
+ }
170
+ slice.push("");
171
+ return slice;
172
+ }
173
+
174
+ /**
175
+ * Extract the intro prose (anything before `## Rules`) verbatim, preserving
176
+ * any title (`# Project Knowledge`), comments, and description text. Falls
177
+ * back to the `DEFAULT_INTRO` template when the source has no Rules heading
178
+ * yet.
179
+ */
180
+ function extractIntro(existing: string): string {
181
+ if (!existing.trim()) return DEFAULT_INTRO;
182
+ const lines = existing.split("\n");
183
+ const rulesIdx = lines.findIndex((l) => l.trim() === RULES_HEADING);
184
+ if (rulesIdx === -1) return DEFAULT_INTRO;
185
+ // Trim trailing blank lines so the assembly adds its own separator.
186
+ const slice = lines.slice(0, rulesIdx);
187
+ while (slice.length > 0 && slice[slice.length - 1]!.trim() === "") {
188
+ slice.pop();
189
+ }
190
+ slice.push("");
191
+ return slice.join("\n");
192
+ }
193
+
194
+ /**
195
+ * Render the hybrid `KNOWLEDGE.md`: manual Rules + projected Patterns +
196
+ * projected Lessons. Returns the rendered content and a flag indicating
197
+ * whether the file was written (skipped when content is byte-identical to
198
+ * what's on disk).
199
+ *
200
+ * Best-effort: catches all errors and returns `{ written: false, content: "" }`.
201
+ */
202
+ export function renderKnowledgeProjection(basePath: string): KnowledgeProjectionResult {
203
+ try {
204
+ const existing = readKnowledgeMd(basePath);
205
+ const intro = extractIntro(existing);
206
+ const rules = extractRulesSection(existing);
207
+ const patternMemories = readKnowledgeMemories("pattern");
208
+ const lessonMemories = readKnowledgeMemories("gotcha");
209
+ if (!patternMemories.ok || !lessonMemories.ok) {
210
+ return { written: false, content: existing };
211
+ }
212
+ const patterns = renderPatternsSection(patternMemories.rows);
213
+ const lessons = renderLessonsSection(lessonMemories.rows);
214
+
215
+ const introText = intro
216
+ .replace(/\n{3,}/g, "\n\n")
217
+ .replace(/\s+$/g, "");
218
+ const projectedText = [...patterns, ...lessons]
219
+ .join("\n")
220
+ .replace(/\n{3,}/g, "\n\n")
221
+ .replace(/\s+$/g, "");
222
+ const content = [introText, rules.join("\n"), projectedText]
223
+ .join("\n")
224
+ .replace(/\s+$/g, "")
225
+ + "\n";
226
+
227
+ if (content === existing) {
228
+ return { written: false, content };
229
+ }
230
+
231
+ atomicWriteSync(knowledgeMdPath(basePath), content, "utf-8");
232
+ return { written: true, content };
233
+ } catch (e) {
234
+ logWarning("renderer", `KNOWLEDGE.md projection render failed: ${(e as Error).message}`);
235
+ return { written: false, content: "" };
236
+ }
237
+ }
238
+
239
+ // Re-export the section headings so tests can assert on the canonical
240
+ // structure without re-defining the strings.
241
+ export { KNOWLEDGE_SECTIONS };
@@ -157,7 +157,12 @@ function renderRoadmapMarkdown(milestone: MilestoneRow, slices: SliceRow[]): str
157
157
  for (const slice of slices) {
158
158
  const done = isClosedStatus(slice.status) ? "x" : " ";
159
159
  const depends = `[${(slice.depends ?? []).join(",")}]`;
160
- lines.push(`- [${done}] **${slice.id}: ${slice.title}** \`risk:${slice.risk}\` \`depends:${depends}\``);
160
+ // ADR-011: sketch slices get a `[sketch]` badge so the roadmap shows at a
161
+ // glance which slices are still pending refine-slice expansion. The badge
162
+ // sits in front of `risk:` so it's visible in narrow terminals that may
163
+ // truncate the line.
164
+ const sketchBadge = slice.is_sketch === 1 ? "`[sketch]` " : "";
165
+ lines.push(`- [${done}] **${slice.id}: ${slice.title}** ${sketchBadge}\`risk:${slice.risk}\` \`depends:${depends}\``);
161
166
  lines.push(` > After this: ${slice.demo}`);
162
167
  lines.push("");
163
168
  }
@@ -920,101 +925,10 @@ export function detectStaleRenders(basePath: string): StaleEntry[] {
920
925
  }
921
926
 
922
927
  // ─── Stale Repair ─────────────────────────────────────────────────────────
923
-
924
- /**
925
- * Repair all stale renders detected by `detectStaleRenders()`.
926
- *
927
- * For each stale entry, calls the appropriate render function:
928
- * - Roadmap checkbox mismatches → renderRoadmapCheckboxes()
929
- * - Plan checkbox mismatches → renderPlanCheckboxes()
930
- * - Missing task summaries → renderTaskSummary()
931
- * - Missing slice summaries/UATs → renderSliceSummary()
932
- *
933
- * Idempotent: calling twice with no DB changes produces zero repairs on the second call.
934
- *
935
- * @returns the number of files repaired
936
- */
937
- export async function repairStaleRenders(basePath: string): Promise<number> {
938
- const staleEntries = detectStaleRenders(basePath);
939
- if (staleEntries.length === 0) return 0;
940
-
941
- // Deduplicate: a single roadmap/plan file might appear multiple times
942
- // (once per mismatched checkbox). We only need to re-render it once.
943
- const repairedPaths = new Set<string>();
944
- let repairCount = 0;
945
-
946
- for (const entry of staleEntries) {
947
- if (repairedPaths.has(entry.path)) continue;
948
- // Normalize path separators for cross-platform regex matching
949
- const normPath = entry.path.replace(/\\/g, "/");
950
-
951
- try {
952
- // Determine repair action from the reason
953
- if (entry.reason.includes("in roadmap")) {
954
- // Roadmap checkbox mismatch — extract milestone ID from path
955
- const milestoneMatch = normPath.match(/milestones\/([^/]+)\//);
956
- if (milestoneMatch) {
957
- const ok = await renderRoadmapCheckboxes(basePath, milestoneMatch[1]);
958
- if (ok) {
959
- repairedPaths.add(entry.path);
960
- repairCount++;
961
- }
962
- }
963
- } else if (entry.reason.includes("in plan")) {
964
- // Plan checkbox mismatch — extract milestone + slice IDs from path
965
- const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
966
- if (pathMatch) {
967
- const ok = await renderPlanCheckboxes(basePath, pathMatch[1], pathMatch[2]);
968
- if (ok) {
969
- repairedPaths.add(entry.path);
970
- repairCount++;
971
- }
972
- }
973
- } else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^T\d+/)) {
974
- // Missing task summary — extract IDs from path
975
- const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\/tasks\//);
976
- const taskMatch = entry.reason.match(/^(T\d+)/);
977
- if (pathMatch && taskMatch) {
978
- const ok = await renderTaskSummary(basePath, pathMatch[1], pathMatch[2], taskMatch[1]);
979
- if (ok) {
980
- repairedPaths.add(entry.path);
981
- repairCount++;
982
- }
983
- }
984
- } else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^S\d+/)) {
985
- // Missing slice summary — extract IDs from path
986
- const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
987
- if (pathMatch) {
988
- const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
989
- if (ok) {
990
- repairedPaths.add(entry.path);
991
- repairCount++;
992
- }
993
- }
994
- } else if (entry.reason.includes("UAT.md missing")) {
995
- // Missing slice UAT — renderSliceSummary handles both SUMMARY + UAT
996
- const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
997
- if (pathMatch) {
998
- const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
999
- if (ok) {
1000
- repairedPaths.add(entry.path);
1001
- repairCount++;
1002
- }
1003
- }
1004
- }
1005
- } catch (err) {
1006
- logWarning("renderer", `repair failed for ${entry.path}: ${(err as Error).message}`);
1007
- }
1008
- }
1009
-
1010
- if (repairCount > 0) {
1011
- process.stderr.write(
1012
- `markdown-renderer: repaired ${repairCount} stale render(s)\n`,
1013
- );
1014
- }
1015
-
1016
- return repairCount;
1017
- }
928
+ // Body relocated to state-reconciliation/drift/stale-render.ts (ADR-017 #5702).
929
+ // detectStaleRenders above stays as a useful diagnostic primitive; the
930
+ // drift handler composes it with the per-reason renderer dispatch and the
931
+ // reconcileBeforeDispatch lifecycle.
1018
932
 
1019
933
  // ─── Replan & Assessment Renderers ────────────────────────────────────────
1020
934