gsd-pi 2.81.0 → 2.82.0-dev.2841a1e44

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 (572) hide show
  1. package/README.md +63 -32
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +3 -1
  4. package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
  5. package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
  6. package/dist/resources/extensions/cmux/index.js +5 -0
  7. package/dist/resources/extensions/gsd/auto/loop.js +111 -8
  8. package/dist/resources/extensions/gsd/auto/orchestrator.js +113 -6
  9. package/dist/resources/extensions/gsd/auto/phases.js +199 -97
  10. package/dist/resources/extensions/gsd/auto/run-unit.js +66 -3
  11. package/dist/resources/extensions/gsd/auto/session.js +9 -0
  12. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +43 -0
  13. package/dist/resources/extensions/gsd/auto-dashboard.js +182 -178
  14. package/dist/resources/extensions/gsd/auto-dispatch.js +14 -11
  15. package/dist/resources/extensions/gsd/auto-post-unit.js +176 -125
  16. package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
  17. package/dist/resources/extensions/gsd/auto-recovery.js +6 -181
  18. package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -0
  19. package/dist/resources/extensions/gsd/auto-start.js +20 -23
  20. package/dist/resources/extensions/gsd/auto-unit-closeout.js +33 -5
  21. package/dist/resources/extensions/gsd/auto-verification.js +38 -26
  22. package/dist/resources/extensions/gsd/auto-worktree.js +8 -0
  23. package/dist/resources/extensions/gsd/auto.js +371 -106
  24. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +13 -6
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +13 -2
  26. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +4 -8
  27. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +16 -7
  28. package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
  29. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +3 -1
  30. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  31. package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
  32. package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
  33. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +4 -10
  34. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +9 -0
  35. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  36. package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
  37. package/dist/resources/extensions/gsd/context-store.js +112 -0
  38. package/dist/resources/extensions/gsd/db-writer.js +150 -84
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  40. package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
  41. package/dist/resources/extensions/gsd/git-service.js +2 -1
  42. package/dist/resources/extensions/gsd/gsd-db.js +7 -23
  43. package/dist/resources/extensions/gsd/health-widget-core.js +1 -1
  44. package/dist/resources/extensions/gsd/health-widget.js +4 -10
  45. package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
  46. package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
  47. package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
  48. package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
  49. package/dist/resources/extensions/gsd/markdown-renderer.js +6 -96
  50. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  51. package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
  52. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
  53. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  54. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  55. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  56. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  57. package/dist/resources/extensions/gsd/native-git-bridge.js +14 -14
  58. package/dist/resources/extensions/gsd/notification-overlay.js +35 -40
  59. package/dist/resources/extensions/gsd/parallel-merge.js +53 -30
  60. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +25 -33
  61. package/dist/resources/extensions/gsd/prompts/complete-slice.md +14 -12
  62. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
  63. package/dist/resources/extensions/gsd/prompts/discuss.md +20 -2
  64. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  65. package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
  66. package/dist/resources/extensions/gsd/recovery-classification.js +15 -1
  67. package/dist/resources/extensions/gsd/session-lock.js +40 -0
  68. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +131 -0
  69. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +247 -0
  70. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +50 -0
  71. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +87 -0
  72. package/dist/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.js +50 -0
  73. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +124 -0
  74. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +32 -0
  75. package/dist/resources/extensions/gsd/state-reconciliation/errors.js +41 -0
  76. package/dist/resources/extensions/gsd/state-reconciliation/index.js +99 -0
  77. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +24 -0
  78. package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +43 -0
  79. package/dist/resources/extensions/gsd/state-reconciliation/types.js +3 -0
  80. package/dist/resources/extensions/gsd/state-reconciliation.js +5 -26
  81. package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
  82. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  83. package/dist/resources/extensions/gsd/tui/render-kit.js +74 -0
  84. package/dist/resources/extensions/gsd/unit-context-manifest.js +25 -2
  85. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  86. package/dist/resources/extensions/gsd/watch/header-renderer.js +92 -69
  87. package/dist/resources/extensions/gsd/watch/splash-palette.js +10 -0
  88. package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
  89. package/dist/resources/extensions/gsd/worktree-lifecycle.js +743 -318
  90. package/dist/resources/extensions/gsd/worktree-telemetry.js +3 -1
  91. package/dist/resources/extensions/subagent/index.js +448 -78
  92. package/dist/resources/extensions/subagent/launch.js +77 -0
  93. package/dist/resources/extensions/subagent/run-store.js +148 -0
  94. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  95. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  96. package/dist/resources/extensions/visual-brief/index.js +5 -0
  97. package/dist/resources/extensions/visual-brief/page-contract.js +122 -0
  98. package/dist/resources/extensions/visual-brief/prompts.js +111 -0
  99. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  100. package/dist/web/standalone/.next/BUILD_ID +1 -1
  101. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  102. package/dist/web/standalone/.next/build-manifest.json +4 -4
  103. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  104. package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
  105. package/dist/web/standalone/.next/required-server-files.json +3 -3
  106. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  107. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  117. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  126. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  145. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  165. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  175. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  181. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  197. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  201. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/index.html +1 -1
  211. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  212. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  213. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  214. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  215. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  216. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  217. package/dist/web/standalone/.next/server/app/page.js +2 -2
  218. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  219. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  220. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  221. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  222. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  223. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  224. package/dist/web/standalone/.next/server/middleware.js +2 -2
  225. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  227. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  228. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  229. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  230. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  231. package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
  232. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  233. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  234. package/dist/web/standalone/.next/static/chunks/app/page-752f1e2ebdaa3e45.js +1 -0
  235. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  236. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  237. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-6a95bc41e0f7ec89.js} +1 -1
  238. package/dist/web/standalone/.next/static/css/0262768ec1b89d34.css +1 -0
  239. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  240. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  241. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  242. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  243. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  244. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  245. package/dist/web/standalone/server.js +1 -1
  246. package/dist/welcome-screen.d.ts +0 -7
  247. package/dist/welcome-screen.js +60 -69
  248. package/package.json +5 -4
  249. package/packages/contracts/dist/rpc.test.js +7 -0
  250. package/packages/contracts/dist/rpc.test.js.map +1 -1
  251. package/packages/contracts/dist/workflow.d.ts +21 -0
  252. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  253. package/packages/contracts/dist/workflow.js +24 -0
  254. package/packages/contracts/dist/workflow.js.map +1 -1
  255. package/packages/contracts/src/rpc.test.ts +8 -0
  256. package/packages/contracts/src/workflow.ts +24 -0
  257. package/packages/daemon/package.json +2 -2
  258. package/packages/mcp-server/README.md +14 -3
  259. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  260. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  261. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  262. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  263. package/packages/mcp-server/package.json +2 -2
  264. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  265. package/packages/mcp-server/src/workflow-tools.test.ts +22 -0
  266. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  267. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  268. package/packages/native/package.json +1 -1
  269. package/packages/pi-agent-core/package.json +1 -1
  270. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  271. package/packages/pi-ai/dist/index.d.ts +2 -2
  272. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  273. package/packages/pi-ai/dist/index.js +1 -1
  274. package/packages/pi-ai/dist/index.js.map +1 -1
  275. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  276. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  277. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  278. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  279. package/packages/pi-ai/package.json +1 -1
  280. package/packages/pi-ai/src/index.ts +7 -2
  281. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  282. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  283. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  284. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts +2 -0
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.d.ts.map +1 -0
  287. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js +47 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/assistant-message-design.test.js.map +1 -0
  289. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +76 -9
  290. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  291. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts +2 -0
  292. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.d.ts.map +1 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js +40 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/user-message-design.test.js.map +1 -0
  295. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +0 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +30 -29
  298. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +10 -3
  300. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +13 -13
  303. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +1 -3
  305. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +58 -3
  307. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +2 -2
  309. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +12 -6
  311. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  313. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -41
  314. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  315. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +0 -1
  316. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +86 -82
  318. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts +35 -0
  320. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.d.ts.map +1 -0
  321. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js +152 -0
  322. package/packages/pi-coding-agent/dist/modes/interactive/components/transcript-design.js.map +1 -0
  323. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts +16 -0
  324. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.d.ts.map +1 -0
  325. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js +73 -0
  326. package/packages/pi-coding-agent/dist/modes/interactive/components/tui-style-kit.js.map +1 -0
  327. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +1 -1
  328. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +12 -8
  330. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  332. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  333. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  334. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  335. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  336. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +105 -1
  337. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  338. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  339. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +27 -26
  340. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  341. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +9 -6
  342. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  344. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  345. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  346. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  347. package/packages/pi-coding-agent/package.json +1 -1
  348. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  349. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +56 -0
  350. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +113 -9
  351. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +48 -0
  352. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +10 -3
  353. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +43 -42
  354. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +14 -14
  355. package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +64 -3
  356. package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +13 -7
  357. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +15 -42
  358. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -104
  359. package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +196 -0
  360. package/packages/pi-coding-agent/src/modes/interactive/components/tui-style-kit.ts +94 -0
  361. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +14 -9
  362. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
  363. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +106 -1
  364. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +27 -26
  365. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +9 -6
  366. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  367. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  368. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +14 -1
  369. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  370. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
  371. package/packages/pi-tui/dist/overlay-layout.js +9 -6
  372. package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
  373. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  374. package/packages/pi-tui/dist/tui.js +5 -0
  375. package/packages/pi-tui/dist/tui.js.map +1 -1
  376. package/packages/pi-tui/package.json +1 -1
  377. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +20 -1
  378. package/packages/pi-tui/src/overlay-layout.ts +10 -7
  379. package/packages/pi-tui/src/tui.ts +6 -0
  380. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  381. package/packages/rpc-client/package.json +1 -1
  382. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  383. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts +2 -0
  384. package/pkg/dist/modes/interactive/theme/theme-highlight.test.d.ts.map +1 -0
  385. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js +17 -0
  386. package/pkg/dist/modes/interactive/theme/theme-highlight.test.js.map +1 -0
  387. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  388. package/pkg/dist/modes/interactive/theme/theme.js +105 -1
  389. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  390. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  391. package/pkg/dist/modes/interactive/theme/themes.js +27 -26
  392. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  393. package/pkg/package.json +1 -1
  394. package/src/resources/GSD-WORKFLOW.md +3 -1
  395. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  396. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  397. package/src/resources/extensions/cmux/index.ts +6 -0
  398. package/src/resources/extensions/gsd/auto/contracts.ts +46 -11
  399. package/src/resources/extensions/gsd/auto/loop-deps.ts +9 -5
  400. package/src/resources/extensions/gsd/auto/loop.ts +113 -9
  401. package/src/resources/extensions/gsd/auto/orchestrator.ts +118 -6
  402. package/src/resources/extensions/gsd/auto/phases.ts +158 -19
  403. package/src/resources/extensions/gsd/auto/run-unit.ts +69 -4
  404. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  405. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
  406. package/src/resources/extensions/gsd/auto-dashboard.ts +230 -183
  407. package/src/resources/extensions/gsd/auto-dispatch.ts +15 -1
  408. package/src/resources/extensions/gsd/auto-post-unit.ts +201 -138
  409. package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
  410. package/src/resources/extensions/gsd/auto-recovery.ts +7 -209
  411. package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
  412. package/src/resources/extensions/gsd/auto-start.ts +22 -22
  413. package/src/resources/extensions/gsd/auto-unit-closeout.ts +51 -0
  414. package/src/resources/extensions/gsd/auto-verification.ts +46 -38
  415. package/src/resources/extensions/gsd/auto-worktree.ts +8 -0
  416. package/src/resources/extensions/gsd/auto.ts +411 -106
  417. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -6
  418. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -2
  419. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +5 -8
  420. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +16 -6
  421. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  422. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +3 -2
  423. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  424. package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
  425. package/src/resources/extensions/gsd/commands/handlers/core.ts +25 -1
  426. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +4 -10
  427. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +12 -0
  428. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  429. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  430. package/src/resources/extensions/gsd/context-store.ts +120 -1
  431. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  432. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  433. package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
  434. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  435. package/src/resources/extensions/gsd/git-service.ts +2 -0
  436. package/src/resources/extensions/gsd/gsd-db.ts +7 -23
  437. package/src/resources/extensions/gsd/health-widget-core.ts +1 -1
  438. package/src/resources/extensions/gsd/health-widget.ts +6 -10
  439. package/src/resources/extensions/gsd/journal.ts +2 -0
  440. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  441. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  442. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  443. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  444. package/src/resources/extensions/gsd/markdown-renderer.ts +10 -96
  445. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  446. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  447. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  448. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  449. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  450. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  451. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  452. package/src/resources/extensions/gsd/native-git-bridge.ts +14 -13
  453. package/src/resources/extensions/gsd/notification-overlay.ts +50 -46
  454. package/src/resources/extensions/gsd/parallel-merge.ts +61 -34
  455. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +33 -35
  456. package/src/resources/extensions/gsd/prompts/complete-slice.md +14 -12
  457. package/src/resources/extensions/gsd/prompts/discuss-headless.md +20 -2
  458. package/src/resources/extensions/gsd/prompts/discuss.md +20 -2
  459. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  460. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  461. package/src/resources/extensions/gsd/recovery-classification.ts +18 -1
  462. package/src/resources/extensions/gsd/session-lock.ts +41 -0
  463. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
  464. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +337 -0
  465. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +69 -0
  466. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +109 -0
  467. package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
  468. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
  469. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
  470. package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
  471. package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
  472. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
  473. package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +60 -0
  474. package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
  475. package/src/resources/extensions/gsd/state-reconciliation.ts +21 -53
  476. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  477. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
  478. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +99 -0
  479. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +729 -176
  480. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +408 -4
  481. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +292 -4
  482. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +20 -5
  483. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +18 -0
  484. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
  485. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  486. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  487. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  488. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  489. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  490. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +28 -1
  491. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  492. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  493. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  494. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +20 -2
  495. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +44 -0
  496. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  497. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  498. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  499. package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
  500. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +10 -0
  501. package/src/resources/extensions/gsd/tests/health-widget.test.ts +14 -4
  502. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  503. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +26 -0
  504. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  505. package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +1 -1
  506. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  507. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +116 -24
  508. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -1
  509. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  510. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  511. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  512. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  513. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1 -1
  514. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  515. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +46 -11
  516. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  517. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  518. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +78 -41
  519. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +44 -0
  520. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +12 -217
  521. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +38 -6
  522. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  523. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +81 -3
  524. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +1 -1
  525. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +32 -1
  526. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  527. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +7 -3
  528. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +6 -3
  529. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  530. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +24 -0
  531. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +71 -58
  532. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +952 -0
  533. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -0
  534. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +121 -1
  535. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +66 -0
  536. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +21 -0
  537. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
  538. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  539. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +6 -0
  540. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +158 -58
  541. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +597 -118
  542. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +59 -2
  543. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
  544. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  545. package/src/resources/extensions/gsd/tui/render-kit.ts +109 -0
  546. package/src/resources/extensions/gsd/unit-context-manifest.ts +35 -2
  547. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  548. package/src/resources/extensions/gsd/watch/header-renderer.ts +121 -79
  549. package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
  550. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  551. package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
  552. package/src/resources/extensions/gsd/worktree-lifecycle.ts +1171 -526
  553. package/src/resources/extensions/gsd/worktree-telemetry.ts +7 -2
  554. package/src/resources/extensions/subagent/index.ts +567 -103
  555. package/src/resources/extensions/subagent/launch.ts +131 -0
  556. package/src/resources/extensions/subagent/run-store.ts +218 -0
  557. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  558. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  559. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  560. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  561. package/src/resources/extensions/visual-brief/index.ts +8 -0
  562. package/src/resources/extensions/visual-brief/page-contract.ts +134 -0
  563. package/src/resources/extensions/visual-brief/prompts.ts +147 -0
  564. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +172 -0
  565. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  566. package/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +0 -1
  567. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  568. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  569. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  570. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +0 -1544
  571. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → Qgr2B_MRhPxC0z8fwv4vT}/_buildManifest.js +0 -0
  572. /package/dist/web/standalone/.next/static/{drLMkgfHQ8lzS229_HWYR → Qgr2B_MRhPxC0z8fwv4vT}/_ssgManifest.js +0 -0
