gsd-pi 2.82.0-dev.725028083 → 2.82.0-dev.98ea09b1e

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 (355) hide show
  1. package/README.md +4 -3
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +10 -1
  4. package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
  5. package/dist/resources/extensions/cmux/index.js +5 -0
  6. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  7. package/dist/resources/extensions/gsd/auto/loop.js +5 -5
  8. package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
  9. package/dist/resources/extensions/gsd/auto/phases.js +8 -1
  10. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  11. package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
  12. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +233 -127
  14. package/dist/resources/extensions/gsd/auto-prompts.js +2 -2
  15. package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
  16. package/dist/resources/extensions/gsd/auto-start.js +85 -12
  17. package/dist/resources/extensions/gsd/auto-verification.js +28 -22
  18. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  19. package/dist/resources/extensions/gsd/auto.js +158 -55
  20. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +4 -1
  21. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
  22. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  23. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
  24. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  25. package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
  26. package/dist/resources/extensions/gsd/commands/handlers/core.js +37 -0
  27. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  28. package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
  29. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  30. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  31. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  32. package/dist/resources/extensions/gsd/doctor.js +2 -28
  33. package/dist/resources/extensions/gsd/export-html.js +27 -425
  34. package/dist/resources/extensions/gsd/git-service.js +39 -1
  35. package/dist/resources/extensions/gsd/gsd-db.js +1 -0
  36. package/dist/resources/extensions/gsd/guided-flow.js +13 -6
  37. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  38. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  39. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  40. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  41. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  42. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  43. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  44. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  45. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  46. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  47. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  48. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  49. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  50. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  51. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  52. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  53. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  54. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  55. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  56. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  57. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  58. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  59. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  60. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  61. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  62. package/dist/resources/extensions/gsd/status-guards.js +4 -0
  63. package/dist/resources/extensions/gsd/templates/plan.md +8 -5
  64. package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
  65. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  66. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  67. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  68. package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
  69. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  70. package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
  71. package/dist/resources/extensions/gsd/validation.js +23 -1
  72. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  73. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  74. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  75. package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
  76. package/dist/resources/extensions/shared/html-shell.js +388 -0
  77. package/dist/resources/extensions/subagent/index.js +448 -78
  78. package/dist/resources/extensions/subagent/launch.js +77 -0
  79. package/dist/resources/extensions/subagent/run-store.js +148 -0
  80. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  81. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  82. package/dist/resources/extensions/visual-brief/index.js +5 -0
  83. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  84. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  85. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  86. package/dist/web/standalone/.next/BUILD_ID +1 -1
  87. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  88. package/dist/web/standalone/.next/build-manifest.json +3 -3
  89. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  90. package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
  91. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  101. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  111. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/index.html +1 -1
  113. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  114. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  116. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  118. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  119. package/dist/web/standalone/.next/server/app/page.js +2 -2
  120. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  121. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  123. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  124. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  128. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  129. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  130. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  131. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  132. package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
  133. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  134. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
  135. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  136. package/package.json +4 -4
  137. package/packages/contracts/dist/rpc.test.js +7 -0
  138. package/packages/contracts/dist/rpc.test.js.map +1 -1
  139. package/packages/contracts/dist/workflow.d.ts +21 -0
  140. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  141. package/packages/contracts/dist/workflow.js +24 -0
  142. package/packages/contracts/dist/workflow.js.map +1 -1
  143. package/packages/contracts/src/rpc.test.ts +8 -0
  144. package/packages/contracts/src/workflow.ts +24 -0
  145. package/packages/mcp-server/README.md +13 -4
  146. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  147. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  148. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  149. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  150. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  151. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  152. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  153. package/packages/native/tsconfig.json +2 -1
  154. package/packages/native/tsconfig.tsbuildinfo +1 -1
  155. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  156. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  157. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  158. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  159. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  160. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  161. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  162. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  163. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  164. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  165. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  166. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  167. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  168. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  169. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  170. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  171. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  172. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  173. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  174. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  175. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  176. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  177. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  178. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  179. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  180. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  181. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  182. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  183. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  184. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  185. package/packages/pi-tui/dist/tui.js +5 -0
  186. package/packages/pi-tui/dist/tui.js.map +1 -1
  187. package/packages/pi-tui/src/tui.ts +6 -0
  188. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  189. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  190. package/src/resources/GSD-WORKFLOW.md +10 -1
  191. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  192. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  193. package/src/resources/extensions/cmux/index.ts +6 -0
  194. package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
  195. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  196. package/src/resources/extensions/gsd/auto/loop.ts +8 -5
  197. package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
  198. package/src/resources/extensions/gsd/auto/phases.ts +7 -1
  199. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  200. package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
  201. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  202. package/src/resources/extensions/gsd/auto-post-unit.ts +266 -139
  203. package/src/resources/extensions/gsd/auto-prompts.ts +2 -2
  204. package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
  205. package/src/resources/extensions/gsd/auto-start.ts +92 -9
  206. package/src/resources/extensions/gsd/auto-verification.ts +36 -34
  207. package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
  208. package/src/resources/extensions/gsd/auto.ts +167 -53
  209. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +6 -1
  210. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
  211. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  212. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
  213. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  214. package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
  215. package/src/resources/extensions/gsd/commands/handlers/core.ts +40 -0
  216. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  217. package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
  218. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  219. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  220. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  221. package/src/resources/extensions/gsd/doctor.ts +2 -27
  222. package/src/resources/extensions/gsd/export-html.ts +27 -427
  223. package/src/resources/extensions/gsd/git-service.ts +45 -1
  224. package/src/resources/extensions/gsd/gsd-db.ts +3 -0
  225. package/src/resources/extensions/gsd/guided-flow.ts +14 -7
  226. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  227. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  228. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  229. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  230. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  231. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  232. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  233. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  234. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  235. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  236. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  237. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  238. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  239. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  240. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  241. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  242. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  243. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  244. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  245. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  246. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  247. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  248. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  249. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  250. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  251. package/src/resources/extensions/gsd/status-guards.ts +5 -0
  252. package/src/resources/extensions/gsd/templates/plan.md +8 -5
  253. package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
  254. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  255. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +54 -0
  256. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
  257. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +12 -11
  258. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
  259. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
  260. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
  261. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  262. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  263. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  264. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  265. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  266. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  267. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  268. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  269. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
  270. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  271. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  272. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
  273. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  274. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  275. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  276. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  277. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  278. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +6 -6
  279. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  280. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  281. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  282. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  283. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +103 -1
  284. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  285. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  286. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  287. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  288. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  289. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  290. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  291. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  292. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  293. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  294. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  295. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
  296. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  297. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  298. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  299. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  300. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  301. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  302. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
  303. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  304. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +31 -1
  305. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  306. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  307. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  308. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  309. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
  310. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  311. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  312. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -1
  313. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  314. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  315. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  316. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  317. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
  318. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
  319. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  320. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  321. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  322. package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
  323. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  324. package/src/resources/extensions/gsd/types.ts +1 -1
  325. package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
  326. package/src/resources/extensions/gsd/validation.ts +23 -1
  327. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  328. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  329. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  330. package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
  331. package/src/resources/extensions/shared/html-shell.ts +412 -0
  332. package/src/resources/extensions/subagent/index.ts +567 -103
  333. package/src/resources/extensions/subagent/launch.ts +131 -0
  334. package/src/resources/extensions/subagent/run-store.ts +218 -0
  335. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  336. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  337. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  338. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  339. package/src/resources/extensions/visual-brief/index.ts +8 -0
  340. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  341. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  342. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  343. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  344. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  345. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  346. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  347. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  348. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  349. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  350. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  351. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  352. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  353. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  354. /package/dist/web/standalone/.next/static/{KDRTXR-22LPCsa80X9dey → euQ0CLP_v8V4e76Tu3odJ}/_buildManifest.js +0 -0
  355. /package/dist/web/standalone/.next/static/{KDRTXR-22LPCsa80X9dey → euQ0CLP_v8V4e76Tu3odJ}/_ssgManifest.js +0 -0
