gsd-pi 2.81.0-dev.72a81bdf3 → 2.82.0-dev.20138ae42

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 (463) hide show
  1. package/README.md +50 -31
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +10 -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/claude-code-cli/partial-builder.js +2 -1
  7. package/dist/resources/extensions/cmux/index.js +5 -0
  8. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  9. package/dist/resources/extensions/gsd/auto/loop.js +5 -5
  10. package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
  11. package/dist/resources/extensions/gsd/auto/phases.js +30 -1
  12. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  13. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  14. package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
  15. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +233 -127
  17. package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
  18. package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
  19. package/dist/resources/extensions/gsd/auto-start.js +85 -12
  20. package/dist/resources/extensions/gsd/auto-verification.js +28 -22
  21. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  22. package/dist/resources/extensions/gsd/auto.js +158 -55
  23. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +25 -6
  24. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -2
  26. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  27. package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
  28. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
  29. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  30. package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
  31. package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -1
  32. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  33. package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
  34. package/dist/resources/extensions/gsd/context-store.js +112 -0
  35. package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
  36. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  37. package/dist/resources/extensions/gsd/db-writer.js +150 -84
  38. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  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/doctor-runtime-checks.js +28 -11
  42. package/dist/resources/extensions/gsd/doctor.js +2 -28
  43. package/dist/resources/extensions/gsd/export-html.js +27 -425
  44. package/dist/resources/extensions/gsd/git-service.js +39 -1
  45. package/dist/resources/extensions/gsd/gsd-db.js +1 -0
  46. package/dist/resources/extensions/gsd/guided-flow.js +93 -111
  47. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  48. package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
  49. package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
  50. package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
  51. package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
  52. package/dist/resources/extensions/gsd/markdown-renderer.js +6 -1
  53. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  54. package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
  55. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
  56. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  57. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  58. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  59. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  60. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  61. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  62. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  63. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  64. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  65. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  66. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  67. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  68. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  71. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  73. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  74. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  75. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  76. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  77. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  79. package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
  80. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  81. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  82. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  83. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  84. package/dist/resources/extensions/gsd/status-guards.js +4 -0
  85. package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
  86. package/dist/resources/extensions/gsd/templates/plan.md +8 -5
  87. package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
  88. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  89. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  90. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  91. package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
  92. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  93. package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
  94. package/dist/resources/extensions/gsd/validation.js +23 -1
  95. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  96. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  97. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  98. package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
  99. package/dist/resources/extensions/shared/html-shell.js +388 -0
  100. package/dist/resources/extensions/subagent/index.js +448 -78
  101. package/dist/resources/extensions/subagent/launch.js +77 -0
  102. package/dist/resources/extensions/subagent/run-store.js +148 -0
  103. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  104. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  105. package/dist/resources/extensions/visual-brief/index.js +5 -0
  106. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  107. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  108. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  109. package/dist/web/standalone/.next/BUILD_ID +1 -1
  110. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  111. package/dist/web/standalone/.next/build-manifest.json +3 -3
  112. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  113. package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
  114. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  124. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  134. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/index.html +1 -1
  136. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  137. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  139. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  141. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  142. package/dist/web/standalone/.next/server/app/page.js +2 -2
  143. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  146. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  147. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  151. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  152. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  153. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  154. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  155. package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
  156. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  157. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
  158. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  159. package/package.json +6 -5
  160. package/packages/contracts/dist/rpc.test.js +7 -0
  161. package/packages/contracts/dist/rpc.test.js.map +1 -1
  162. package/packages/contracts/dist/workflow.d.ts +21 -0
  163. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  164. package/packages/contracts/dist/workflow.js +24 -0
  165. package/packages/contracts/dist/workflow.js.map +1 -1
  166. package/packages/contracts/src/rpc.test.ts +8 -0
  167. package/packages/contracts/src/workflow.ts +24 -0
  168. package/packages/daemon/package.json +2 -2
  169. package/packages/mcp-server/README.md +14 -3
  170. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  171. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  172. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  173. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  174. package/packages/mcp-server/package.json +2 -2
  175. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  176. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  177. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  178. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  179. package/packages/native/package.json +1 -1
  180. package/packages/native/tsconfig.json +2 -1
  181. package/packages/native/tsconfig.tsbuildinfo +1 -1
  182. package/packages/pi-agent-core/package.json +1 -1
  183. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  184. package/packages/pi-ai/dist/index.d.ts +2 -2
  185. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  186. package/packages/pi-ai/dist/index.js +1 -1
  187. package/packages/pi-ai/dist/index.js.map +1 -1
  188. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  189. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  190. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  191. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  192. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  193. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  194. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  195. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  196. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  197. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  198. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  199. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  200. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  201. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  202. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  203. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  204. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  205. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  206. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  207. package/packages/pi-ai/package.json +1 -1
  208. package/packages/pi-ai/src/index.ts +7 -2
  209. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  210. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  211. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  212. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  213. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  214. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  215. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  216. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  217. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  218. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  219. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  220. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  222. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  224. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  225. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  226. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  227. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  228. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  229. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  230. package/packages/pi-coding-agent/package.json +1 -1
  231. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  232. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  233. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  234. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  235. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  236. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  237. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  238. package/packages/pi-tui/dist/tui.js +5 -0
  239. package/packages/pi-tui/dist/tui.js.map +1 -1
  240. package/packages/pi-tui/package.json +1 -1
  241. package/packages/pi-tui/src/tui.ts +6 -0
  242. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  243. package/packages/rpc-client/package.json +1 -1
  244. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  245. package/pkg/package.json +1 -1
  246. package/src/resources/GSD-WORKFLOW.md +10 -1
  247. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  248. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  249. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  250. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  251. package/src/resources/extensions/cmux/index.ts +6 -0
  252. package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
  253. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  254. package/src/resources/extensions/gsd/auto/loop.ts +8 -5
  255. package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
  256. package/src/resources/extensions/gsd/auto/phases.ts +36 -1
  257. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  258. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  259. package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
  260. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  261. package/src/resources/extensions/gsd/auto-post-unit.ts +266 -139
  262. package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
  263. package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
  264. package/src/resources/extensions/gsd/auto-start.ts +92 -9
  265. package/src/resources/extensions/gsd/auto-verification.ts +36 -34
  266. package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
  267. package/src/resources/extensions/gsd/auto.ts +167 -53
  268. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +33 -6
  269. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
  270. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -2
  271. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  272. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  273. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
  274. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  275. package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
  276. package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -1
  277. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  278. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  279. package/src/resources/extensions/gsd/context-store.ts +120 -1
  280. package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
  281. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  282. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  283. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  284. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  285. package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
  286. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  287. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  288. package/src/resources/extensions/gsd/doctor.ts +2 -27
  289. package/src/resources/extensions/gsd/export-html.ts +27 -427
  290. package/src/resources/extensions/gsd/git-service.ts +45 -1
  291. package/src/resources/extensions/gsd/gsd-db.ts +3 -0
  292. package/src/resources/extensions/gsd/guided-flow.ts +126 -128
  293. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  294. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  295. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  296. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  297. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  298. package/src/resources/extensions/gsd/markdown-renderer.ts +6 -1
  299. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  300. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  301. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  302. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  303. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  304. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  305. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  306. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  307. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  308. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  309. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  310. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  311. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  312. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  313. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  314. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  315. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  316. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  317. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  318. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  319. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  320. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  321. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  322. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  323. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  324. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  325. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  326. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  327. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  328. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  329. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  330. package/src/resources/extensions/gsd/status-guards.ts +5 -0
  331. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  332. package/src/resources/extensions/gsd/templates/plan.md +8 -5
  333. package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
  334. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  335. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  336. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +129 -0
  337. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
  338. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +12 -11
  339. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  340. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
  341. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
  342. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
  343. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  344. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  345. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  346. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  347. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  348. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
  349. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  350. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  351. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  352. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  353. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  354. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
  355. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  356. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  357. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  358. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  359. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  360. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
  361. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  362. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  363. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  364. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  365. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  366. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  367. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  368. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  369. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  370. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  371. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  372. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  373. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  374. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  375. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  376. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  377. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +103 -1
  378. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  379. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  380. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  381. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  382. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  383. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  384. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  385. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  386. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  387. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  388. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  389. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  390. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  391. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  392. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  393. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  394. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  395. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  396. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  397. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
  398. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  399. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  400. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  401. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  402. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  403. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
  404. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  405. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +20 -1
  406. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  407. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
  408. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  409. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  410. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  411. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
  412. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  413. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  414. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  415. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  416. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
  417. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  418. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  419. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -1
  420. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  421. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  422. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  423. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  424. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
  425. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
  426. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  427. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  428. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  429. package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
  430. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  431. package/src/resources/extensions/gsd/types.ts +1 -1
  432. package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
  433. package/src/resources/extensions/gsd/validation.ts +23 -1
  434. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  435. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  436. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  437. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  438. package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
  439. package/src/resources/extensions/shared/html-shell.ts +412 -0
  440. package/src/resources/extensions/subagent/index.ts +567 -103
  441. package/src/resources/extensions/subagent/launch.ts +131 -0
  442. package/src/resources/extensions/subagent/run-store.ts +218 -0
  443. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  444. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  445. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  446. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  447. package/src/resources/extensions/visual-brief/index.ts +8 -0
  448. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  449. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  450. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  451. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  452. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  453. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  454. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  455. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  456. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  457. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  458. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  459. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  460. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  461. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  462. /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_buildManifest.js +0 -0
  463. /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_ssgManifest.js +0 -0
