gsd-pi 2.82.0-dev.2841a1e44 → 2.82.0-dev.3709f22a5

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 (305) hide show
  1. package/README.md +2 -2
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +7 -0
  4. package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
  5. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  6. package/dist/resources/extensions/gsd/auto/loop.js +5 -5
  7. package/dist/resources/extensions/gsd/auto/orchestrator.js +11 -0
  8. package/dist/resources/extensions/gsd/auto/phases.js +28 -2
  9. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  10. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  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 +70 -9
  14. package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
  15. package/dist/resources/extensions/gsd/auto-start.js +85 -12
  16. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  17. package/dist/resources/extensions/gsd/auto.js +37 -4
  18. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +25 -6
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
  20. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -2
  21. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +5 -2
  22. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +13 -1
  23. package/dist/resources/extensions/gsd/commands/handlers/core.js +17 -1
  24. package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
  25. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  26. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  27. package/dist/resources/extensions/gsd/doctor-git-checks.js +46 -1
  28. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  29. package/dist/resources/extensions/gsd/doctor.js +2 -28
  30. package/dist/resources/extensions/gsd/export-html.js +27 -425
  31. package/dist/resources/extensions/gsd/git-service.js +39 -1
  32. package/dist/resources/extensions/gsd/gsd-db.js +1 -0
  33. package/dist/resources/extensions/gsd/guided-flow.js +93 -111
  34. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  35. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  36. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  37. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  38. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  39. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  40. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  41. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  42. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  43. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  44. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  45. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  46. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  47. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  48. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  49. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  50. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  51. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  52. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  53. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  54. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  55. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  56. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  57. package/dist/resources/extensions/gsd/status-guards.js +4 -0
  58. package/dist/resources/extensions/gsd/templates/plan.md +8 -5
  59. package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
  60. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  61. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  62. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  63. package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
  64. package/dist/resources/extensions/gsd/unit-context-manifest.js +7 -8
  65. package/dist/resources/extensions/gsd/validation.js +23 -1
  66. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  67. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  68. package/dist/resources/extensions/gsd/worktree-lifecycle.js +33 -8
  69. package/dist/resources/extensions/shared/html-shell.js +388 -0
  70. package/dist/resources/extensions/visual-brief/page-contract.js +2 -0
  71. package/dist/resources/extensions/visual-brief/prompts.js +29 -0
  72. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  73. package/dist/web/standalone/.next/BUILD_ID +1 -1
  74. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  75. package/dist/web/standalone/.next/build-manifest.json +3 -3
  76. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  77. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  79. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  87. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  90. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  91. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  92. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  94. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  97. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/index.html +1 -1
  99. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  100. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  102. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  104. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  105. package/dist/web/standalone/.next/server/app/page.js +2 -2
  106. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  107. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  109. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  110. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  113. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  114. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  115. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  116. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  117. package/dist/web/standalone/.next/static/chunks/{webpack-6a95bc41e0f7ec89.js → webpack-9a4db269f9ed63ad.js} +1 -1
  118. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  119. package/package.json +2 -2
  120. package/packages/mcp-server/src/workflow-tools.test.ts +1 -1
  121. package/packages/native/tsconfig.json +2 -1
  122. package/packages/native/tsconfig.tsbuildinfo +1 -1
  123. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  124. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  125. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  126. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  127. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  128. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  129. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  130. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  131. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  132. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  133. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  134. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  135. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  136. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  137. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  138. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  139. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  140. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  141. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  142. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  143. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  144. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  145. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  146. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  147. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  148. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  149. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  150. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  151. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  152. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  153. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  154. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  155. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  156. package/src/resources/GSD-WORKFLOW.md +7 -0
  157. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  158. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  159. package/src/resources/extensions/gsd/auto/contracts.ts +14 -6
  160. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  161. package/src/resources/extensions/gsd/auto/loop.ts +8 -5
  162. package/src/resources/extensions/gsd/auto/orchestrator.ts +11 -0
  163. package/src/resources/extensions/gsd/auto/phases.ts +30 -2
  164. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  165. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  166. package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
  167. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  168. package/src/resources/extensions/gsd/auto-post-unit.ts +77 -7
  169. package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
  170. package/src/resources/extensions/gsd/auto-start.ts +92 -9
  171. package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
  172. package/src/resources/extensions/gsd/auto.ts +40 -4
  173. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +33 -6
  174. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
  175. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -2
  176. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +3 -1
  177. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +16 -1
  178. package/src/resources/extensions/gsd/commands/handlers/core.ts +17 -1
  179. package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
  180. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  181. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  182. package/src/resources/extensions/gsd/doctor-git-checks.ts +45 -1
  183. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  184. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  185. package/src/resources/extensions/gsd/doctor.ts +2 -27
  186. package/src/resources/extensions/gsd/export-html.ts +27 -427
  187. package/src/resources/extensions/gsd/git-service.ts +45 -1
  188. package/src/resources/extensions/gsd/gsd-db.ts +3 -0
  189. package/src/resources/extensions/gsd/guided-flow.ts +126 -128
  190. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  191. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  192. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  193. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  194. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  195. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  196. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  197. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  198. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  199. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  200. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  201. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  202. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  203. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  204. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  205. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  206. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  207. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  208. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  209. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  210. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  211. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  212. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  213. package/src/resources/extensions/gsd/status-guards.ts +5 -0
  214. package/src/resources/extensions/gsd/templates/plan.md +8 -5
  215. package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
  216. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  217. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  218. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +54 -0
  219. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +80 -1
  220. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +6 -6
  221. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  222. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
  223. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
  224. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  225. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
  226. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  227. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
  228. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  229. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  230. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  231. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
  232. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  233. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  234. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
  235. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  236. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  237. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  238. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  239. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  240. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  241. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  242. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  243. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  244. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  245. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  246. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  247. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  248. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +103 -1
  249. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  250. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  251. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  252. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  253. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  254. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  255. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  256. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  257. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  258. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
  259. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  260. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  261. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  262. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  263. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  264. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +20 -1
  265. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
  266. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  267. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  268. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
  269. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  270. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  271. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  272. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +65 -7
  273. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  274. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -1
  275. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  276. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  277. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  278. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  279. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +38 -0
  280. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  281. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  282. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  283. package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
  284. package/src/resources/extensions/gsd/types.ts +1 -1
  285. package/src/resources/extensions/gsd/unit-context-manifest.ts +12 -9
  286. package/src/resources/extensions/gsd/validation.ts +23 -1
  287. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  288. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  289. package/src/resources/extensions/gsd/worktree-lifecycle.ts +41 -8
  290. package/src/resources/extensions/shared/html-shell.ts +412 -0
  291. package/src/resources/extensions/visual-brief/page-contract.ts +2 -0
  292. package/src/resources/extensions/visual-brief/prompts.ts +37 -1
  293. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +40 -0
  294. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  295. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  296. package/dist/web/standalone/.next/static/css/0262768ec1b89d34.css +0 -1
  297. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  298. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  299. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  300. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  301. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  302. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  303. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  304. /package/dist/web/standalone/.next/static/{Qgr2B_MRhPxC0z8fwv4vT → kkGf3_VaPFkiDNV_D7Dtl}/_buildManifest.js +0 -0
  305. /package/dist/web/standalone/.next/static/{Qgr2B_MRhPxC0z8fwv4vT → kkGf3_VaPFkiDNV_D7Dtl}/_ssgManifest.js +0 -0
