gsd-pi 2.82.0-dev.ed17d078d → 3.0.0

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 (567) hide show
  1. package/README.md +6 -5
  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/claude-code-cli/stream-adapter.js +1 -1
  6. package/dist/resources/extensions/cmux/index.js +5 -0
  7. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  8. package/dist/resources/extensions/gsd/auto/loop.js +19 -6
  9. package/dist/resources/extensions/gsd/auto/orchestrator.js +11 -0
  10. package/dist/resources/extensions/gsd/auto/phases.js +81 -31
  11. package/dist/resources/extensions/gsd/auto/session.js +4 -0
  12. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +3 -0
  13. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  14. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  15. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
  17. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  18. package/dist/resources/extensions/gsd/auto-post-unit.js +246 -133
  19. package/dist/resources/extensions/gsd/auto-prompts.js +2 -2
  20. package/dist/resources/extensions/gsd/auto-recovery.js +71 -14
  21. package/dist/resources/extensions/gsd/auto-start.js +87 -14
  22. package/dist/resources/extensions/gsd/auto-verification.js +45 -26
  23. package/dist/resources/extensions/gsd/auto-worktree.js +176 -10
  24. package/dist/resources/extensions/gsd/auto.js +57 -33
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +31 -7
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -9
  27. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -2
  28. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  29. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +17 -3
  30. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  31. package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
  32. package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -0
  33. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  34. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  35. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +7 -2
  36. package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
  37. package/dist/resources/extensions/gsd/crash-recovery.js +43 -5
  38. package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
  39. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  40. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  41. package/dist/resources/extensions/gsd/doctor-git-checks.js +46 -1
  42. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  43. package/dist/resources/extensions/gsd/doctor.js +2 -28
  44. package/dist/resources/extensions/gsd/export-html.js +27 -425
  45. package/dist/resources/extensions/gsd/forensics.js +3 -3
  46. package/dist/resources/extensions/gsd/git-service.js +45 -3
  47. package/dist/resources/extensions/gsd/gsd-db.js +21 -6
  48. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
  49. package/dist/resources/extensions/gsd/guided-flow.js +101 -116
  50. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  51. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -8
  52. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  53. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  54. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  55. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  56. package/dist/resources/extensions/gsd/paths.js +4 -0
  57. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  58. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  59. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  60. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  61. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  62. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  63. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  64. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  65. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  66. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  67. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  68. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  69. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  70. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  71. package/dist/resources/extensions/gsd/queue-reorder-ui.js +30 -13
  72. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  73. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  74. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  75. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  76. package/dist/resources/extensions/gsd/state.js +3 -3
  77. package/dist/resources/extensions/gsd/status-guards.js +11 -0
  78. package/dist/resources/extensions/gsd/templates/plan.md +9 -5
  79. package/dist/resources/extensions/gsd/templates/task-plan.md +10 -2
  80. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  81. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  82. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  83. package/dist/resources/extensions/gsd/tools/plan-slice.js +87 -14
  84. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  85. package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
  86. package/dist/resources/extensions/gsd/validation.js +23 -1
  87. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  88. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  89. package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
  90. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  91. package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
  92. package/dist/resources/extensions/gsd/worktree-manager.js +1 -1
  93. package/dist/resources/extensions/shared/html-shell.js +388 -0
  94. package/dist/resources/extensions/subagent/index.js +448 -78
  95. package/dist/resources/extensions/subagent/launch.js +77 -0
  96. package/dist/resources/extensions/subagent/run-store.js +148 -0
  97. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  98. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  99. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  100. package/dist/resources/extensions/visual-brief/index.js +5 -0
  101. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  102. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  103. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  104. package/dist/web/standalone/.next/BUILD_ID +1 -1
  105. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  106. package/dist/web/standalone/.next/build-manifest.json +4 -4
  107. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  108. package/dist/web/standalone/.next/react-loadable-manifest.json +5 -5
  109. package/dist/web/standalone/.next/required-server-files.json +3 -3
  110. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  111. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  121. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  131. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  150. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  170. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  180. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  186. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  202. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  206. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/index.html +1 -1
  216. package/dist/web/standalone/.next/server/app/index.rsc +5 -8
  217. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  218. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -8
  219. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  220. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  221. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  222. package/dist/web/standalone/.next/server/app/page.js +2 -2
  223. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  224. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  225. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  226. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  227. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  228. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  229. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  230. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  231. package/dist/web/standalone/.next/server/middleware.js +2 -2
  232. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  233. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  234. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  235. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  236. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  237. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  238. package/dist/web/standalone/.next/static/chunks/8359.65b24fac92188a6b.js +10 -0
  239. package/dist/web/standalone/.next/static/chunks/9441.ff70bb53f6835771.js +1 -0
  240. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  241. package/dist/web/standalone/.next/static/chunks/app/layout-b23b3f6858dc6dc8.js +1 -0
  242. package/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +1 -0
  243. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  244. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  245. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-855d616060cb6e59.js} +1 -1
  246. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  247. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  248. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  249. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  250. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  251. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  252. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  253. package/dist/web/standalone/server.js +1 -1
  254. package/package.json +4 -4
  255. package/packages/contracts/dist/rpc.test.js +7 -0
  256. package/packages/contracts/dist/rpc.test.js.map +1 -1
  257. package/packages/contracts/dist/workflow.d.ts +21 -0
  258. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  259. package/packages/contracts/dist/workflow.js +24 -0
  260. package/packages/contracts/dist/workflow.js.map +1 -1
  261. package/packages/contracts/src/rpc.test.ts +8 -0
  262. package/packages/contracts/src/workflow.ts +24 -0
  263. package/packages/daemon/package.json +2 -2
  264. package/packages/mcp-server/README.md +13 -4
  265. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  266. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  267. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  268. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  269. package/packages/mcp-server/package.json +2 -2
  270. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  271. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  272. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  273. package/packages/native/package.json +1 -1
  274. package/packages/native/tsconfig.json +2 -1
  275. package/packages/native/tsconfig.tsbuildinfo +1 -1
  276. package/packages/pi-agent-core/package.json +1 -1
  277. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  278. package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
  279. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  280. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
  281. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
  282. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
  283. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
  284. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  285. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  286. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  287. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  288. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  289. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  290. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  291. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  292. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  293. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  294. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  295. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  296. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  297. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  298. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  299. package/packages/pi-ai/package.json +1 -1
  300. package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +49 -0
  301. package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
  302. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  303. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  304. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  305. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  306. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  307. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  308. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  309. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  310. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  311. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  312. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  313. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
  314. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  315. package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
  316. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  317. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  318. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  319. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  321. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +71 -97
  322. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  323. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +25 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
  325. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  326. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +24 -10
  328. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  329. package/packages/pi-coding-agent/package.json +1 -1
  330. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  331. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  332. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
  333. package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
  334. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  335. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -102
  336. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +30 -1
  337. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +29 -10
  338. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  339. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
  340. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
  341. package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
  342. package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
  343. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  344. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  345. package/packages/pi-tui/dist/terminal.js +12 -0
  346. package/packages/pi-tui/dist/terminal.js.map +1 -1
  347. package/packages/pi-tui/package.json +1 -1
  348. package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
  349. package/packages/pi-tui/src/terminal.ts +11 -0
  350. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  351. package/packages/rpc-client/package.json +1 -1
  352. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  353. package/pkg/package.json +1 -1
  354. package/src/resources/GSD-WORKFLOW.md +10 -1
  355. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  356. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +1 -1
  357. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  358. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +9 -0
  359. package/src/resources/extensions/cmux/index.ts +6 -0
  360. package/src/resources/extensions/gsd/auto/contracts.ts +14 -6
  361. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  362. package/src/resources/extensions/gsd/auto/loop.ts +22 -6
  363. package/src/resources/extensions/gsd/auto/orchestrator.ts +11 -0
  364. package/src/resources/extensions/gsd/auto/phases.ts +90 -38
  365. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  366. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +5 -1
  367. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  368. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  369. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
  370. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -19
  371. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  372. package/src/resources/extensions/gsd/auto-post-unit.ts +279 -144
  373. package/src/resources/extensions/gsd/auto-prompts.ts +2 -2
  374. package/src/resources/extensions/gsd/auto-recovery.ts +74 -11
  375. package/src/resources/extensions/gsd/auto-start.ts +94 -12
  376. package/src/resources/extensions/gsd/auto-verification.ts +58 -36
  377. package/src/resources/extensions/gsd/auto-worktree.ts +193 -10
  378. package/src/resources/extensions/gsd/auto.ts +59 -31
  379. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +42 -7
  380. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -9
  381. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -2
  382. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  383. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +20 -4
  384. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  385. package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
  386. package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -0
  387. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  388. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  389. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +8 -3
  390. package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
  391. package/src/resources/extensions/gsd/crash-recovery.ts +44 -4
  392. package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
  393. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  394. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  395. package/src/resources/extensions/gsd/doctor-git-checks.ts +45 -1
  396. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  397. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  398. package/src/resources/extensions/gsd/doctor.ts +2 -27
  399. package/src/resources/extensions/gsd/export-html.ts +27 -427
  400. package/src/resources/extensions/gsd/forensics.ts +3 -3
  401. package/src/resources/extensions/gsd/git-service.ts +51 -4
  402. package/src/resources/extensions/gsd/gsd-db.ts +21 -6
  403. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
  404. package/src/resources/extensions/gsd/guided-flow.ts +134 -133
  405. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  406. package/src/resources/extensions/gsd/markdown-renderer.ts +10 -8
  407. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  408. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  409. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  410. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  411. package/src/resources/extensions/gsd/paths.ts +5 -0
  412. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  413. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  414. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  415. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  416. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  417. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  418. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  419. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  420. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  421. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  422. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  423. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  424. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  425. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  426. package/src/resources/extensions/gsd/queue-reorder-ui.ts +31 -13
  427. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  428. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  429. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  430. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  431. package/src/resources/extensions/gsd/state.ts +3 -3
  432. package/src/resources/extensions/gsd/status-guards.ts +13 -0
  433. package/src/resources/extensions/gsd/templates/plan.md +9 -5
  434. package/src/resources/extensions/gsd/templates/task-plan.md +10 -2
  435. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  436. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  437. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +56 -0
  438. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +80 -1
  439. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +151 -12
  440. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  441. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +18 -6
  442. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +91 -6
  443. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  444. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
  445. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  446. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  447. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
  448. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  449. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
  450. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  451. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +378 -0
  452. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  453. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  454. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  455. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +86 -2
  456. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
  457. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  458. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  459. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +66 -0
  460. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  461. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  462. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  463. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  464. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +11 -0
  465. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +5 -2
  466. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  467. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  468. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  469. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  470. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  471. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  472. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  473. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  474. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  475. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  476. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +112 -1
  477. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  478. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +46 -0
  479. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
  480. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  481. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  482. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  483. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  484. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  485. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  486. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -1
  487. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  488. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  489. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +251 -2
  490. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  491. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  492. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  493. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  494. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +84 -0
  495. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  496. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +59 -0
  497. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  498. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
  499. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +6 -0
  500. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
  501. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
  502. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
  503. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  504. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  505. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
  506. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  507. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  508. package/src/resources/extensions/gsd/tests/status-guards.test.ts +13 -1
  509. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  510. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  511. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +103 -7
  512. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
  513. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  514. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  515. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
  516. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -1
  517. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  518. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  519. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  520. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  521. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
  522. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
  523. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  524. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  525. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  526. package/src/resources/extensions/gsd/tools/plan-slice.ts +97 -12
  527. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  528. package/src/resources/extensions/gsd/types.ts +1 -1
  529. package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
  530. package/src/resources/extensions/gsd/validation.ts +23 -1
  531. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  532. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  533. package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
  534. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  535. package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
  536. package/src/resources/extensions/gsd/worktree-manager.ts +1 -1
  537. package/src/resources/extensions/shared/html-shell.ts +412 -0
  538. package/src/resources/extensions/subagent/index.ts +567 -103
  539. package/src/resources/extensions/subagent/launch.ts +131 -0
  540. package/src/resources/extensions/subagent/run-store.ts +218 -0
  541. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  542. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  543. package/src/resources/extensions/ttsr/ttsr-manager.ts +5 -1
  544. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  545. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  546. package/src/resources/extensions/visual-brief/index.ts +8 -0
  547. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  548. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  549. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  550. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  551. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  552. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +0 -10
  553. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
  554. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  555. package/dist/web/standalone/.next/static/chunks/app/page-752f1e2ebdaa3e45.js +0 -1
  556. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  557. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  558. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  559. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  560. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  561. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  562. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  563. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  564. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  565. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  566. /package/dist/web/standalone/.next/static/{YEvjuT-fsFfYQhDSWtueS → qoMxZh-xuwuvpFW0x0k01}/_buildManifest.js +0 -0
  567. /package/dist/web/standalone/.next/static/{YEvjuT-fsFfYQhDSWtueS → qoMxZh-xuwuvpFW0x0k01}/_ssgManifest.js +0 -0