@@ -0,0 +1,277 @@
1
+ // GSD-2 — ADR-013 Phase 6 preflight scanner.
2
+ //
3
+ // Read-only detection of rows in the legacy knowledge surfaces (decisions
4
+ // table, `.gsd/KNOWLEDGE.md`) that lack a corresponding `memories` row.
5
+ // Runs on session start (and on demand via doctor); never mutates state.
6
+ //
7
+ // The scanner exists so the destructive Phase 6 cutover (#5755) can prove
8
+ // the migration is complete before any tables are dropped. Today's
9
+ // `backfillDecisionsToMemories` writes a `structured_fields.sourceDecisionId`
10
+ // marker on each migrated row; the scanner uses that marker for decisions
11
+ // detection. A `sourceKnowledgeId` marker is reserved for the parallel
12
+ // KNOWLEDGE.md backfill that Phase 6 will introduce — until that ships,
13
+ // every KNOWLEDGE.md row is reported as unmigrated, which is the honest
14
+ // state of the consolidation.
15
+
16
+ import { existsSync, readFileSync } from "node:fs";
17
+
18
+ import { _getAdapter, isDbAvailable } from "./gsd-db.js";
19
+ import { appendNotification } from "./notification-store.js";
20
+ import { resolveGsdRootFile } from "./paths.js";
21
+ import { logWarning } from "./workflow-logger.js";
22
+
23
+ // ─── Types ──────────────────────────────────────────────────────────────────
24
+
25
+ export interface KnowledgeSurfaceReport {
26
+ total: number;
27
+ migrated: number;
28
+ unmigrated: number;
29
+ byTable: { rules: number; patterns: number; lessons: number };
30
+ /** Up to 5 sample row IDs/content for diagnosing what's unmigrated. */
31
+ samples: Array<{ table: "rules" | "patterns" | "lessons"; id: string; row: string }>;
32
+ }
33
+
34
+ export interface DecisionsSurfaceReport {
35
+ total: number;
36
+ migrated: number;
37
+ unmigrated: number;
38
+ /** Up to 5 sample decision IDs with a short content excerpt. */
39
+ samples: Array<{ id: string; decision: string }>;
40
+ }
41
+
42
+ export interface ConsolidationGapReport {
43
+ decisions: DecisionsSurfaceReport;
44
+ knowledge: KnowledgeSurfaceReport;
45
+ /** Sum of unmigrated rows across both surfaces. Zero ⇒ clean preflight. */
46
+ totalGaps: number;
47
+ /** Human-readable single-line summary suitable for notifications + logs. */
48
+ summary: string;
49
+ }
50
+
51
+ // ─── KNOWLEDGE.md parsing ────────────────────────────────────────────────────
52
+
53
+ const KNOWLEDGE_SECTIONS = [
54
+ { table: "rules" as const, heading: "## Rules", idPrefix: "K" },
55
+ { table: "patterns" as const, heading: "## Patterns", idPrefix: "P" },
56
+ { table: "lessons" as const, heading: "## Lessons Learned", idPrefix: "L" },
57
+ ];
58
+
59
+ interface KnowledgeRow {
60
+ table: "rules" | "patterns" | "lessons";
61
+ id: string;
62
+ row: string;
63
+ }
64
+
65
+ /**
66
+ * Parse `.gsd/KNOWLEDGE.md` into rows, one per table entry. Skips the table
67
+ * header and separator lines; ignores rows from unrecognized sections.
68
+ *
69
+ * The format is locked in `files.ts:appendKnowledge` — three `## ` sections
70
+ * (Rules, Patterns, Lessons Learned), each a Markdown table. Row IDs are
71
+ * `K###` / `P###` / `L###`.
72
+ */
73
+ export function parseKnowledgeRows(content: string): KnowledgeRow[] {
74
+ const rows: KnowledgeRow[] = [];
75
+ if (!content.trim()) return rows;
76
+
77
+ // Slice the content into sections by heading. The leading text before the
78
+ // first ## heading is intro prose — ignored.
79
+ const lines = content.split("\n");
80
+ let activeSection: typeof KNOWLEDGE_SECTIONS[number] | undefined;
81
+
82
+ for (const line of lines) {
83
+ const trimmed = line.trim();
84
+ if (trimmed.startsWith("## ")) {
85
+ activeSection = KNOWLEDGE_SECTIONS.find((s) => s.heading === trimmed);
86
+ continue;
87
+ }
88
+ if (!activeSection) continue;
89
+ if (!trimmed.startsWith("|")) continue;
90
+
91
+ // Skip the table header rows: the column-titles line and the |---|---| separator.
92
+ // Real data rows start with `| <prefix>### |`.
93
+ const idMatch = new RegExp(`^\\|\\s*(${activeSection.idPrefix}\\d+)\\s*\\|`).exec(trimmed);
94
+ if (!idMatch) continue;
95
+
96
+ rows.push({
97
+ table: activeSection.table,
98
+ id: idMatch[1] ?? "",
99
+ row: trimmed,
100
+ });
101
+ }
102
+
103
+ return rows;
104
+ }
105
+
106
+ function knowledgeMdContent(basePath: string): string {
107
+ const path = resolveGsdRootFile(basePath, "KNOWLEDGE");
108
+ if (!existsSync(path)) return "";
109
+ try {
110
+ return readFileSync(path, "utf-8");
111
+ } catch {
112
+ return "";
113
+ }
114
+ }
115
+
116
+ // ─── DB queries ──────────────────────────────────────────────────────────────
117
+
118
+ interface DecisionRow {
119
+ id: string;
120
+ decision: string;
121
+ }
122
+
123
+ function getActiveDecisions(): DecisionRow[] {
124
+ if (!isDbAvailable()) return [];
125
+ const adapter = _getAdapter();
126
+ if (!adapter) return [];
127
+ try {
128
+ const rows = adapter
129
+ .prepare(
130
+ "SELECT id, decision FROM decisions WHERE superseded_by IS NULL",
131
+ )
132
+ .all() as Array<Record<string, unknown>>;
133
+ return rows
134
+ .map((row): DecisionRow => ({
135
+ id: String(row["id"] ?? ""),
136
+ decision: String(row["decision"] ?? ""),
137
+ }))
138
+ .filter((row) => row.id.length > 0);
139
+ } catch {
140
+ return [];
141
+ }
142
+ }
143
+
144
+ /**
145
+ * True when a memory row has a `structured_fields` JSON payload containing
146
+ * the given `markerKey: "value"` pair. Matches the LIKE pattern used by
147
+ * `backfillDecisionsToMemories` so the scanner is consistent with the
148
+ * backfill's idempotency check.
149
+ */
150
+ function memoryHasSourceMarker(markerKey: string, value: string): boolean {
151
+ if (!isDbAvailable()) return false;
152
+ const adapter = _getAdapter();
153
+ if (!adapter) return false;
154
+ try {
155
+ const pattern = `%"${markerKey}":"${value}"%`;
156
+ const row = adapter
157
+ .prepare("SELECT 1 FROM memories WHERE structured_fields LIKE :pattern LIMIT 1")
158
+ .get({ ":pattern": pattern });
159
+ return row !== undefined;
160
+ } catch {
161
+ return false;
162
+ }
163
+ }
164
+
165
+ // ─── Public API ──────────────────────────────────────────────────────────────
166
+
167
+ const SAMPLE_LIMIT = 5;
168
+
169
+ /**
170
+ * Scan the legacy knowledge surfaces and return a structured report of what's
171
+ * already in the `memories` table vs what's still unmigrated. Pure detection
172
+ * — no DB writes, no file writes, no notifications.
173
+ */
174
+ export function scanConsolidationGaps(basePath: string): ConsolidationGapReport {
175
+ // ── Decisions ────────────────────────────────────────────────────────
176
+ const decisions = getActiveDecisions();
177
+ const decisionSamples: DecisionsSurfaceReport["samples"] = [];
178
+ let decisionMigrated = 0;
179
+ for (const decision of decisions) {
180
+ if (memoryHasSourceMarker("sourceDecisionId", decision.id)) {
181
+ decisionMigrated += 1;
182
+ continue;
183
+ }
184
+ if (decisionSamples.length < SAMPLE_LIMIT) {
185
+ decisionSamples.push({
186
+ id: decision.id,
187
+ decision: decision.decision.length > 80 ? decision.decision.slice(0, 79) + "…" : decision.decision,
188
+ });
189
+ }
190
+ }
191
+
192
+ // ── KNOWLEDGE.md ─────────────────────────────────────────────────────
193
+ const knowledgeRows = parseKnowledgeRows(knowledgeMdContent(basePath));
194
+ const knowledgeByTable = { rules: 0, patterns: 0, lessons: 0 };
195
+ const knowledgeSamples: KnowledgeSurfaceReport["samples"] = [];
196
+ let knowledgeMigrated = 0;
197
+ for (const row of knowledgeRows) {
198
+ knowledgeByTable[row.table] += 1;
199
+ // Phase 6 will introduce a `sourceKnowledgeId` marker as part of the
200
+ // KNOWLEDGE.md backfill. Until that path ships, this check returns
201
+ // false for every row, which is the honest state of the consolidation.
202
+ if (memoryHasSourceMarker("sourceKnowledgeId", row.id)) {
203
+ knowledgeMigrated += 1;
204
+ continue;
205
+ }
206
+ if (knowledgeSamples.length < SAMPLE_LIMIT) {
207
+ knowledgeSamples.push({
208
+ table: row.table,
209
+ id: row.id,
210
+ row: row.row.length > 100 ? row.row.slice(0, 99) + "…" : row.row,
211
+ });
212
+ }
213
+ }
214
+
215
+ const decisionsReport: DecisionsSurfaceReport = {
216
+ total: decisions.length,
217
+ migrated: decisionMigrated,
218
+ unmigrated: decisions.length - decisionMigrated,
219
+ samples: decisionSamples,
220
+ };
221
+ const knowledgeReport: KnowledgeSurfaceReport = {
222
+ total: knowledgeRows.length,
223
+ migrated: knowledgeMigrated,
224
+ unmigrated: knowledgeRows.length - knowledgeMigrated,
225
+ byTable: knowledgeByTable,
226
+ samples: knowledgeSamples,
227
+ };
228
+
229
+ const totalGaps = decisionsReport.unmigrated + knowledgeReport.unmigrated;
230
+
231
+ // Summary line is intentionally short so it fits in a single notification
232
+ // (notification-store truncates messages over 500 chars). Detail is
233
+ // accessible via getProviderSwitchStats-style callers, not embedded here.
234
+ const parts: string[] = [];
235
+ if (decisionsReport.unmigrated > 0) {
236
+ parts.push(`${decisionsReport.unmigrated} of ${decisionsReport.total} active decisions`);
237
+ }
238
+ if (knowledgeReport.unmigrated > 0) {
239
+ parts.push(`${knowledgeReport.unmigrated} of ${knowledgeReport.total} KNOWLEDGE.md rows`);
240
+ }
241
+ const summary =
242
+ parts.length === 0
243
+ ? "Memory consolidation: all decisions and KNOWLEDGE.md rows are in memories."
244
+ : `Memory consolidation: ${parts.join(" and ")} not yet in memories table. Run /doctor for details.`;
245
+
246
+ return { decisions: decisionsReport, knowledge: knowledgeReport, totalGaps, summary };
247
+ }
248
+
249
+ /**
250
+ * Run the scanner and emit a persistent notification + workflow-logger
251
+ * warning when gaps exist. Best-effort: never throws; a broken scanner
252
+ * cannot block agent startup.
253
+ *
254
+ * Returns the full {@link ConsolidationGapReport} regardless of whether gaps
255
+ * exist (including when `totalGaps === 0`). Returns `null` only when
256
+ * `scanConsolidationGaps` itself throws. `appendNotification` and
257
+ * `logWarning` are called only when `report.totalGaps > 0`.
258
+ *
259
+ * Idempotent at the surface: the notification store applies its own
260
+ * 30-second dedup window keyed on (severity, source, message), so repeated
261
+ * boots with identical gaps produce one notification, not a flood.
262
+ */
263
+ export function reportConsolidationGaps(basePath: string): ConsolidationGapReport | null {
264
+ try {
265
+ const report = scanConsolidationGaps(basePath);
266
+ if (report.totalGaps === 0) return report;
267
+ appendNotification(report.summary, "warning", "workflow-logger");
268
+ logWarning("memory-consolidation", report.summary);
269
+ return report;
270
+ } catch (e) {
271
+ logWarning(
272
+ "memory-consolidation",
273
+ `scanner failed: ${(e as Error).message}`,
274
+ );
275
+ return null;
276
+ }
277
+ }
@@ -34,6 +34,9 @@ export type MigrationImportCounts = ReturnType<typeof migrateFromMarkdown>;
34
34
 