@@ -13,17 +13,19 @@
13
13
  import { describe, test, beforeEach, afterEach } from "node:test";
14
14
  import assert from "node:assert/strict";
15
15
  import { chmodSync, existsSync, mkdtempSync, writeFileSync, readFileSync, rmSync } from "node:fs";
16
- import { join } from "node:path";
16
+ import { delimiter, join } from "node:path";
17
17
  import { tmpdir } from "node:os";
18
18
  import { execFileSync } from "node:child_process";
19
19
  import {
20
20
  assertWorktreeMaterialized,
21
21
  nativeBranchDelete,
22
22
  nativeCommit,
23
+ nativeGetCurrentBranch,
23
24
  nativeIsRepo,
24
25
  nativeResetHard,
25
26
  nativeWorktreeAdd,
26
27
  } from "../native-git-bridge.js";
28
+ import { GIT_NO_PROMPT_ENV } from "../git-constants.js";
27
29
 
28
30
  // Note: prior static-analysis tests that scanned native-git-bridge.ts for
29
31
  // the raw shell-spawn pattern were removed under #4827 — the integration
@@ -78,6 +80,55 @@ describe("native-git-bridge #4180: fallback runtime behaviour", () => {
78
80
  assert.equal(subject, "test: regression commit #4180");
79
81
  });