@@ -195,6 +195,11 @@ describe("infrastructure error detection", () => {
195
195
  assert.equal(isInfrastructureError(err), "EAGAIN");
196
196
  });
197
197
 
198
+ test("ENOBUFS (no buffer space available) is detected", () => {
199
+ const err = Object.assign(new Error("spawnSync git ENOBUFS"), { code: "ENOBUFS" });
200
+ assert.equal(isInfrastructureError(err), "ENOBUFS");
201
+ });
202
+
198
203
  test("SQLite WAL corruption is detected via message scan", () => {
199
204
  const err = new Error("database disk image is malformed");
200
205
  assert.equal(isInfrastructureError(err), "SQLITE_CORRUPT");
@@ -223,7 +228,7 @@ describe("infrastructure error detection", () => {
223
228
  test("all INFRA_ERROR_CODES are covered", () => {
224
229
  const expectedCodes = [
225
230
  "ENOSPC", "ENOMEM", "EROFS", "EDQUOT", "EMFILE",
226
- "ENFILE", "EAGAIN", "ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
231
+ "ENFILE", "EAGAIN", "ENOBUFS", "ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
227
232
  ];
228
233
  for (const code of expectedCodes) {
229
234
  assert.ok(INFRA_ERROR_CODES.has(code), `${code} should be in INFRA_ERROR_CODES`);
@@ -22,6 +22,7 @@ import type { IterationContext, LoopState, PreDispatchData, IterationData } from
22
22
  import type { SessionLockStatus } from "../session-lock.js";
23
23
  import { runDispatch, runUnitPhase, runPreDispatch, runFinalize } from "../auto/phases.js";
24
24
  import { readUnitRuntimeRecord } from "../unit-runtime.js";
25
+ import { ModelPolicyDispatchBlockedError } from "../auto-model-selection.js";
25
26
  import {
26
27
  closeDatabase,
27
28
  insertMilestone,
@@ -160,6 +161,8 @@ function makeIC(
160
161
  pi: {
161
162
  sendMessage: () => {},
162
163
  setModel: async () => true,
164
+ getThinkingLevel: () => "off",
165
+ setThinkingLevel: () => {},
163
166
  } as any,
164
167
  s: makeSession(),
165
168
  deps,
@@ -868,6 +871,49 @@ test("runUnitPhase increments unitDispatchCount for repeated artifact-missing re
868
871
  assert.equal(ic.s.unitDispatchCount.get("execute-task/M001/S01/T01"), 2);
869
872
  });
870
873
 
874
+ test("runUnitPhase pre-dispatch model validation failures do not emit unit-start or dispatch runtime state", async (t) => {
875
+ const capture = createEventCapture();
876
+ const base = mkdtempSync(join(tmpdir(), `gsd-pre-dispatch-block-${randomUUID()}`));
877
+ t.after(() => rmSync(base, { recursive: true, force: true }));
878
+
879
+ const deps = makeMockDeps(capture, {
880
+ selectAndApplyModel: async () => {
881
+ throw new ModelPolicyDispatchBlockedError("execute-task", "M001/S01/T01", []);
882
+ },
883
+ });
884
+ const ic = makeIC(deps, {
885
+ s: {
886
+ ...makeSession(),
887
+ basePath: base,
888
+ } as any,
889
+ });
890
+ const iterData: IterationData = {
891
+ unitType: "execute-task",
892
+ unitId: "M001/S01/T01",
893
+ prompt: "do stuff",
894
+ finalPrompt: "do stuff",
895
+ pauseAfterUatDispatch: false,
896
+ state: { phase: "executing", activeMilestone: { id: "M001" }, activeSlice: { id: "S01" }, registry: [], blockers: [] } as any,
897
+ mid: "M001",
898
+ midTitle: "Test",
899
+ isRetry: false,
900
+ previousTier: undefined,
901
+ };
902
+ const loopState: LoopState = { recentUnits: [{ key: "execute-task/M001/S01/T01" }], stuckRecoveryAttempts: 0, consecutiveFinalizeTimeouts: 0 };
903
+
904
+ await assert.rejects(() => runUnitPhase(ic, iterData, loopState), ModelPolicyDispatchBlockedError);
905
+ await assert.rejects(() => runUnitPhase(ic, iterData, loopState), ModelPolicyDispatchBlockedError);
906
+
907
+ const startEvents = capture.events.filter(e => e.eventType === "unit-start");
908
+ assert.equal(startEvents.length, 0, "pre-dispatch validation failures must not emit unit-start");
909
+ assert.equal(ic.s.unitDispatchCount.get("execute-task/M001/S01/T01") ?? 0, 0, "dispatch count must not increment on pre-dispatch validation failure");
910
+ assert.equal(
911
+ readUnitRuntimeRecord(base, "execute-task", "M001/S01/T01"),
912
+ null,
913
+ "pre-dispatch validation failures must not persist a dispatched runtime record",
914
+ );
915
+ });
916
+
871
917
  test("all events from a mock iteration have monotonically increasing seq and same flowId", async () => {
872
918
  const capture = createEventCapture();
873
919
  const { resolveAgentEnd, _resetPendingResolve } = await import("../auto/resolve.js");
@@ -0,0 +1,179 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import {
4
+ chmodSync,
5
+ existsSync,
6
+ mkdtempSync,
7
+ mkdirSync,
8
+ readFileSync,
9
+ realpathSync,
10
+ rmSync,
11
+ writeFileSync,
12
+ } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { delimiter, join } from "node:path";
15
+ import { execFileSync } from "node:child_process";
16
+
17
+ import { mergeMilestoneToMain } from "../auto-worktree.ts";
18
+ import { closeDatabase, openDatabase } from "../gsd-db.ts";
19
+ import { GIT_NO_PROMPT_ENV } from "../git-constants.js";
20
+ import { _clearGsdRootCache } from "../paths.ts";
21
+ import { _resetServiceCache } from "../worktree.ts";
22
+ import { worktreePath } from "../worktree-manager.ts";
23
+
24
+ function git(args: string[], cwd: string): string {
25
+ return execFileSync("git", args, {
26
+ cwd,
27
+ stdio: ["ignore", "pipe", "pipe"],
28
+ encoding: "utf-8",
29
+ }).trim();
30
+ }
31
+
32
+ function withPlatform<T>(platform: NodeJS.Platform, fn: () => T): T {
33
+ const descriptor = Object.getOwnPropertyDescriptor(process, "platform");
34
+ Object.defineProperty(process, "platform", { value: platform });
35
+ try {
36
+ return fn();
37
+ } finally {
38
+ if (descriptor) {
39
+ Object.defineProperty(process, "platform", descriptor);
40
+ }
41
+ }
42
+ }
43
+
44
+ function realGitPath(): string {
45
+ const gitExecPath = execFileSync("git", ["--exec-path"], {
46
+ encoding: "utf-8",
47
+ }).trim();
48
+ return join(gitExecPath, process.platform === "win32" ? "git.exe" : "git");
49
+ }
50
+
51
+ function installGitShim(bin: string, probePath: string): void {
52
+ const shim = join(bin, "git-proxy.cjs");
53
+ writeFileSync(
54
+ shim,
55
+ `
56
+ const { appendFileSync, existsSync } = require("node:fs");
57
+ const { join } = require("node:path");
58
+ const { spawnSync } = require("node:child_process");
59
+
60
+ const realGit = ${JSON.stringify(realGitPath())};
61
+ const probePath = ${JSON.stringify(probePath)};
62
+ const args = process.argv.slice(2);
63
+
64
+ if (args[0] === "merge" && args[1] === "--squash") {
65
+ const sidecars = [
66
+ join(process.cwd(), ".gsd", "gsd.db-wal"),
67
+ join(process.cwd(), ".gsd", "gsd.db-shm"),
68
+ ];
69
+ const locked = sidecars.find((path) => existsSync(path));
70
+ if (locked) {
71
+ appendFileSync(probePath, "blocked:" + locked + "\\n");
72
+ console.error("error: local changes would be overwritten by merge");
73
+ console.error("\\t" + locked);
74
+ process.exit(1);
75
+ }
76
+ appendFileSync(probePath, "clean\\n");
77
+ }
78
+
79
+ const result = spawnSync(realGit, args, { stdio: "inherit", env: process.env });
80
+ process.exit(result.status ?? 1);
81
+ `,
82
+ "utf-8",
83
+ );
84
+
85
+ if (process.platform === "win32") {
86
+ writeFileSync(join(bin, "git.cmd"), `@echo off\r\nnode "%~dp0git-proxy.cjs" %*\r\n`, "utf-8");
87
+ } else {
88
+ const executable = join(bin, "git");
89
+ writeFileSync(executable, `#!/bin/sh\nexec node "${shim}" "$@"\n`, "utf-8");
90
+ chmodSync(executable, 0o755);
91
+ }
92
+ }
93
+
94
+ function createRepo(root: string): { repo: string; worktree: string } {
95
+ const repo = join(root, "repo");
96
+ mkdirSync(repo, { recursive: true });
97
+ git(["init"], repo);
98
+ git(["config", "user.email", "test@test.com"], repo);
99
+ git(["config", "user.name", "Test"], repo);
100
+ writeFileSync(join(repo, ".gitignore"), ".gsd/\n", "utf-8");
101
+ writeFileSync(join(repo, "README.md"), "# test\n", "utf-8");
102
+ git(["add", "."], repo);
103
+ git(["commit", "-m", "init"], repo);
104
+ git(["branch", "-M", "main"], repo);
105
+
106
+ git(["checkout", "-b", "milestone/M001"], repo);
107
+ writeFileSync(join(repo, "feature.txt"), "milestone change\n", "utf-8");
108
+ mkdirSync(join(repo, ".gsd"), { recursive: true });
109
+ writeFileSync(join(repo, ".gsd", "gsd.db-shm"), "milestone placeholder\n", "utf-8");
110
+ git(["add", "feature.txt"], repo);
111
+ git(["add", "-f", ".gsd/gsd.db-shm"], repo);
112
+ git(["commit", "-m", "feat: milestone change"], repo);
113
+ git(["checkout", "main"], repo);
114
+
115
+ const wt = worktreePath(repo, "M001");
116
+ mkdirSync(join(repo, ".gsd", "worktrees"), { recursive: true });
117
+ git(["worktree", "add", wt, "milestone/M001"], repo);
118
+ return { repo, worktree: wt };
119
+ }
120
+
121
+ test("mergeMilestoneToMain keeps the Windows DB cycle closed through squash merge", () => {
122
+ const savedCwd = process.cwd();
123
+ const originalPath = process.env.PATH ?? "";
124
+ const gitEnv = GIT_NO_PROMPT_ENV as NodeJS.ProcessEnv;
125
+ const originalGitEnvPath = gitEnv.PATH;
126
+ const originalHome = process.env.HOME;
127
+ const originalGsdHome = process.env.GSD_HOME;
128
+
129
+ const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-db-cycle-")));
130
+ const fakeHome = join(root, "home");
131
+ const bin = join(root, "bin");
132
+ const probePath = join(root, "merge-probe.txt");
133
+ mkdirSync(fakeHome, { recursive: true });
134
+ mkdirSync(bin, { recursive: true });
135
+ installGitShim(bin, probePath);
136
+
137
+ try {
138
+ process.env.HOME = fakeHome;
139
+ process.env.GSD_HOME = join(fakeHome, ".gsd");
140
+ _clearGsdRootCache();
141
+ _resetServiceCache();
142
+
143
+ const { repo, worktree } = createRepo(root);
144
+ mkdirSync(join(repo, ".gsd"), { recursive: true });
145
+
146
+ withPlatform("win32", () => {
147
+ assert.equal(openDatabase(join(repo, ".gsd", "gsd.db")), true);
148
+ assert.equal(existsSync(join(repo, ".gsd", "gsd.db-shm")), true);
149
+
150
+ process.env.PATH = `${bin}${delimiter}${originalPath}`;
151
+ gitEnv.PATH = process.env.PATH;
152
+ process.chdir(worktree);
153
+
154
+ const result = mergeMilestoneToMain(repo, "M001", "# M001: Windows DB cycle\n");
155
+ assert.equal(result.codeFilesChanged, true);
156
+ });
157
+
158
+ assert.equal(git(["show", "HEAD:feature.txt"], repo), "milestone change");
159
+ assert.equal(readFileSync(probePath, "utf-8"), "clean\n");
160
+ } finally {
161
+ closeDatabase();
162
+ process.chdir(savedCwd);
163
+ process.env.PATH = originalPath;
164
+ gitEnv.PATH = originalGitEnvPath;
165
+ if (originalHome === undefined) {
166
+ delete process.env.HOME;
167
+ } else {
168
+ process.env.HOME = originalHome;
169
+ }
170
+ if (originalGsdHome === undefined) {
171
+ delete process.env.GSD_HOME;
172
+ } else {
173
+ process.env.GSD_HOME = originalGsdHome;
174
+ }
175
+ _clearGsdRootCache();
176
+ _resetServiceCache();
177
+ if (existsSync(root)) rmSync(root, { recursive: true, force: true });
178
+ }
179
+ });
@@ -41,6 +41,15 @@ const SAMPLE_ROADMAP = `# Project Roadmap
41
41
  - [ ] 31 — Notifications
42
42
  `;
43
43
 
44
+ const SAMPLE_VERSION_PREFIX_ROADMAP = `# Project Roadmap
45
+
46
+ ## Phases
47
+
48
+ - ✅ **v1.0 MVP** — Phases 1-6 (shipped 2026-02-24)
49
+ - ✅ **v1.1 Onboarding** — Phases 7-9 (shipped 2026-03-01)
50
+ - 🚧 **v1.8 Production** — Phases 44-53
51
+ `;
52
+
44
53
  const SAMPLE_PROJECT = `# My Project
45
54
 
46
55
  A sample project for testing the migration parser.
@@ -246,6 +255,21 @@ test('parseOldRoadmap: flat format', () => {
246
255
  assert.deepStrictEqual(roadmap.phases[1].done, false, 'flat roadmap: second phase not done');
247
256
  });
248
257
 
258
+ test('parseOldRoadmap: emoji version-prefix phase ranges', () => {
259
+ const roadmap = parseOldRoadmap(SAMPLE_VERSION_PREFIX_ROADMAP);
260
+ assert.deepStrictEqual(roadmap.milestones.length, 0, 'version roadmap: no milestone sections');
261
+ assert.deepStrictEqual(roadmap.phases.length, 3, 'version roadmap: 3 phase ranges');
262
+ assert.deepStrictEqual(roadmap.phases[0].number, 1, 'version roadmap: first range starts at phase 1');
263
+ assert.deepStrictEqual(roadmap.phases[0].title, 'MVP', 'version roadmap: first title');
264
+ assert.deepStrictEqual(roadmap.phases[0].done, true, 'version roadmap: first range done');
265
+ assert.deepStrictEqual(roadmap.phases[1].number, 7, 'version roadmap: second range starts at phase 7');
266
+ assert.deepStrictEqual(roadmap.phases[1].title, 'Onboarding', 'version roadmap: second title');
267
+ assert.deepStrictEqual(roadmap.phases[1].done, true, 'version roadmap: second range done');
268
+ assert.deepStrictEqual(roadmap.phases[2].number, 44, 'version roadmap: third range starts at phase 44');
269
+ assert.deepStrictEqual(roadmap.phases[2].title, 'Production', 'version roadmap: third title');
270
+ assert.deepStrictEqual(roadmap.phases[2].done, false, 'version roadmap: third range in progress');
271
+ });
272
+
249
273
  test('parseOldRoadmap: milestone-sectioned with <details>', () => {
250
274
  const roadmap = parseOldRoadmap(SAMPLE_MILESTONE_SECTIONED_ROADMAP);
251
275
  assert.ok(roadmap.milestones.length >= 2, 'ms roadmap: has milestone sections');
@@ -387,4 +411,3 @@ test('parseOldProject', () => {
387
411
  const project = parseOldProject(SAMPLE_PROJECT);
388
412
  assert.deepStrictEqual(project, SAMPLE_PROJECT, 'project: returns raw content');
389
413
  });
390
-
@@ -6,13 +6,15 @@ import test from "node:test";
6
6
 
7
7
  import { ensureDbOpen } from "../bootstrap/dynamic-tools.ts";
8
8
  import {
9
- _getAdapter,
10
9
  closeDatabase,
11
10
  getAllMilestones,
11
+ insertMilestone,
12
+ insertSlice,
13
+ insertTask,
12
14
  getSliceTasks,
13
15
  } from "../gsd-db.ts";
14
16
  import {
15
- autoImportMarkdownHierarchyIfDbMismatch,
17
+ checkMarkdownHierarchyAgainstDb,
16
18
  countMarkdownHierarchy,
17
19
  } from "../migration-auto-check.ts";
18
20
  import { writeGSDDirectory } from "../migrate/writer.ts";
@@ -70,7 +72,7 @@ function projectFixture(): GSDProject {
70
72
  };
71
73
  }
72
74
 
73
- test("migration auto-check imports markdown hierarchy when DB is empty", async () => {
75
+ test("migration auto-check preserves empty DB and reports explicit recovery", async () => {
74
76
  const base = makeBase();
75
77
  try {
76
78
  await writeGSDDirectory(projectFixture(), base);
@@ -79,32 +81,35 @@ test("migration auto-check imports markdown hierarchy when DB is empty", async (
79
81
  assert.equal(await ensureDbOpen(base), true);
80
82
  assert.equal(getAllMilestones().length, 0, "fresh authoritative DB starts empty");
81
83
 
82
- const result = await autoImportMarkdownHierarchyIfDbMismatch(base);
83
- assert.equal(result.action, "imported");
84
+ const result = await checkMarkdownHierarchyAgainstDb(base);
85
+ assert.equal(result.action, "recovery-required");
84
86
  assert.equal(result.reason, "db-empty");
85
- assert.deepEqual(result.afterDb, { milestones: 1, slices: 1, tasks: 1 });
86
- assert.equal(getAllMilestones().length, 1);
87
- assert.equal(getSliceTasks("M001", "S01").length, 1);
87
+ assert.deepEqual(result.afterDb, { milestones: 0, slices: 0, tasks: 0 });
88
+ assert.equal(result.recoveryCommand, "gsd recover");
89
+ assert.match(result.message ?? "", /will not import markdown automatically/);
90
+ assert.equal(getAllMilestones().length, 0);
91
+ assert.equal(getSliceTasks("M001", "S01").length, 0);
88
92
  } finally {
89
93
  cleanup(base);
90
94
  }
91
95
  });
92
96
 
93
- test("migration auto-check repairs DB hierarchy count mismatch", async () => {
97
+ test("migration auto-check preserves DB on hierarchy count mismatch", async () => {
94
98
  const base = makeBase();
95
99
  try {
96
100
  await writeGSDDirectory(projectFixture(), base);
97
- await autoImportMarkdownHierarchyIfDbMismatch(base);
98
-
99
- _getAdapter()!.prepare("DELETE FROM tasks WHERE milestone_id = ? AND slice_id = ? AND id = ?").run("M001", "S01", "T01");
101
+ assert.equal(await ensureDbOpen(base), true);
102
+ insertMilestone({ id: "M001", title: "Legacy Milestone", status: "active" });
103
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Legacy Slice", status: "pending", risk: "medium", depends: [], demo: "Legacy slice demo", sequence: 1 });
100
104
  assert.equal(getSliceTasks("M001", "S01").length, 0, "test fixture simulates stale DB task count");
101
105
 
102
- const result = await autoImportMarkdownHierarchyIfDbMismatch(base);
103
- assert.equal(result.action, "imported");
106
+ const result = await checkMarkdownHierarchyAgainstDb(base);
107
+ assert.equal(result.action, "recovery-required");
104
108
  assert.equal(result.reason, "count-mismatch");
105
109
  assert.deepEqual(result.beforeDb, { milestones: 1, slices: 1, tasks: 0 });
106
- assert.deepEqual(result.afterDb, { milestones: 1, slices: 1, tasks: 1 });
107
- assert.equal(getSliceTasks("M001", "S01").length, 1);
110
+ assert.deepEqual(result.afterDb, { milestones: 1, slices: 1, tasks: 0 });
111
+ assert.equal(result.recoveryCommand, "gsd recover");
112
+ assert.equal(getSliceTasks("M001", "S01").length, 0);
108
113
  } finally {
109
114
  cleanup(base);
110
115
  }
@@ -114,9 +119,12 @@ test("migration auto-check leaves matching DB hierarchy alone", async () => {
114
119
  const base = makeBase();
115
120
  try {
116
121
  await writeGSDDirectory(projectFixture(), base);
117
- await autoImportMarkdownHierarchyIfDbMismatch(base);
122
+ assert.equal(await ensureDbOpen(base), true);
123
+ insertMilestone({ id: "M001", title: "Legacy Milestone", status: "active" });
124
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Legacy Slice", status: "pending", risk: "medium", depends: [], demo: "Legacy slice demo", sequence: 1 });
125
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Legacy Task", status: "pending" });
118
126
 
119
- const result = await autoImportMarkdownHierarchyIfDbMismatch(base);
127
+ const result = await checkMarkdownHierarchyAgainstDb(base);
120
128
  assert.equal(result.action, "none");
121
129
  assert.equal(result.reason, "in-sync");
122
130
  assert.deepEqual(result.markdown, { milestones: 1, slices: 1, tasks: 1 });
@@ -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
  });