35
35
  function assertMigrationImportMatchesPreview(imported: MigrationImportCounts, preview: MigrationPreview): void {
36
36
  const mismatches: string[] = [];
37
+ if (imported.decisions !== preview.decisions.total) {
38
+ mismatches.push(`decisions ${imported.decisions}/${preview.decisions.total}`);
39
+ }
37
40
  if (imported.hierarchy.milestones !== preview.milestoneCount) {
38
41
  mismatches.push(`milestones ${imported.hierarchy.milestones}/${preview.milestoneCount}`);
39
42
  }
@@ -73,6 +76,7 @@ export async function importWrittenMigrationToDb(
73
76
  /** Format preview stats for embedding in the review prompt. */
74
77
  function formatPreviewStats(preview: MigrationPreview): string {
75
78
  const lines = [
79
+ `- Decisions: ${preview.decisions.total}`,
76
80
  `- Milestones: ${preview.milestoneCount}`,
77
81
  `- Slices: ${preview.totalSlices} (${preview.doneSlices} done — ${preview.sliceCompletionPct}%)`,
78
82
  `- Tasks: ${preview.totalTasks} (${preview.doneTasks} done — ${preview.taskCompletionPct}%)`,
@@ -179,6 +183,7 @@ export async function handleMigrate(
179
183
 
180
184
  // ── Build preview text ─────────────────────────────────────────────────────
181
185
  const lines: string[] = [
186
+ `Decisions: ${preview.decisions.total}`,
182
187
  `Milestones: ${preview.milestoneCount}`,
183
188
  `Slices: ${preview.totalSlices} (${preview.doneSlices} done — ${preview.sliceCompletionPct}%)`,
184
189
  `Tasks: ${preview.totalTasks} (${preview.doneTasks} done — ${preview.taskCompletionPct}%)`,
@@ -4,6 +4,13 @@
4
4
  import type { GSDProject } from './types.js';
5
5
  import type { MigrationPreview } from './writer.js';
6
6
 
7
+ function countCanonicalDecisionRows(content: string): number {
8
+ return content
9
+ .split('\n')
10
+ .filter((line) => /^\|\s*D\d+\s*\|/.test(line.trim()))
11
+ .length;
12
+ }
13
+
7
14
  /**
8
15
  * Compute pre-write statistics from a GSDProject without performing I/O.
9
16
  * Used to show the user what a migration will produce before writing anything.
@@ -36,6 +43,9 @@ export function generatePreview(project: GSDProject): MigrationPreview {
36
43
  }
37
44
 
38
45
  return {
46
+ decisions: {
47
+ total: countCanonicalDecisionRows(project.decisionsContent),
48
+ },
39
49
  milestoneCount: project.milestones.length,
40
50
  totalSlices,
41
51
  totalTasks,
@@ -238,16 +238,53 @@ function normalizeStatus(status: string): 'active' | 'validated' | 'deferred' {
238
238
  return 'active';
239
239
  }
240
240
 
241
+ function normalizeRequirementId(id: string): string | null {
242
+ const match = id.trim().match(/^R(\d+)$/i);
243
+ if (!match) return null;
244
+ return `R${match[1].padStart(3, '0')}`;
245
+ }
246
+
241
247
  function mapRequirements(reqs: PlanningRequirement[]): GSDRequirement[] {
242
248
  let autoId = 0;
249
+ const reservedIds = new Set(
250
+ reqs
251
+ .map((req) => normalizeRequirementId(req.id))
252
+ .filter((id): id is string => id !== null),
253
+ );
254
+ const usedIds = new Set<string>();
255
+
256
+ function nextRequirementId(): string {
257
+ let id = '';
258
+ do {
259
+ autoId++;
260
+ id = padId('R', autoId, 3);
261
+ } while (usedIds.has(id) || reservedIds.has(id));
262
+ usedIds.add(id);
263
+ return id;
264
+ }
265
+
243
266
  return reqs.map((req) => {
244
- autoId++;
267
+ const originalId = req.id.trim();
268
+ const canonicalId = normalizeRequirementId(originalId);
269
+ let id: string;
270
+ let description = req.description;
271
+
272
+ if (canonicalId && !usedIds.has(canonicalId)) {
273
+ id = canonicalId;
274
+ usedIds.add(id);
275
+ } else {
276
+ id = nextRequirementId();
277
+ if (originalId) {
278
+ description = `Legacy ID: ${originalId}\n\n${description}`;
279
+ }
280
+ }
281
+
245
282
  return {
246
- id: req.id && req.id.trim() !== '' ? req.id : padId('R', autoId, 3),
283
+ id,
247
284
  title: req.title,
248
285
  class: 'core-capability',
249
286
  status: normalizeStatus(req.status),
250
- description: req.description,
287
+ description,
251
288
  source: 'inferred',
252
289
  primarySlice: 'none yet',
253
290
  };
@@ -286,7 +323,24 @@ function deriveDecisions(parsed: PlanningProject): string {
286
323
  }
287
324
  }
288
325
  if (decisions.length === 0) return '';
289
- return decisions.map((d) => `- ${d}`).join('\n');
326
+ const lines = [
327
+ '# Decisions Register',
328
+ '',
329
+ '<!-- Append-only. Never edit or remove existing rows.',
330
+ ' To reverse a decision, add a new row that supersedes it.',
331
+ ' Read this file at the start of any planning or research phase. -->',
332
+ '',
333
+ '| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |',
334
+ '|---|------|-------|----------|--------|-----------|------------|---------|',
335
+ ];
336
+
337
+ decisions.forEach((decision, index) => {
338
+ const id = padId('D', index + 1, 3);
339
+ const escaped = decision.replace(/\|/g, '\\|');
340
+ lines.push(`| ${id} | migration | migrated-summary | ${escaped} | ${escaped} | Migrated from legacy summary key-decisions | Yes | agent |`);
341
+ });
342
+
343
+ return lines.join('\n') + '\n';
290
344
  }
291
345
 
292
346
  // ─── Main Entry Point ──────────────────────────────────────────────────────
@@ -37,6 +37,9 @@ export interface WrittenFiles {
37
37
 
38
38
  /** Pre-write statistics computed from a GSDProject without I/O. */
39
39
  export interface MigrationPreview {
40
+ decisions: {
41
+ total: number;
42
+ };
40
43
  milestoneCount: number;
41
44
  totalSlices: number;
42
45
  totalTasks: number;
@@ -374,7 +377,17 @@ export function formatProject(content: string): string {
374
377
  */
375
378
  export function formatDecisions(content: string): string {
376
379
  if (!content || !content.trim()) {
377
- return '# Decisions\n\n<!-- Append-only register of architectural and pattern decisions -->\n\n| ID | Decision | Rationale | Date |\n|----|----------|-----------|------|\n';
380
+ return [
381
+ '# Decisions Register',
382
+ '',
383
+ '<!-- Append-only. Never edit or remove existing rows.',
384
+ ' To reverse a decision, add a new row that supersedes it.',
385
+ ' Read this file at the start of any planning or research phase. -->',
386
+ '',
387
+ '| # | When | Scope | Decision | Choice | Rationale | Revisable? | Made By |',
388
+ '|---|------|-------|----------|--------|-----------|------------|---------|',
389
+ '',
390
+ ].join('\n');
378
391
  }
379
392
  return content.endsWith('\n') ? content : content + '\n';
380
393
  }
@@ -705,20 +705,21 @@ export function nativeAddTracked(basePath: string): void {
705
705
  gitFileExec(basePath, ["add", "-u"]);
706
706
  }
707
707
 
708
- function isDotGsdIgnored(basePath: string): boolean {
709
- for (const path of [".gsd", ".gsd/"]) {
710
- try {
711
- execFileSync("git", ["check-ignore", "-q", path], {
712
- cwd: basePath,
713
- stdio: "pipe",
714
- env: GIT_NO_PROMPT_ENV,
715
- });
716
- return true;
717
- } catch {
718
- // exit 1 means this form is not ignored; try the next variant
719
- }
708
+ export function nativeIsIgnored(basePath: string, path: string): boolean {
709
+ try {
710
+ execFileSync("git", ["check-ignore", "-q", "--", path], {
711
+ cwd: basePath,
712
+ stdio: "pipe",
713
+ env: GIT_NO_PROMPT_ENV,
714
+ });
715
+ return true;
716
+ } catch {
717
+ return false;
720
718
  }
721
- return false;
719
+ }
720
+
721
+ function isDotGsdIgnored(basePath: string): boolean {
722
+ return [".gsd", ".gsd/"].some(path => nativeIsIgnored(basePath, path));
722
723
  }
723
724
 
724
725
  /**
@@ -1,9 +1,8 @@
1
- // GSD Extension — Notification History Overlay
2
- // Scrollable panel showing all persisted notifications with severity filtering.
3
- // Toggled with Ctrl+Alt+N (⌃⌥N on macOS), Ctrl+Shift+N fallback, or /gsd notifications.
1
+ // Project/App: GSD-2
2
+ // File Purpose: Notification history overlay with severity filtering and width-safe TUI rendering.
4
3
 
5
4
  import type { Theme } from "@gsd/pi-coding-agent";
6
- import { truncateToWidth, visibleWidth, wrapTextWithAnsi, matchesKey, Key } from "@gsd/pi-tui";
5
+ import { truncateToWidth, visibleWidth, matchesKey, Key } from "@gsd/pi-tui";
7
6
 
8
7
  import {
9
8
  readNotifications,
@@ -14,10 +13,32 @@ import {
14
13
  type NotifySeverity,
15
14
  } from "./notification-store.js";
16
15
  import { formattedShortcutPair } from "./shortcut-defs.js";
17
- import { padRight, joinColumns } from "../shared/mod.js";
18
-
19
- type FilterMode = "all" | "error" | "warning" | "info";
20
- const FILTER_CYCLE: FilterMode[] = ["all", "error", "warning", "info"];
16
+ import {
17
+ padRightVisible,
18
+ renderFrame,
19
+ renderKeyHints,
20
+ rightAlign,
21
+ wrapVisibleText,
22
+ } from "./tui/render-kit.js";
23
+
24
+ type FilterMode = "all" | "error" | "warning" | "success" | "info";
25
+ const FILTER_CYCLE: FilterMode[] = ["all", "error", "warning", "success", "info"];
26
+ const OVERLAY_WIDTH = "58%";
27
+ const OVERLAY_MIN_WIDTH = 68;
28
+ const OVERLAY_MAX_HEIGHT_PERCENT = 52;
29
+ const OVERLAY_MARGIN = { top: 2, right: 2, bottom: 6, left: 2 } as const;
30
+
31
+ export function notificationOverlayOptions() {
32
+ return {
33
+ width: OVERLAY_WIDTH,
34
+ minWidth: OVERLAY_MIN_WIDTH,
35
+ maxHeight: `${OVERLAY_MAX_HEIGHT_PERCENT}%`,
36
+ anchor: "top-center",
37
+ row: "24%",
38
+ margin: OVERLAY_MARGIN,
39
+ backdrop: true,
40
+ } as const;
41
+ }
21
42
 
22
43
  function severityIcon(severity: NotifySeverity): string {
23
44
  switch (severity) {
@@ -29,17 +50,6 @@ function severityIcon(severity: NotifySeverity): string {
29
50
  }
30
51
  }
31
52
 
32
- /** Column-aware word wrap using pi-tui's native wrapper (handles unicode/ANSI). */
33
- function wrapText(text: string, maxWidth: number): string[] {
34
- if (maxWidth <= 0) return [text];
35
- const lines = wrapTextWithAnsi(text, maxWidth);
36
- // Safety clamp: if any line still exceeds maxWidth (e.g. unbreakable long token),
37
- // truncate it with an ellipsis so it cannot bleed past the box border.
38
- return lines.map((l) =>
39
- visibleWidth(l) > maxWidth ? truncateToWidth(l, maxWidth, "…") : l,
40
- );
41
- }
42
-
43
53
  function formatTimestamp(ts: string): string {
44
54
  try {
45
55
  const d = new Date(ts);
@@ -184,13 +194,19 @@ export class GSDNotificationOverlay {
184
194
  }
185
195
 
186
196
  const content = this.buildContentLines(width);
187
- const maxVisibleRows = Math.max(5, process.stdout.rows ? process.stdout.rows - 8 : 24) - 2;
197
+ const terminalRows = process.stdout.rows || 32;
198
+ const availableRows = Math.max(1, terminalRows - OVERLAY_MARGIN.top - OVERLAY_MARGIN.bottom);
199
+ const overlayRows = Math.min(
200
+ availableRows,
201
+ Math.max(1, Math.floor((terminalRows * OVERLAY_MAX_HEIGHT_PERCENT) / 100)),
202
+ );
203
+ const maxVisibleRows = Math.max(5, overlayRows - 2);
188
204
  const visibleContentRows = Math.min(content.length, maxVisibleRows);
189
205
  const maxScroll = Math.max(0, content.length - visibleContentRows);
190
206
  this.scrollOffset = Math.min(this.scrollOffset, maxScroll);
191
207
  const visibleContent = content.slice(this.scrollOffset, this.scrollOffset + visibleContentRows);
192
208
 
193
- const lines = this.wrapInBox(visibleContent, width);
209
+ const lines = renderFrame(this.theme, visibleContent, width);
194
210
 
195
211
  this.cachedWidth = width;
196
212
  this.cachedLines = lines;
@@ -227,33 +243,15 @@ export class GSDNotificationOverlay {
227
243
  }
228
244
  }
229
245
 
230
- private wrapInBox(inner: string[], width: number): string[] {
231
- const th = this.theme;
232
- const border = (s: string) => th.fg("borderAccent", s);
233
- const innerWidth = width - 4;
234
- const lines: string[] = [];
235
-
236
- lines.push(border("╭" + "─".repeat(width - 2) + "╮"));
237
- for (const line of inner) {
238
- const truncated = truncateToWidth(line, innerWidth);
239
- const padWidth = Math.max(0, innerWidth - visibleWidth(truncated));
240
- lines.push(border("│") + " " + truncated + " ".repeat(padWidth) + " " + border("│"));
241
- }
242
- lines.push(border("╰" + "─".repeat(width - 2) + "╯"));
243
- return lines;
244
- }
245
-
246
246
  private buildContentLines(width: number): string[] {
247
247
  const th = this.theme;
248
- const shellWidth = width - 4;
249
- const contentWidth = Math.min(shellWidth, 128);
250
- const sidePad = Math.max(0, Math.floor((shellWidth - contentWidth) / 2));
251
- const leftMargin = " ".repeat(sidePad);
248
+ const shellWidth = Math.max(1, width - 4);
249
+ const contentWidth = shellWidth;
252
250
  const lines: string[] = [];
253
251
 
254
252
  const row = (content = ""): string => {
255
253
  const truncated = truncateToWidth(content, contentWidth);
256
- return leftMargin + padRight(truncated, contentWidth);
254
+ return padRightVisible(truncated, contentWidth);
257
255
  };
258
256
  const blank = () => row("");
259
257
  const hr = () => row(th.fg("dim", "─".repeat(contentWidth)));
@@ -262,9 +260,15 @@ export class GSDNotificationOverlay {
262
260
  const title = th.fg("accent", th.bold("Notifications"));
263
261
  const filterLabel = this.filter === "all"
264
262
  ? th.fg("dim", "all")
265
- : th.fg(this.filter === "error" ? "error" : this.filter === "warning" ? "warning" : "dim", this.filter);
263
+ : th.fg(
264
+ this.filter === "error" ? "error"
265
+ : this.filter === "warning" ? "warning"
266
+ : this.filter === "success" ? "success"
267
+ : "dim",
268
+ this.filter,
269
+ );
266
270
  const count = `${this.filteredEntries.length} entries`;
267
- lines.push(row(joinColumns(
271
+ lines.push(row(rightAlign(
268
272
  `${title} ${th.fg("dim", "filter:")} ${filterLabel}`,
269
273
  th.fg("dim", count),
270
274
  contentWidth,
@@ -273,7 +277,7 @@ export class GSDNotificationOverlay {
273
277
 
274
278
  // Controls
275
279
  const closeShortcut = formattedShortcutPair("notifications");
276
- lines.push(row(th.fg("dim", `↑/↓ scroll f filter c clear Esc close (${closeShortcut})`)));
280
+ lines.push(row(renderKeyHints(th, ["↑/↓ scroll", "f filter", "c clear", `Esc/${closeShortcut} close`], contentWidth)));
277
281
  lines.push(blank());
278
282
 
279
283
  // Entries
@@ -302,7 +306,7 @@ export class GSDNotificationOverlay {
302
306
  const msgMaxWidth = Math.max(10, contentWidth - prefixWidth);
303
307
 
304
308
  // Wrap long messages onto continuation lines indented to align with message start
305
- const msgLines = wrapText(entry.message, msgMaxWidth);
309
+ const msgLines = wrapVisibleText(entry.message, msgMaxWidth);
306
310
  const indent = " ".repeat(prefixWidth);
307
311
  for (let i = 0; i < msgLines.length; i++) {
308
312
  if (i === 0) {