@@ -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]",
@@ -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)" },
@@ -23,7 +23,8 @@
23
23
  import { emitJournalEvent, queryJournal, } from "./journal.js";
24
24
  import { readFileSync, unlinkSync, existsSync } from "node:fs";
25
25
  import { join } from "node:path";
26
- import { findStaleWorkerForProject, getAllAutoWorkers, } from "./db/auto-workers.js";
26
+ import { findStaleWorkerForProject, getAllAutoWorkers, markWorkerCrashed, } from "./db/auto-workers.js";
27
+ import { markLatestActiveForWorkerCanceled } from "./db/unit-dispatches.js";
27
28
  import { getRuntimeKv, setRuntimeKv, deleteRuntimeKv } from "./db/runtime-kv.js";
28
29
  import { _getAdapter, isDbAvailable } from "./gsd-db.js";
29
30
  import { gsdRoot, normalizeRealPath } from "./paths.js";
@@ -34,6 +35,16 @@ const SESSION_FILE_KV_KEY = "session_file";
34
35
  function lockPath(basePath) {
35
36
  return join(gsdRoot(basePath), effectiveLockFile());
36
37
  }
38
+ function clearLegacyLockFile(basePath) {
39
+ try {
40
+ const p = lockPath(basePath);
41
+ if (existsSync(p))
42
+ unlinkSync(p);
43
+ }
44
+ catch {
45
+ // Best-effort.
46
+ }
47
+ }
37
48
  function readLegacyLock(basePath) {
38
49
  try {
39
50
  const p = lockPath(basePath);
@@ -166,21 +177,36 @@ export function writeLock(basePath, unitType, unitId, sessionFile) {
166
177
  * stale session-file pointer.
167
178
  */
168
179
  export function clearLock(basePath) {
180
+ clearLegacyLockFile(basePath);
181
+ if (!isDbAvailable())
182
+ return;
169
183
  try {
170
- const p = lockPath(basePath);
171
- if (existsSync(p))
172
- unlinkSync(p);
184
+ const projectRoot = normalizeRealPath(basePath);
185
+ const worker = findActiveWorkerForCurrentProcess(projectRoot);
186
+ if (!worker)
187
+ return;
188
+ deleteRuntimeKv("worker", worker.worker_id, SESSION_FILE_KV_KEY);
173
189
  }
174
190
  catch {
175
191
  // Best-effort.
176
192
  }
193
+ }
194
+ /**
195
+ * Clear a stale DB-backed worker lock after readCrashLock/findStaleWorkerForProject
196
+ * has identified a dead worker. Unlike clearLock(), this targets the stale
197
+ * worker row instead of the current process's active worker.
198
+ */
199
+ export function clearStaleWorkerLock(basePath) {
200
+ clearLegacyLockFile(basePath);
177
201
  if (!isDbAvailable())
178
202
  return;
179
203
  try {
180
204
  const projectRoot = normalizeRealPath(basePath);
181
- const worker = findActiveWorkerForCurrentProcess(projectRoot);
205
+ const worker = findStaleWorkerForProject(projectRoot);
182
206
  if (!worker)
183
207
  return;
208
+ markLatestActiveForWorkerCanceled(worker.worker_id, "crash-recovered");
209
+ markWorkerCrashed(worker.worker_id);
184
210
  deleteRuntimeKv("worker", worker.worker_id, SESSION_FILE_KV_KEY);
185
211
  }
186
212
  catch {
@@ -391,16 +391,17 @@ export function getRecentUnitKeysForProjectRoot(projectRootRealpath, limit = 20)
391
391
  if (!isDbAvailable())
392
392
  return [];
393
393
  const db = _getAdapter();
394
- const rows = db.prepare(`SELECT ud.unit_id
394
+ const rows = db.prepare(`SELECT ud.unit_type, ud.unit_id
395
395
  FROM unit_dispatches ud
396
396
  INNER JOIN workers w ON w.worker_id = ud.worker_id
397
397
  WHERE w.project_root_realpath = :project_root_realpath
398
+ AND w.status != 'crashed'
398
399
  ORDER BY ud.started_at DESC, ud.id DESC
399
400
  LIMIT :limit`).all({
400
401
  ":project_root_realpath": projectRootRealpath,
401
402
  ":limit": limit,
402
403
  });
403
- return rows.reverse().map((r) => ({ key: r.unit_id }));
404
+ return rows.reverse().map((r) => ({ key: `${r.unit_type}/${r.unit_id}` }));
404
405
  }
405
406
  /**
406
407
  * Fetch dispatches for a milestone filtered by status. Useful for janitors
@@ -4,7 +4,7 @@ import { findMilestoneIds } from "./guided-flow.js";
4
4
  import { parseUnitId } from "./unit-id.js";
5
5
  import { isDbAvailable, getMilestoneSlices, getMilestone } from "./gsd-db.js";
6
6
  import { parseRoadmap } from "./parsers-legacy.js";
7
- import { isClosedStatus } from "./status-guards.js";
7
+ import { isClosedStatus, isSkippedForDispatch } from "./status-guards.js";
8
8
  import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
9
9
  import { readFileSync } from "node:fs";
10
10
  const SLICE_DISPATCH_TYPES = new Set([
@@ -49,7 +49,7 @@ export function getPriorSliceCompletionBlocker(base, _mainBranch, unitType, unit
49
49
  // DB-backed projects must not treat SUMMARY.md as authoritative.
50
50
  if (isDbAvailable()) {
51
51
  const milestoneRow = getMilestone(mid);
52
- if (milestoneRow && isClosedStatus(milestoneRow.status))
52
+ if (milestoneRow && isSkippedForDispatch(milestoneRow.status))
53
53
  continue;
54
54
  }
55
55
  else {
@@ -5,7 +5,7 @@ import { milestonesDir, gsdRoot, resolveGsdRootFile } from "./paths.js";
5
5
  import { deriveState, isGhostMilestone, isReusableGhostMilestone } from "./state.js";
6
6
  import { saveFile } from "./files.js";
7
7
  import { nativeIsRepo, nativeForEachRef, nativeUpdateRef } from "./native-git-bridge.js";
8
- import { readCrashLock, isLockProcessAlive, clearLock } from "./crash-recovery.js";
8
+ import { readCrashLock, isLockProcessAlive, clearStaleWorkerLock } from "./crash-recovery.js";
9
9
  import { getActiveAutoWorkers } from "./db/auto-workers.js";
10
10
  import { normalizeRealPath } from "./paths.js";
11
11
  import { ensureGitignore, isGsdGitignored } from "./gitignore.js";
@@ -46,7 +46,7 @@ export async function checkRuntimeHealth(basePath, issues, fixesApplied, shouldF
46
46
  fixable: true,
47
47
  });
48
48
  if (shouldFix("stale_crash_lock")) {
49
- clearLock(basePath);
49
+ clearStaleWorkerLock(basePath);
50
50
  fixesApplied.push("cleared stale auto-mode worker state");
51
51
  }
52
52
  }
@@ -70,15 +70,32 @@ export async function checkRuntimeHealth(basePath, issues, fixesApplied, shouldF
70
70
  // heartbeat for this project?" — readCrashLock returns null for
71
71
  // healthy live workers (it surfaces stale ones only), so we must
72
72
  // consult getActiveAutoWorkers directly.
73
- const projectRoot = normalizeRealPath(basePath);
74
- const activeWorkers = getActiveAutoWorkers().filter((w) => w.project_root_realpath === projectRoot && isLockProcessAlive({
75
- pid: w.pid,
76
- startedAt: w.started_at,
77
- unitType: "starting",
78
- unitId: "bootstrap",
79
- unitStartedAt: w.started_at,
80
- }));
81
- const lockHolderAlive = activeWorkers.length > 0;
73
+ let lockHolderAlive = false;
74
+ try {
75
+ const projectRoot = normalizeRealPath(basePath);
76
+ for (const worker of getActiveAutoWorkers()) {
77
+ if (worker.project_root_realpath !== projectRoot)
78
+ continue;
79
+ try {
80
+ if (isLockProcessAlive({
81
+ pid: worker.pid,
82
+ startedAt: worker.started_at,
83
+ unitType: "starting",
84
+ unitId: "bootstrap",
85
+ unitStartedAt: worker.started_at,
86
+ })) {
87
+ lockHolderAlive = true;
88
+ break;
89
+ }
90
+ }
91
+ catch {
92
+ // Ignore malformed worker rows or transient PID probe failures.
93
+ }
94
+ }
95
+ }
96
+ catch {
97
+ // If worker lookup fails, continue with the stranded lock diagnosis.
98
+ }
82
99
  if (!lockHolderAlive) {
83
100
  issues.push({
84
101
  severity: "error",
@@ -12,37 +12,11 @@ import { GLOBAL_STATE_CODES } from "./doctor-types.js";
12
12
  import { checkGitHealth, checkRuntimeHealth, checkGlobalHealth, checkEngineHealth } from "./doctor-checks.js";
13
13
  import { checkEnvironmentHealth } from "./doctor-environment.js";
14
14
  import { runProviderChecks } from "./doctor-providers.js";
15
+ import { validateTitle } from "./validation.js";
15
16
  export { summarizeDoctorIssues, filterDoctorIssues, formatDoctorReport, formatDoctorIssuesForPrompt, formatDoctorReportJson } from "./doctor-format.js";
16
17
  export { runEnvironmentChecks, runFullEnvironmentChecks, formatEnvironmentReport } from "./doctor-environment.js";
17
18
  export { computeProgressScore, computeProgressScoreWithContext, formatProgressLine, formatProgressReport } from "./progress-score.js";
18
- /**
19
- * Characters that are used as delimiters in GSD state management documents
20
- * and should not appear in milestone or slice titles.
21
- *
22
- * - "\u2014" (em dash, U+2014): used as a display separator in STATE.md and other docs.
23
- * A title containing "\u2014" makes the separator ambiguous, corrupting state display
24
- * and confusing the LLM agent that reads and writes these files.
25
- * - "\u2013" (en dash, U+2013): visually similar to em dash; same ambiguity risk.
26
- * - "/" (forward slash, U+002F): used as the path separator in unit IDs (M001/S01)
27
- * and git branch names (gsd/M001/S01). A slash in a title can break path resolution.
28
- */
29
- const TITLE_DELIMITER_RE = /[\u2014\u2013\/]/; // em dash, en dash, forward slash
30
- /**
31
- * Check whether a milestone or slice title contains characters that conflict
32
- * with GSD's state document delimiter conventions.
33
- * Returns a human-readable description of the problem, or null if the title is safe.
34
- */
35
- export function validateTitle(title) {
36
- if (TITLE_DELIMITER_RE.test(title)) {
37
- const found = [];
38
- if (/[\u2014\u2013]/.test(title))
39
- found.push("em/en dash (\u2014 or \u2013)");
40
- if (/\//.test(title))
41
- found.push("forward slash (/)");
42
- return `title contains ${found.join(" and ")}, which conflict with GSD state document delimiters`;
43
- }
44
- return null;
45
- }
19
+ export { validateTitle } from "./validation.js";
46
20
  function validatePreferenceShape(preferences) {
47
21
  const issues = [];
48
22
  const listFields = ["always_use_skills", "prefer_skills", "avoid_skills", "custom_instructions"];