80
82
 
83
+ test("nativeCommit retries once after transient ENOBUFS from git", (t) => {
84
+ const bin = mkdtempSync(join(tmpdir(), "ngb-enobufs-bin-"));
85
+ t.after(() => rmSync(bin, { recursive: true, force: true }));
86
+
87
+ const realGit = execFileSync("git", ["--exec-path"], { encoding: "utf-8" }).trim();
88
+ const attempts = join(bin, "attempts.txt");
89
+ const fakeGit = join(bin, "fake-git.cjs");
90
+ writeFileSync(fakeGit, `
91
+ const { appendFileSync, readFileSync } = require("node:fs");
92
+ const { spawnSync } = require("node:child_process");
93
+ const attempts = ${JSON.stringify(attempts)};
94
+ const realGit = ${JSON.stringify(join(realGit, process.platform === "win32" ? "git.exe" : "git"))};
95
+ appendFileSync(attempts, "1");
96
+ if (process.argv[2] === "commit" && readFileSync(attempts, "utf-8").length === 1) {
97
+ console.error("spawnSync git ENOBUFS");
98
+ process.exit(1);
99
+ }
100
+ const result = spawnSync(realGit, process.argv.slice(2), { stdio: "inherit" });
101
+ process.exit(result.status ?? 1);
102
+ `, "utf-8");
103
+
104
+ if (process.platform === "win32") {
105
+ writeFileSync(join(bin, "git.cmd"), `@echo off\r\nnode "${fakeGit}" %*\r\n`, "utf-8");
106
+ } else {
107
+ const shim = join(bin, "git");
108
+ writeFileSync(shim, `#!/bin/sh\nexec node "${fakeGit}" "$@"\n`, "utf-8");
109
+ chmodSync(shim, 0o755);
110
+ }
111
+
112
+ writeFileSync(join(repo, "file.txt"), "retry commit\n");
113
+ git(["add", "."], repo);
114
+
115
+ const originalPath = process.env.PATH ?? "";
116
+ const gitEnv = GIT_NO_PROMPT_ENV as NodeJS.ProcessEnv;
117
+ const originalGitEnvPath = gitEnv.PATH;
118
+ try {
119
+ process.env.PATH = `${bin}${delimiter}${originalPath}`;
120
+ gitEnv.PATH = process.env.PATH;
121
+ const result = nativeCommit(repo, "test: retry ENOBUFS commit");
122
+ assert.ok(result !== null, "commit should succeed after retry");
123
+ } finally {
124
+ process.env.PATH = originalPath;
125
+ gitEnv.PATH = originalGitEnvPath;
126
+ }
127
+
128
+ assert.equal(readFileSync(attempts, "utf-8").length, 2);
129
+ assert.equal(git(["log", "-1", "--format=%s"], repo), "test: retry ENOBUFS commit");
130
+ });
131
+
81
132
  test("nativeCommit runs commit hooks", () => {
82
133
  const hookPath = join(repo, ".git", "hooks", "commit-msg");
83
134
  const marker = join(repo, "hook-ran.txt");
@@ -119,7 +170,17 @@ describe("native-git-bridge #4180: fallback runtime behaviour", () => {
119
170
  test("nativeBranchDelete throws when git cannot delete the branch", () => {
120
171
  assert.throws(
121
172
  () => nativeBranchDelete(repo, "does-not-exist"),
122
- /GSD_GIT_ERROR|git branch -D does-not-exist failed/,
173
+ /git branch -D does-not-exist failed[\s\S]*does-not-exist/,
174
+ );
175
+ });
176
+
177
+ test("nativeGetCurrentBranch preserves git stderr in fallback errors", (t) => {
178
+ const dir = mkdtempSync(join(tmpdir(), "ngb-stderr-notrepo-"));
179
+ t.after(() => rmSync(dir, { recursive: true, force: true }));
180
+
181
+ assert.throws(
182
+ () => nativeGetCurrentBranch(dir),
183
+ /git branch --show-current failed[\s\S]*(not a git repository|not a git repo|fatal:)/,
123
184
  );
124
185
  });
125
186
 
@@ -243,7 +243,7 @@ describe("auditOrphanedMilestoneBranches", () => {
243
243
  );
244
244
  });
245
245
 
246
- test("handles milestone in DB but no branch (no-op)", () => {
246
+ test("milestone in DB, no branch, no worktree dir → no-op", () => {
247
247
  insertMilestone({ id: "M001", title: "Test", status: "complete" });
248
248
 
249
249
  const result = auditOrphanedMilestoneBranches(dir, "worktree");
@@ -251,4 +251,124 @@ describe("auditOrphanedMilestoneBranches", () => {
251
251
  assert.deepStrictEqual(result.recovered, []);
252
252
  assert.deepStrictEqual(result.warnings, []);
253
253
  });
254
+
255
+ test("#5879 — cleans orphaned worktree dir for complete milestone whose branch was already deleted", () => {
256
+ // Reproduces the postflight-stash-restore-failed scenario:
257
+ // 1. An earlier audit deleted milestone/M001 (merged + complete).
258
+ // 2. The worktree dir cleanup failed silently (logWarning only).
259
+ // 3. On the next startup the branch is gone, so the existing branch-keyed
260
+ // loop is invisible to the orphan dir. Without the second pass, the
261
+ // directory lives forever.
262
+ insertMilestone({ id: "M001", title: "Test", status: "complete" });
263
+
264
+ const wtDir = join(dir, ".gsd", "worktrees", "M001");
265
+ mkdirSync(wtDir, { recursive: true });
266
+ writeFileSync(join(wtDir, "leftover.txt"), "stranded from a prior session\n");
267
+
268
+ // No milestone/M001 branch — already deleted on a previous run.
269
+ const branches = run("git branch --list milestone/M001", dir);
270
+ assert.equal(branches, "", "test fixture: branch should not exist");
271
+
272
+ const result = auditOrphanedMilestoneBranches(dir, "worktree");
273
+
274
+ assert.ok(
275
+ result.recovered.some((r) => r.includes("M001") && r.includes("branch already deleted")),
276
+ `should report branch-less orphan cleanup; got: ${JSON.stringify(result.recovered)}`,
277
+ );
278
+ assert.ok(!existsSync(wtDir), "branch-less orphan worktree dir should be removed");
279
+ });
280
+
281
+ test("#5879 — branch list failure still cleans complete orphan only after branch absence is verified", () => {
282
+ insertMilestone({ id: "M001", title: "Test", status: "complete" });
283
+
284
+ const wtDir = join(dir, ".gsd", "worktrees", "M001");
285
+ mkdirSync(wtDir, { recursive: true });
286
+ writeFileSync(join(wtDir, "leftover.txt"), "stranded from a prior session\n");
287
+
288
+ const result = auditOrphanedMilestoneBranches(dir, "worktree", {
289
+ branchList: () => {
290
+ throw new Error("branch list failed");
291
+ },
292
+ branchExists: (_basePath, branch) => {
293
+ assert.equal(branch, "milestone/M001");
294
+ return false;
295
+ },
296
+ });
297
+
298
+ assert.ok(
299
+ result.recovered.some((r) => r.includes("M001") && r.includes("branch already deleted")),
300
+ `should report verified branch-less orphan cleanup; got: ${JSON.stringify(result.recovered)}`,
301
+ );
302
+ assert.ok(!existsSync(wtDir), "verified branch-less orphan worktree dir should be removed");
303
+ });
304
+
305
+ test("#5879 — branch list failure preserves complete worktree when branch still exists", () => {
306
+ insertMilestone({ id: "M001", title: "Test", status: "complete" });
307
+
308
+ const wtDir = join(dir, ".gsd", "worktrees", "M001");
309
+ mkdirSync(wtDir, { recursive: true });
310
+ writeFileSync(join(wtDir, "live-work.txt"), "do not delete\n");
311
+
312
+ const result = auditOrphanedMilestoneBranches(dir, "worktree", {
313
+ branchList: () => {
314
+ throw new Error("branch list failed");
315
+ },
316
+ branchExists: (_basePath, branch) => {
317
+ assert.equal(branch, "milestone/M001");
318
+ return true;
319
+ },
320
+ });
321
+
322
+ assert.deepStrictEqual(result.recovered, []);
323
+ assert.ok(existsSync(wtDir), "worktree dir must be preserved when branch existence is verified");
324
+ });
325
+
326
+ test("#5879 — skips branch-less orphan for milestone that is not complete", () => {
327
+ // Defensive: only `complete` milestones get the branch-less cleanup. An
328
+ // `active` milestone with no branch but a worktree dir is a different
329
+ // state (probably mid-recovery) and should not be silently wiped.
330
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
331
+
332
+ const wtDir = join(dir, ".gsd", "worktrees", "M001");
333
+ mkdirSync(wtDir, { recursive: true });
334
+ writeFileSync(join(wtDir, "live-work.txt"), "do not delete\n");
335
+
336
+ const result = auditOrphanedMilestoneBranches(dir, "worktree");
337
+
338
+ assert.deepStrictEqual(result.recovered, []);
339
+ assert.ok(existsSync(wtDir), "active milestone worktree dir must be preserved");
340
+ });
341
+
342
+ test("#5879 — branch list failure does not delete worktree for milestone that is not complete", () => {
343
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
344
+
345
+ const wtDir = join(dir, ".gsd", "worktrees", "M001");
346
+ mkdirSync(wtDir, { recursive: true });
347
+ writeFileSync(join(wtDir, "live-work.txt"), "do not delete\n");
348
+
349
+ const result = auditOrphanedMilestoneBranches(dir, "worktree", {
350
+ branchList: () => {
351
+ throw new Error("branch list failed");
352
+ },
353
+ branchExists: () => {
354
+ throw new Error("branchExists should not be called for active milestones");
355
+ },
356
+ });
357
+
358
+ assert.deepStrictEqual(result.recovered, []);
359
+ assert.ok(existsSync(wtDir), "active milestone worktree dir must be preserved");
360
+ });
361
+
362
+ test("#5879 — skips branch-less orphan in 'none' isolation mode", () => {
363
+ insertMilestone({ id: "M001", title: "Test", status: "complete" });
364
+
365
+ const wtDir = join(dir, ".gsd", "worktrees", "M001");
366
+ mkdirSync(wtDir, { recursive: true });
367
+ writeFileSync(join(wtDir, "leftover.txt"), "stranded\n");
368
+
369
+ const result = auditOrphanedMilestoneBranches(dir, "none");
370
+
371
+ assert.deepStrictEqual(result.recovered, []);
372
+ assert.ok(existsSync(wtDir), "'none' mode must not touch worktree dirs");
373
+ });
254
374
  });
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { test } from "node:test";
9
9
  import assert from "node:assert/strict";
10
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
10
+ import { existsSync, mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
11
11
  import { join } from "node:path";
12
12
  import { tmpdir } from "node:os";
13
13
 
@@ -48,6 +48,60 @@ test("parkMilestone updates DB status to 'parked' (#2694)", () => {
48
48
  }
49
49
  });
50
50
 
51
+ test("parkMilestone ignores blocked SUMMARY.md when DB milestone is active (#5828)", () => {
52
+ const base = createBase();
53
+ try {
54
+ openDatabase(":memory:");
55
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
56
+ writeFileSync(
57
+ join(base, ".gsd", "milestones", "M001", "M001-SUMMARY.md"),
58
+ [
59
+ "---",
60
+ "status: closeout_blocked",
61
+ "---",
62
+ "",
63
+ "# M001 Summary",
64
+ "",
65
+ "Completion was not persisted.",
66
+ ].join("\n"),
67
+ "utf-8",
68
+ );
69
+
70
+ const parked = parkMilestone(base, "M001", "test");
71
+
72
+ assert.ok(parked, "active DB row should allow parking despite a blocked SUMMARY.md");
73
+ assert.ok(
74
+ existsSync(join(base, ".gsd", "milestones", "M001", "M001-PARKED.md")),
75
+ "PARKED.md should be written",
76
+ );
77
+ assert.equal(getMilestone("M001")!.status, "parked", "DB status should be parked");
78
+ } finally {
79
+ closeDatabase();
80
+ rmSync(base, { recursive: true, force: true });
81
+ }
82
+ });
83
+
84
+ test("parkMilestone refuses DB-complete milestones (#5828)", () => {
85
+ const base = createBase();
86
+ try {
87
+ openDatabase(":memory:");
88
+ insertMilestone({ id: "M001", title: "Test", status: "complete" });
89
+
90
+ const parked = parkMilestone(base, "M001", "test");
91
+
92
+ assert.equal(parked, false, "complete DB row should not be parkable");
93
+ assert.equal(
94
+ existsSync(join(base, ".gsd", "milestones", "M001", "M001-PARKED.md")),
95
+ false,
96
+ "PARKED.md should not be written",
97
+ );
98
+ assert.equal(getMilestone("M001")!.status, "complete", "DB status should remain complete");
99
+ } finally {
100
+ closeDatabase();
101
+ rmSync(base, { recursive: true, force: true });
102
+ }
103
+ });
104
+
51
105
  test("unparkMilestone updates DB status to 'active' (#2694)", () => {
52
106
  const base = createBase();
53
107
  try {
@@ -11,6 +11,7 @@ import {
11
11
  clearPendingAutoStart,
12
12
  _getPendingAutoStart,
13
13
  } from "../guided-flow.ts";
14
+ import type { PendingAutoStartInput } from "../pending-auto-start.ts";
14
15
 
15
16
  // ─── Helpers ─────────────────────────────────────────────────────────────────
16
17
 
@@ -20,6 +21,15 @@ function makeProjectDir(): string {
20
21
  return dir;
21
22
  }
22
23
 
24
+ function pendingInput(basePath: string, milestoneId: string) {
25
+ return {
26
+ basePath,
27
+ milestoneId,
28
+ ctx: { ui: { notify: () => undefined } } as any,
29
+ pi: { sendMessage: () => undefined } as any,
30
+ };
31
+ }
32
+
23
33
  // ─── Tests ───────────────────────────────────────────────────────────────────
24
34
 
25
35
  describe("pendingAutoStart scope pinning (C1)", () => {
@@ -38,7 +48,7 @@ describe("pendingAutoStart scope pinning (C1)", () => {
38
48
  });
39
49
 
40
50
  test("setPendingAutoStart stores a scope whose paths derive from the basePath at reservation time", () => {
41
- setPendingAutoStart(base, { basePath: base, milestoneId: "M001" });
51
+ setPendingAutoStart(base, pendingInput(base, "M001"));
42
52
 
43
53
  const entry = _getPendingAutoStart(base);
44
54
  assert.ok(entry, "entry should exist");
@@ -54,8 +64,22 @@ describe("pendingAutoStart scope pinning (C1)", () => {
54
64
  assert.equal(entry.scope.stateFile(), expectedState);
55
65
  });
56
66
 
67
+ test("setPendingAutoStart rejects entries without ctx and pi before storing them", () => {
68
+ assert.throws(
69
+ () =>
70
+ setPendingAutoStart(base, {
71
+ basePath: base,
72
+ milestoneId: "M001",
73
+ } as PendingAutoStartInput),
74
+ /requires ctx and pi/,
75
+ "pending entries must include the handles later used by auto-start recovery",
76
+ );
77
+
78
+ assert.equal(_getPendingAutoStart(base), null);
79
+ });
80
+
57
81
  test("scope paths are unaffected by process.chdir after reservation", (t) => {
58
- setPendingAutoStart(base, { basePath: base, milestoneId: "M002" });
82
+ setPendingAutoStart(base, pendingInput(base, "M002"));
59
83
 
60
84
  const entry = _getPendingAutoStart(base);
61
85
  assert.ok(entry, "entry should exist");
@@ -82,7 +106,7 @@ describe("pendingAutoStart scope pinning (C1)", () => {
82
106
 
83
107
  test("scope identityKey matches the realpath of the original basePath even with trailing slash", () => {
84
108
  const baseWithSlash = base + "/";
85
- setPendingAutoStart(base, { basePath: baseWithSlash, milestoneId: "M003" });
109
+ setPendingAutoStart(base, pendingInput(baseWithSlash, "M003"));
86
110
 
87
111
  const entry = _getPendingAutoStart(base);
88
112
  assert.ok(entry, "entry should exist");
@@ -96,7 +120,7 @@ describe("pendingAutoStart scope pinning (C1)", () => {
96
120
  });
97
121
 
98
122
  test("clearPendingAutoStart removes the entry", () => {
99
- setPendingAutoStart(base, { basePath: base, milestoneId: "M001" });
123
+ setPendingAutoStart(base, pendingInput(base, "M001"));
100
124
 
101
125
  const before = _getPendingAutoStart(base);
102
126
  assert.ok(before, "entry should exist before clear");
@@ -108,7 +132,7 @@ describe("pendingAutoStart scope pinning (C1)", () => {
108
132
  });
109
133
 
110
134
  test("_getPendingAutoStart with no basePath argument returns the sole entry", () => {
111
- setPendingAutoStart(base, { basePath: base, milestoneId: "M001" });
135
+ setPendingAutoStart(base, pendingInput(base, "M001"));
112
136
 
113
137
  // No argument — should return the sole entry
114
138
  const entry = _getPendingAutoStart();
@@ -116,6 +116,32 @@ test('handlePlanMilestone rejects invalid payloads', async () => {
116
116
  }
117
117
  });
118
118
 
119
+ test('handlePlanMilestone rejects delimiter characters in milestone and slice titles', async () => {
120
+ const base = makeTmpBase();
121
+ const dbPath = join(base, '.gsd', 'gsd.db');
122
+ openDatabase(dbPath);
123
+
124
+ try {
125
+ const milestoneResult = await handlePlanMilestone({ ...validParams(), title: 'Client/Server split' }, base);
126
+ assert.ok('error' in milestoneResult);
127
+ assert.match(milestoneResult.error, /validation failed: title is invalid: .*forward slash/);
128
+ assert.equal(getMilestone('M001'), null, 'invalid milestone title must not persist');
129
+
130
+ const sliceResult = await handlePlanMilestone({
131
+ ...validParams(),
132
+ slices: [
133
+ validParams().slices[0],
134
+ { ...validParams().slices[1], title: 'Client/Server migration' },
135
+ ],
136
+ }, base);
137
+ assert.ok('error' in sliceResult);
138
+ assert.match(sliceResult.error, /validation failed: slices\[1\]\.title is invalid: .*forward slash/);
139
+ assert.equal(getMilestoneSlices('M001').length, 0, 'invalid slice title must not persist partial roadmap state');
140
+ } finally {
141
+ cleanup(base);
142
+ }
143
+ });
144
+
119
145
  test('handlePlanMilestone surfaces render failures and does not clear parse-visible state on failure', async () => {
120
146
  const base = makeTmpBase();
121
147
  const dbPath = join(base, '.gsd', 'gsd.db');
@@ -65,7 +65,9 @@ test("plan-slice prompt: DB-backed tool names survive template substitution", ()
65
65
  const result = loadPrompt("plan-slice", { ...BASE_VARS, commitInstruction: "Do not commit." });
66
66
  assert.ok(result.includes("gsd_plan_slice"), "gsd_plan_slice should appear in rendered prompt");
67
67
  assert.ok(result.includes("gsd_plan_task"), "gsd_plan_task should appear in rendered prompt");
68
+ assert.ok(result.includes("gsd_decision_save"), "structural decisions should use DB-backed decision tool");
68
69
  assert.ok(result.includes("canonical write path"), "canonical write path language should survive substitution");
70
+ assert.doesNotMatch(result, /append them to `.gsd\/DECISIONS\.md`/);
69
71
  });
70
72
 
71
73
  test("plan-slice prompt: compact planning gates survive template substitution", () => {