@@ -10,6 +10,7 @@ import { resolveAllSkillReferences, renderPreferencesForSystemPrompt, loadEffect
10
10
  import { resolveModelWithFallbacksForUnit } from "../preferences-models.js";
11
11
  import { resolveSkillReference } from "../preferences-skills.js";
12
12
  import { resolveGsdRootFile, resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveTaskFiles, resolveTasksDir, relSliceFile, relSlicePath, relTaskFile } from "../paths.js";
13
+ import { extractIntroAndRules } from "../knowledge-parser.js";
13
14
  import { ensureCodebaseMapFresh, readCodebaseMap } from "../codebase-generator.js";
14
15
  import { hasSkillSnapshot, detectNewSkills, formatSkillsXml } from "../skill-discovery.js";
15
16
  import { getActiveAutoWorktreeContext } from "../auto-worktree.js";
@@ -116,19 +117,19 @@ export async function buildBeforeAgentStartResult(event, ctx) {
116
117
  catch (e) {
117
118
  logWarning("bootstrap", `cmux prompt setup skipped: ${e.message}`);
118
119
  }
120
+ const ctxProjectRoot = ctx.projectRoot;
121
+ const basePath = typeof ctxProjectRoot === "string" && ctxProjectRoot.length > 0
122
+ ? ctxProjectRoot
123
+ : process.cwd();
119
124
  let preferenceBlock = "";
120
125
  if (loadedPreferences) {
121
- const cwd = process.cwd();
126
+ const cwd = basePath;
122
127
  const report = resolveAllSkillReferences(loadedPreferences.preferences, cwd);
123
128
  preferenceBlock = `\n\n${renderPreferencesForSystemPrompt(loadedPreferences.preferences, report.resolutions)}`;
124
129
  if (report.warnings.length > 0) {
125
130
  ctx.ui.notify(`GSD skill preferences: ${report.warnings.length} unresolved skill${report.warnings.length === 1 ? "" : "s"}: ${report.warnings.join(", ")}`, "warning");
126
131
  }
127
132
  }
128
- const { block: knowledgeBlock, globalSizeKb } = loadKnowledgeBlock(gsdHome(), process.cwd());
129
- if (globalSizeKb > 4) {
130
- ctx.ui.notify(`GSD: ~/.gsd/agent/KNOWLEDGE.md is ${globalSizeKb.toFixed(1)}KB — consider trimming to keep system prompt lean.`, "warning");
131
- }
132
133
  // ADR-013 step 5: opportunistic decisions->memories backfill. Idempotent
133
134
  // and best-effort — first run absorbs the existing decisions table into
134
135
  // the memory store; subsequent runs are a single sentinel SELECT.
@@ -136,12 +137,47 @@ export async function buildBeforeAgentStartResult(event, ctx) {
136
137
  const { backfillDecisionsToMemories } = await import("../memory-backfill.js");
137
138
  const written = backfillDecisionsToMemories();
138
139
  if (written > 0) {
139
- ctx.ui.notify(`GSD: backfilled ${written} decision${written === 1 ? "" : "s"} into the memory store (ADR-013).`, "info");
140
+ ctx.ui.notify(`GSD: backfilled ${written} decision${written === 1 ? "" : "s"} into the memory store.`, "info");
140
141
  }
141
142
  }
142
143
  catch (e) {
143
144
  logWarning("bootstrap", `decisions backfill failed: ${e.message}`);
144
145
  }
146
+ // ADR-013 Stage 2b: KNOWLEDGE.md Patterns + Lessons backfill, then
147
+ // re-render the hybrid projection (manual Rules + projected Patterns +
148
+ // projected Lessons). Both are idempotent and best-effort — failures here
149
+ // can't block agent startup.
150
+ try {
151
+ const { backfillKnowledgeToMemories } = await import("../knowledge-backfill.js");
152
+ const writtenK = backfillKnowledgeToMemories(basePath);
153
+ if (writtenK > 0) {
154
+ ctx.ui.notify(`GSD: backfilled ${writtenK} KNOWLEDGE.md row${writtenK === 1 ? "" : "s"} into the memory store.`, "info");
155
+ }
156
+ }
157
+ catch (e) {
158
+ logWarning("bootstrap", `KNOWLEDGE.md backfill failed: ${e.message}`);
159
+ }
160
+ try {
161
+ const { renderKnowledgeProjection } = await import("../knowledge-projection.js");
162
+ renderKnowledgeProjection(basePath);
163
+ }
164
+ catch (e) {
165
+ logWarning("bootstrap", `KNOWLEDGE.md projection render failed: ${e.message}`);
166
+ }
167
+ // ADR-013 step 6 preflight: warn when decisions / KNOWLEDGE.md rows are not
168
+ // yet in the memories table. Read-only; never throws. Runs after the two
169
+ // backfills above so the gap report reflects post-backfill state.
170
+ try {
171
+ const { reportConsolidationGaps } = await import("../memory-consolidation-scanner.js");
172
+ reportConsolidationGaps(basePath);
173
+ }
174
+ catch (e) {
175
+ logWarning("bootstrap", `memory consolidation scan failed: ${e.message}`);
176
+ }
177
+ const { block: knowledgeBlock, globalSizeKb } = loadKnowledgeBlock(gsdHome(), basePath);
178
+ if (globalSizeKb > 4) {
179
+ ctx.ui.notify(`GSD: ~/.gsd/agent/KNOWLEDGE.md is ${globalSizeKb.toFixed(1)}KB — consider trimming to keep system prompt lean.`, "warning");
180
+ }
145
181
  let newSkillsBlock = "";
146
182
  if (hasSkillSnapshot()) {
147
183
  const newSkills = detectNewSkills();
@@ -320,7 +356,9 @@ export async function loadMemoryBlock(userPrompt, opts = {}) {
320
356
  }
321
357
  }
322
358
  export function loadKnowledgeBlock(gsdHomeDir, cwd) {
323
- // 1. Global knowledge (~/.gsd/agent/KNOWLEDGE.md) — cross-project, user-maintained
359
+ // 1. Global knowledge (~/.gsd/agent/KNOWLEDGE.md) — cross-project,
360
+ // user-maintained. NOT migrated to memories (which are project-scoped),
361
+ // so the full file is injected unchanged.
324
362
  let globalKnowledge = "";
325
363
  let globalSizeKb = 0;
326
364
  const globalKnowledgePath = join(gsdHomeDir, "agent", "KNOWLEDGE.md");
@@ -336,14 +374,19 @@ export function loadKnowledgeBlock(gsdHomeDir, cwd) {
336
374
  logWarning("bootstrap", `global knowledge file read failed: ${e.message}`);
337
375
  }
338
376
  }
339
- // 2. Project knowledge (.gsd/KNOWLEDGE.md) — project-specific
377
+ // 2. Project knowledge (.gsd/KNOWLEDGE.md) — project-specific.
378
+ // ADR-013 Stage 2b: Patterns and Lessons are projected from the
379
+ // memories table and already reach the LLM via loadMemoryBlock. Inject
380
+ // only the intro prose + `## Rules` section here to avoid duplicating
381
+ // Patterns/Lessons content in the prompt. Rules stay manual per
382
+ // ADR-013 line 39 and have no memory equivalent.
340
383
  let projectKnowledge = "";
341
384
  const knowledgePath = resolveGsdRootFile(cwd, "KNOWLEDGE");
342
385
  if (existsSync(knowledgePath)) {
343
386
  try {
344
- const content = readFileSync(knowledgePath, "utf-8").trim();
345
- if (content)
346
- projectKnowledge = content;
387
+ const raw = readFileSync(knowledgePath, "utf-8").trim();
388
+ if (raw)
389
+ projectKnowledge = extractIntroAndRules(raw).trim();
347
390
  }
348
391
  catch (e) {
349
392
  logWarning("bootstrap", `project knowledge file read failed: ${e.message}`);
@@ -361,7 +404,7 @@ export function loadKnowledgeBlock(gsdHomeDir, cwd) {
361
404
  }
362
405
  const body = limitKnowledgeBlock(parts.join("\n\n"), getKnowledgeCharLimit());
363
406
  return {
364
- block: `\n\n[KNOWLEDGE — Rules, patterns, and lessons learned]\n\n${body}`,
407
+ block: `\n\n[KNOWLEDGE — Rules from KNOWLEDGE.md (Patterns and Lessons reach the LLM via the memory block)]\n\n${body}`,
365
408
  globalSizeKb,
366
409
  };
367
410
  }
@@ -3,6 +3,7 @@ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readlinkS
3
3
  import { isAbsolute, join, relative, resolve, sep } from "node:path";
4
4
  import { minimatch } from "minimatch";
5
5
  import { getIsolationMode } from "../preferences.js";
6
+ import { compileSubagentPermissionContract } from "../unit-context-manifest.js";
6
7
  import { logWarning } from "../workflow-logger.js";
7
8
  import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "../worktree-root.js";
8
9
  /**
@@ -58,6 +59,7 @@ const QUEUE_SAFE_TOOLS = new Set([
58
59
  * true / false — shell no-ops / test exit codes
59
60
  */
60
61
  const BASH_READ_ONLY_RE = /^\s*(cat|head|tail|less|more|wc|file|stat|du|df|which|type|echo|printf|ls|find|grep|rg|awk|sed\b(?!.*-i)|sort|uniq|diff|comm|tr|cut|tee\s+-a\s+\/dev\/null|git\s+(log|show|diff|status|branch|tag|remote|rev-parse|ls-files|blame|shortlog|describe|stash\s+list|config\s+--get|cat-file)|gh\s+(issue|pr|api|repo|release)\s+(view|list|diff|status|checks)|mkdir\s+-p\s+\.gsd|rtk\s|npm\s+run\s+(test|test:\w+|lint|lint:\w+|typecheck|type-check|type-check:\w+|check|verify|audit|outdated|format:check|ci|validate)\b|npm\s+(ls|list|info|view|show|outdated|audit|explain|doctor|ping|--version|-v)\b|npx\s|tsx\s|node\s+(--print|--version|-v\b)|python[23]?\s+(-c\s+'[^']*'|--version|-V\b|-m\s+(pip\s+show|pip\s+list|site))|pip[23]?\s+(show|list|freeze|check|index\s+versions)\b|jq\s|yq\s|curl\s+(-s\b|--silent\b)(?!\s+[^|>]*\s-[oO]\b)(?!\s+[^|>]*\s--output\b)[^|>]*$|openssl\s+(version|x509|s_client)|env\b|printenv\b|true\b|false\b)/;
62
+ const BASH_VERIFICATION_RE = /^\s*(npm\s+(run\s+(build|test|test:\w+|lint|lint:\w+|typecheck|type-check|verify|ci|validate)\b|test\b)|pnpm\s+(build|test|lint|typecheck|verify)\b|yarn\s+(build|test|lint|typecheck|verify)\b|vitest\b|jest\b|go\s+test\b)/;
61
63
  function createEmptyWriteGateState() {
62
64
  return {
63
65
  verifiedDepthMilestones: new Set(),
@@ -642,6 +644,9 @@ function blockReason(unitType, mode, what) {
642
644
  * and listed in the policy's allowedSubagents.
643
645
  * - "docs" → like "planning" but also allows writes to paths
644
646
  * matching `allowedPathGlobs` relative to basePath.
647
+ * - "verification"
648
+ * → allows Bash for project verification commands, but keeps
649
+ * writes restricted to .gsd/ and blocks subagent dispatch.
645
650
  *
646
651
  * `pathOrCommand` is the file path for write/edit-shaped tools and the
647
652
  * shell command for bash. Other tools ignore this argument.
@@ -673,7 +678,7 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
673
678
  // Unknown tool in read-only mode — block by default.
674
679
  return { block: true, reason: blockReason(unitType, policy.mode, `tool "${tool}" is not on the read-only allowlist`) };
675
680
  }
676
- // planning / planning-dispatch / docs modes share the same surface for safe tools, bash, and subagent.
681
+ // planning / planning-dispatch / docs / verification modes share the same surface for safe tools, bash, and subagent.
677
682
  if (PLANNING_SAFE_TOOLS.has(tool))
678
683
  return { block: false };
679
684
  if (tool.startsWith("gsd_"))
@@ -681,7 +686,8 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
681
686
  if (PLANNING_SUBAGENT_TOOLS.has(tool)) {
682
687
  if (policy.mode === "planning-dispatch") {
683
688
  const requested = (agentClasses ?? []).map(a => a.trim()).filter(Boolean);
684
- const allowedSubagents = Array.isArray(policy.allowedSubagents) ? policy.allowedSubagents : [];
689
+ const dispatchContract = compileSubagentPermissionContract(policy);
690
+ const allowedSubagents = dispatchContract.allowedSubagents;
685
691
  const allowed = new Set(allowedSubagents);
686
692
  // When agentClasses is undefined, the caller has not been updated to extract
687
693
  // agent identities yet. Block and warn so stale callers surface in telemetry
@@ -718,6 +724,14 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
718
724
  return { block: true, reason: blockReason(unitType, policy.mode, `subagent dispatch is not permitted in planning units`) };
719
725
  }
720
726
  if (tool === "bash") {
727
+ if (policy.mode === "verification") {
728
+ if (BASH_VERIFICATION_RE.test(pathOrCommand) || BASH_READ_ONLY_RE.test(pathOrCommand))
729
+ return { block: false };
730
+ return {
731
+ block: true,
732
+ reason: blockReason(unitType, policy.mode, `bash is restricted to build/test verification commands (npm run build, npm test, etc.); cannot run "${pathOrCommand.slice(0, 80)}${pathOrCommand.length > 80 ? "…" : ""}"`),
733
+ };
734
+ }
721
735
  if (BASH_READ_ONLY_RE.test(pathOrCommand))
722
736
  return { block: false };
723
737
  return {
@@ -8,14 +8,153 @@
8
8
  *
9
9
  * Design constraints (from Trek-e approval):
10
10
  * - Warn the user before stashing (no silent surprises)
11
- * - git stash push / git stash pop only no custom stash management layer
12
- * - Stash/pop errors are logged but MUST NOT block the merge itself
11
+ * - git stash push / git stash apply+drop for targeted restore
12
+ * - Stash/apply errors are logged but MUST NOT block the merge itself
13
13
  * - Fast-path status check — clean trees pay no extra cost
14
14
  */
15
15
  import { execFileSync } from "node:child_process";
16
+ import { existsSync, readFileSync } from "node:fs";
17
+ import { join } from "node:path";
16
18
  import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
17
19
  import { logWarning } from "./workflow-logger.js";
18
20
  import { nativeHasChanges } from "./native-git-bridge.js";
21
+ function gitText(basePath, args) {
22
+ return execFileSync("git", args, {
23
+ cwd: basePath,
24
+ stdio: ["ignore", "pipe", "pipe"],
25
+ encoding: "utf-8",
26
+ env: GIT_NO_PROMPT_ENV,
27
+ });
28
+ }
29
+ function gitBuffer(basePath, args) {
30
+ return execFileSync("git", args, {
31
+ cwd: basePath,
32
+ stdio: ["ignore", "pipe", "pipe"],
33
+ env: GIT_NO_PROMPT_ENV,
34
+ });
35
+ }
36
+ function errorText(err) {
37
+ if (!err || typeof err !== "object")
38
+ return String(err);
39
+ const parts = [];
40
+ const stderr = err.stderr;
41
+ const stdout = err.stdout;
42
+ for (const value of [stderr, stdout]) {
43
+ if (typeof value === "string")
44
+ parts.push(value);
45
+ else if (value instanceof Uint8Array)
46
+ parts.push(Buffer.from(value).toString("utf-8"));
47
+ }
48
+ parts.push(err instanceof Error ? err.message : String(err));
49
+ return parts.filter(Boolean).join("\n");
50
+ }
51
+ function parseAlreadyExistsNoCheckoutPaths(text) {
52
+ const paths = [];
53
+ for (const line of text.split(/\r?\n/)) {
54
+ const match = /^(.+?) already exists, no checkout$/i.exec(line.trim());
55
+ if (match?.[1])
56
+ paths.push(match[1]);
57
+ }
58
+ return [...new Set(paths)];
59
+ }
60
+ function readZeroDelimitedPaths(output) {
61
+ return output.split("\0").filter(Boolean);
62
+ }
63
+ function listStashUntrackedPaths(basePath, stashRef) {
64
+ try {
65
+ const output = gitText(basePath, ["ls-tree", "-r", "-z", "--name-only", `${stashRef}^3`]);
66
+ return readZeroDelimitedPaths(output);
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ function listStashTrackedPaths(basePath, stashRef) {
73
+ try {
74
+ const output = gitText(basePath, ["diff", "--name-only", "-z", `${stashRef}^1`, stashRef]);
75
+ return readZeroDelimitedPaths(output);
76
+ }
77
+ catch {
78
+ return null;
79
+ }
80
+ }
81
+ function isWorktreeClean(basePath) {
82
+ try {
83
+ return gitText(basePath, ["status", "--porcelain"]).trim() === "";
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ }
89
+ function stashBlobEqualsWorktreeFile(basePath, stashRef, path) {
90
+ try {
91
+ const worktreePath = join(basePath, path);
92
+ if (!existsSync(worktreePath))
93
+ return false;
94
+ const worktreeContent = readFileSync(worktreePath);
95
+ const stashContent = gitBuffer(basePath, ["show", `${stashRef}^3:${path}`]);
96
+ return Buffer.compare(worktreeContent, stashContent) === 0;
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ }
102
+ function reconcileAlreadyPresentUntrackedStash(basePath, milestoneId, stashRef, err) {
103
+ const text = errorText(err);
104
+ const collidedPaths = parseAlreadyExistsNoCheckoutPaths(text);
105
+ if (collidedPaths.length === 0)
106
+ return null;
107
+ const untrackedPaths = listStashUntrackedPaths(basePath, stashRef);
108
+ if (!untrackedPaths || untrackedPaths.length === 0)
109
+ return null;
110
+ const trackedPaths = listStashTrackedPaths(basePath, stashRef);
111
+ if (trackedPaths === null || trackedPaths.length > 0)
112
+ return null;
113
+ const untrackedPathSet = new Set(untrackedPaths);
114
+ if (!collidedPaths.every((path) => untrackedPathSet.has(path)))
115
+ return null;
116
+ if (!untrackedPaths.every((path) => existsSync(join(basePath, path))))
117
+ return null;
118
+ if (isWorktreeClean(basePath) !== true)
119
+ return null;
120
+ const blobComparisons = untrackedPaths.map((path) => stashBlobEqualsWorktreeFile(basePath, stashRef, path));
121
+ if (blobComparisons.some((result) => result === null))
122
+ return null;
123
+ const allIdentical = blobComparisons.every(Boolean);
124
+ if (allIdentical) {
125
+ let dropped = true;
126
+ try {
127
+ execFileSync("git", ["stash", "drop", stashRef], {
128
+ cwd: basePath,
129
+ stdio: ["ignore", "pipe", "pipe"],
130
+ encoding: "utf-8",
131
+ env: GIT_NO_PROMPT_ENV,
132
+ });
133
+ }
134
+ catch (err) {
135
+ dropped = false;
136
+ logWarning("preflight", `git stash drop ${stashRef} failed after identical preflight stash reconciliation: ${err instanceof Error ? err.message : String(err)}`);
137
+ }
138
+ return {
139
+ restored: true,
140
+ needsManualRecovery: false,
141
+ message: dropped
142
+ ? `Preflight stash for milestone ${milestoneId} contained files already present after merge; identical stash dropped.`
143
+ : `Preflight stash for milestone ${milestoneId} contained files already present after merge, but ${stashRef} could not be dropped and remains as a backup.`,
144
+ stashRef,
145
+ resolution: dropped ? "already-present-dropped" : "already-present-preserved",
146
+ collidedPaths,
147
+ };
148
+ }
149
+ return {
150
+ restored: false,
151
+ needsManualRecovery: false,
152
+ message: `Preflight stash for milestone ${milestoneId} contained untracked files already present after merge. Keeping merged files and preserving ${stashRef} as a backup.`,
153
+ stashRef,
154
+ resolution: "already-present-preserved",
155
+ collidedPaths,
156
+ };
157
+ }
19
158
  function findPreflightStashRef(basePath, milestoneId, stashMarker) {
20
159
  const markerPrefix = `gsd-preflight-stash:${milestoneId}:`;
21
160
  let fallbackRef = null;
@@ -115,28 +254,50 @@ export function postflightPopStash(basePath, milestoneId, stashMarker, notify) {
115
254
  message: msg,
116
255
  };
117
256
  }
118
- execFileSync("git", ["stash", "pop", stashRef], {
257
+ execFileSync("git", ["stash", "apply", stashRef], {
119
258
  cwd: basePath,
120
259
  stdio: ["ignore", "pipe", "pipe"],
121
260
  encoding: "utf-8",
122
261
  env: GIT_NO_PROMPT_ENV,
123
262
  });
263
+ let dropWarning = null;
264
+ try {
265
+ execFileSync("git", ["stash", "drop", stashRef], {
266
+ cwd: basePath,
267
+ stdio: ["ignore", "pipe", "pipe"],
268
+ encoding: "utf-8",
269
+ env: GIT_NO_PROMPT_ENV,
270
+ });
271
+ }
272
+ catch (err) {
273
+ dropWarning = ` Stash was restored, but git stash drop ${stashRef} failed: ${err instanceof Error ? err.message : String(err)}.`;
274
+ logWarning("preflight", dropWarning.trim());
275
+ }
124
276
  const msg = `Restored stashed changes after milestone ${milestoneId} merge.`;
125
- notify(msg, "info");
277
+ notify(`${msg}${dropWarning ?? ""}`, dropWarning ? "warning" : "info");
126
278
  return {
127
279
  restored: true,
128
280
  needsManualRecovery: false,
129
- message: msg,
281
+ message: `${msg}${dropWarning ?? ""}`,
130
282
  stashRef,
283
+ resolution: "applied",
131
284
  };
132
285
  }
133
286
  catch (err) {
134
- // Pop conflicts mean the merged code collides with the stashed changes.
287
+ if (stashRef) {
288
+ const reconciled = reconcileAlreadyPresentUntrackedStash(basePath, milestoneId, stashRef, err);
289
+ if (reconciled) {
290
+ logWarning("preflight", reconciled.message);
291
+ notify(reconciled.message, reconciled.resolution === "already-present-preserved" ? "warning" : "info");
292
+ return reconciled;
293
+ }
294
+ }
295
+ // Apply conflicts mean the merged code collides with the stashed changes.
135
296
  // Log a warning — the user needs to resolve manually, but the merge succeeded.
136
297
  const restoreHint = stashRef
137
- ? `Run "git stash pop ${stashRef}" or "git stash apply ${stashRef}" manually to restore the correct stash.`
298
+ ? `Run "git stash apply ${stashRef}" manually to restore the correct stash, then "git stash drop ${stashRef}" after recovery.`
138
299
  : `Run "git stash list" to find the matching GSD preflight stash before restoring manually.`;
139
- const msg = `git stash pop ${stashRef ?? ""}`.trim() + ` failed after merge of milestone ${milestoneId}: ${err instanceof Error ? err.message : String(err)}. ${restoreHint}`;
300
+ const msg = `git stash apply ${stashRef ?? ""}`.trim() + ` failed after merge of milestone ${milestoneId}: ${err instanceof Error ? err.message : String(err)}. ${restoreHint}`;
140
301
  logWarning("preflight", msg);
141
302
  notify(msg, "warning");
142
303
  return {
@@ -144,6 +305,7 @@ export function postflightPopStash(basePath, milestoneId, stashMarker, notify) {
144
305
  needsManualRecovery: true,
145
306
  message: msg,
146
307
  ...(stashRef ? { stashRef } : {}),
308
+ resolution: "manual-recovery",
147
309
  };
148
310
  }
149
311
  }
@@ -2,7 +2,8 @@ import { existsSync, readFileSync, readdirSync } from "node:fs";
2
2
  import { join, resolve } from "node:path";
3
3
  import { loadRegistry } from "../workflow-templates.js";
4
4
  import { gsdHome } from "../gsd-home.js";
5
- export const GSD_COMMAND_DESCRIPTION = "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|model|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|debug|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|new-project|parallel|cmux|park|unpark|init|setup|onboarding|inspect|extensions|update|fast|mcp|rethink|workflow|codebase|notifications|ship|do|session-report|backlog|pr-branch|add-tests|scan|language|worktree|eval-review";
5
+ import { VISUAL_BRIEF_MODES } from "../../visual-brief/prompts.js";
6
+ export const GSD_COMMAND_DESCRIPTION = "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|brief|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|model|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|debug|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|new-project|parallel|cmux|park|unpark|init|setup|onboarding|inspect|extensions|update|fast|mcp|rethink|workflow|codebase|notifications|ship|do|session-report|backlog|pr-branch|add-tests|scan|language|worktree|eval-review";
6
7
  export const TOP_LEVEL_SUBCOMMANDS = [
7
8
  { cmd: "help", desc: "Categorized command reference with descriptions" },
8
9
  { cmd: "next", desc: "Explicit step mode (same as /gsd)" },
@@ -12,6 +13,7 @@ export const TOP_LEVEL_SUBCOMMANDS = [
12
13
  { cmd: "status", desc: "Progress dashboard" },
13
14
  { cmd: "widget", desc: "Cycle widget: full → small → min → off" },
14
15
  { cmd: "visualize", desc: "Open 10-tab workflow visualizer (progress, timeline, deps, metrics, health, agent, changes, knowledge, captures, export)" },
16
+ { cmd: "brief", desc: "Generate a visual HTML brief: diagram, plan, diff review, recap, table, or slides" },
15
17
  { cmd: "queue", desc: "Queue and reorder future milestones" },
16
18
  { cmd: "quick", desc: "Execute a quick task without full planning overhead" },
17
19
  { cmd: "discuss", desc: "Discuss architecture and decisions" },
@@ -75,6 +77,7 @@ export const TOP_LEVEL_SUBCOMMANDS = [
75
77
  { cmd: "eval-review", desc: "Audit a slice's AI evaluation strategy and write a scored EVAL-REVIEW.md (--force, --show)" },
76
78
  ];
77
79
  const NESTED_COMPLETIONS = {
80
+ brief: VISUAL_BRIEF_MODES.map((mode) => ({ cmd: mode.mode, desc: mode.description })),
78
81
  auto: [
79
82
  { cmd: "--verbose", desc: "Show detailed execution output" },
80
83
  { cmd: "--debug", desc: "Enable debug logging" },
@@ -1,3 +1,4 @@
1
+ import { createRequire } from "node:module";
1
2
  import { computeProgressScore, formatProgressLine } from "../../progress-score.js";
2
3
  import { getGlobalGSDPreferencesPath, getProjectGSDPreferencesPath } from "../../preferences.js";
3
4
  import { ensurePreferencesFile, handlePrefs, handlePrefsMode, handlePrefsWizard, handleLanguage } from "../../commands-prefs-wizard.js";
@@ -7,6 +8,8 @@ import { handleCmux } from "../../commands-cmux.js";
7
8
  import { setSessionModelOverride } from "../../session-model-override.js";
8
9
  import { projectRoot } from "../context.js";
9
10
  import { formattedShortcutPair } from "../../shortcut-defs.js";
11
+ import { getVisualBriefOutputDir } from "../../../visual-brief/artifact-policy.js";
12
+ import { buildVisualBriefPrompt, parseVisualBriefArgs, VISUAL_BRIEF_USAGE } from "../../../visual-brief/prompts.js";
10
13
  export function showHelp(ctx, args = "") {
11
14
  const summaryLines = [
12
15
  "GSD — Get Shit Done\n",
@@ -22,6 +25,7 @@ export function showHelp(ctx, args = "") {
22
25
  ` /gsd parallel watch Parallel monitor (${formattedShortcutPair("parallel")})`,
23
26
  ` /gsd notifications Notification history (${formattedShortcutPair("notifications")})`,
24
27
  " /gsd visualize Interactive 10-tab TUI",
28
+ " /gsd brief <mode> Visual HTML brief (diagram, plan, diff, recap, table, slides)",
25
29
  " /gsd queue Show queued/dispatched units",
26
30
  "",
27
31
  "COURSE CORRECTION",
@@ -69,6 +73,7 @@ export function showHelp(ctx, args = "") {
69
73
  ` /gsd parallel watch Open parallel worker monitor (${formattedShortcutPair("parallel")})`,
70
74
  " /gsd widget Cycle status widget [full|small|min|off]",
71
75
  " /gsd visualize Interactive 10-tab TUI (progress, timeline, deps, metrics, health, agent, changes, knowledge, captures, export)",
76
+ " /gsd brief <mode> Generate a visual HTML brief [diagram|plan|diff|recap|table|slides] [topic] [--slides]",
72
77
  " /gsd queue Show queued/dispatched units and execution order",
73
78
  " /gsd history View execution history [--cost] [--phase] [--model] [N]",
74
79
  " /gsd changelog Show categorized release notes [version]",
@@ -90,7 +95,7 @@ export function showHelp(ctx, args = "") {
90
95
  " /gsd unpark [id] Reactivate a parked milestone",
91
96
  "",
92
97
  "PROJECT KNOWLEDGE",
93
- " /gsd knowledge <type> <text> Add rule, pattern, or lesson to KNOWLEDGE.md",
98
+ " /gsd knowledge <type> <text> Add a rule to KNOWLEDGE.md or capture a pattern/lesson to memories",
94
99
  " /gsd codebase [generate|update|stats] Manage the CODEBASE.md cache used in prompt context",
95
100
  "",
96
101
  "SHIPPING & BACKLOG",
@@ -182,6 +187,34 @@ export async function handleVisualize(ctx) {
182
187
  ctx.ui.notify("Visualizer requires an interactive terminal. Use /gsd status for a text-based overview.", "warning");
183
188
  }
184
189
  }
190
+ export async function handleBrief(args, ctx, pi) {
191
+ const request = parseVisualBriefArgs(args);
192
+ if (!request) {
193
+ ctx.ui.notify(VISUAL_BRIEF_USAGE, "info");
194
+ return;
195
+ }
196
+ if (!pi?.sendUserMessage) {
197
+ ctx.ui.notify("Visual brief generation is unavailable in this context.", "warning");
198
+ return;
199
+ }
200
+ const outputDir = getVisualBriefOutputDir();
201
+ const version = resolveGsdVersion();
202
+ pi.sendUserMessage(buildVisualBriefPrompt(request, { outputDir, version }));
203
+ }
204
+ const briefRequire = createRequire(import.meta.url);
205
+ function resolveGsdVersion() {
206
+ const envVersion = process.env.GSD_VERSION?.trim();
207
+ if (envVersion)
208
+ return envVersion;
209
+ try {
210
+ const pkg = briefRequire("../../../../../../package.json");
211
+ const fromPkg = typeof pkg.version === "string" ? pkg.version.trim() : "";
212
+ return fromPkg || undefined;
213
+ }
214
+ catch {
215
+ return undefined;
216
+ }
217
+ }
185
218
  export async function handleSetup(args, ctx, pi) {
186
219
  const { detectProjectState, hasGlobalSetup } = await import("../../detection.js");
187
220
  const { isOnboardingComplete, readOnboardingRecord } = await import("../../onboarding-state.js");
@@ -370,6 +403,10 @@ export async function handleCoreCommand(trimmed, ctx, pi) {
370
403
  await handleVisualize(ctx);
371
404
  return true;
372
405
  }
406
+ if (trimmed === "brief" || trimmed.startsWith("brief ")) {
407
+ await handleBrief(trimmed.replace(/^brief\s*/, "").trim(), ctx, pi);
408
+ return true;
409
+ }
373
410
  if (trimmed === "widget" || trimmed.startsWith("widget ")) {
374
411
  const { cycleWidgetMode, setWidgetMode, getWidgetMode } = await import("../../auto-dashboard.js");
375
412
  const arg = trimmed.replace(/^widget\s*/, "").trim();
@@ -1,4 +1,5 @@
1
1
  import { importExtensionModule } from "@gsd/pi-coding-agent";
2
+ import { VISUAL_BRIEF_MODES } from "../visual-brief/prompts.js";
2
3
  const TOP_LEVEL_SUBCOMMANDS = [
3
4
  { cmd: "help", desc: "Categorized command reference with descriptions" },
4
5
  { cmd: "next", desc: "Explicit step mode (same as /gsd)" },
@@ -7,6 +8,7 @@ const TOP_LEVEL_SUBCOMMANDS = [
7
8
  { cmd: "pause", desc: "Pause auto-mode (preserves state, /gsd auto to resume)" },
8
9
  { cmd: "status", desc: "Progress dashboard" },
9
10
  { cmd: "visualize", desc: "Open workflow visualizer" },
11
+ { cmd: "brief", desc: "Generate a visual HTML brief" },
10
12
  { cmd: "queue", desc: "Queue and reorder future milestones" },
11
13
  { cmd: "quick", desc: "Execute a quick task without full planning overhead" },
12
14
  { cmd: "discuss", desc: "Discuss architecture and decisions" },
@@ -75,6 +77,9 @@ function getGsdArgumentCompletions(prefix) {
75
77
  { cmd: "--dry-run", desc: "Preview next step without executing" },
76
78
  ], "next");
77
79
  }
80
+ if (parts[0] === "brief" && parts.length <= 2) {
81
+ return filterStartsWith(partial, VISUAL_BRIEF_MODES.map((mode) => ({ cmd: mode.mode, desc: mode.description })), "brief");
82
+ }
78
83
  if ((parts[0] === "new-project" || parts[0] === "new-milestone") && parts.length <= 2) {
79
84
  return filterStartsWith(partial, [
80
85
  { cmd: "--deep", desc: "Enable deep planning mode (staged project-level discovery)" },
@@ -303,8 +303,21 @@ export async function handleKnowledge(args, ctx) {
303
303
  const scope = state.activeMilestone?.id
304
304
  ? `${state.activeMilestone.id}${state.activeSlice ? `/${state.activeSlice.id}` : ""}`
305
305
  : "global";
306
- await appendKnowledge(basePath, type, entryText, scope);
307
- ctx.ui.notify(`Added ${type} to KNOWLEDGE.md: "${entryText}"`, "success");
306
+ // ADR-013 Stage 2c: Patterns and Lessons land in the memories table; the
307
+ // next session-start projection render emits them back into KNOWLEDGE.md.
308
+ // Rules stay file-canonical per ADR-013 line 39 — Rules are not migrated.
309
+ if (type === "rule") {
310
+ await appendKnowledge(basePath, type, entryText, scope);
311
+ ctx.ui.notify(`Added rule to KNOWLEDGE.md: "${entryText}"`, "success");
312
+ return;
313
+ }
314
+ const { captureKnowledgeEntry } = await import("./knowledge-capture.js");
315
+ const { id, written } = captureKnowledgeEntry(basePath, type, entryText, scope);
316
+ if (!written) {
317
+ ctx.ui.notify(`Could not persist ${type} — see logs for details.`, "error");
318
+ return;
319
+ }
320
+ ctx.ui.notify(`Captured ${type} ${id} to memories; KNOWLEDGE.md will render it on next session start.`, "success");
308
321
  }
309
322
  export async function handleRunHook(args, ctx, pi) {
310
323
  const parts = args.trim().split(/\s+/);