gsd-pi 2.48.0 → 2.49.0-dev.9e177e9

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 (369) hide show
  1. package/dist/headless-ui.js +12 -2
  2. package/dist/headless.js +29 -13
  3. package/dist/resources/extensions/gsd/auto/infra-errors.js +1 -0
  4. package/dist/resources/extensions/gsd/auto/phases.js +11 -11
  5. package/dist/resources/extensions/gsd/auto/resolve.js +2 -2
  6. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -2
  7. package/dist/resources/extensions/gsd/auto/session.js +4 -0
  8. package/dist/resources/extensions/gsd/auto-artifact-paths.js +8 -10
  9. package/dist/resources/extensions/gsd/auto-dashboard.js +6 -3
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +34 -7
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +34 -27
  12. package/dist/resources/extensions/gsd/auto-prompts.js +102 -21
  13. package/dist/resources/extensions/gsd/auto-recovery.js +62 -184
  14. package/dist/resources/extensions/gsd/auto-start.js +4 -31
  15. package/dist/resources/extensions/gsd/auto-timers.js +2 -2
  16. package/dist/resources/extensions/gsd/auto-verification.js +4 -7
  17. package/dist/resources/extensions/gsd/auto-worktree.js +262 -115
  18. package/dist/resources/extensions/gsd/auto.js +7 -5
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +89 -0
  20. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +8 -1
  21. package/dist/resources/extensions/gsd/branch-patterns.js +13 -0
  22. package/dist/resources/extensions/gsd/commands/handlers/auto.js +43 -3
  23. package/dist/resources/extensions/gsd/doctor-checks.js +5 -1234
  24. package/dist/resources/extensions/gsd/doctor-engine-checks.js +168 -0
  25. package/dist/resources/extensions/gsd/doctor-environment.js +28 -7
  26. package/dist/resources/extensions/gsd/doctor-git-checks.js +405 -0
  27. package/dist/resources/extensions/gsd/doctor-global-checks.js +74 -0
  28. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +600 -0
  29. package/dist/resources/extensions/gsd/doctor.js +9 -1
  30. package/dist/resources/extensions/gsd/extension-manifest.json +1 -1
  31. package/dist/resources/extensions/gsd/git-service.js +20 -20
  32. package/dist/resources/extensions/gsd/gsd-db.js +124 -1
  33. package/dist/resources/extensions/gsd/guided-flow-queue.js +10 -11
  34. package/dist/resources/extensions/gsd/markdown-renderer.js +33 -5
  35. package/dist/resources/extensions/gsd/preferences-types.js +2 -1
  36. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  37. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +27 -8
  38. package/dist/resources/extensions/gsd/prompts/complete-slice.md +9 -8
  39. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +223 -56
  40. package/dist/resources/extensions/gsd/prompts/execute-task.md +16 -13
  41. package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
  42. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
  43. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  44. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  45. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  46. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  47. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  48. package/dist/resources/extensions/gsd/prompts/plan-slice.md +8 -3
  49. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +3 -0
  50. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  51. package/dist/resources/extensions/gsd/prompts/run-uat.md +4 -4
  52. package/dist/resources/extensions/gsd/repo-identity.js +29 -0
  53. package/dist/resources/extensions/gsd/roadmap-slices.js +2 -2
  54. package/dist/resources/extensions/gsd/session-forensics.js +6 -11
  55. package/dist/resources/extensions/gsd/session-lock.js +67 -56
  56. package/dist/resources/extensions/gsd/state.js +34 -7
  57. package/dist/resources/extensions/gsd/templates/milestone-summary.md +8 -0
  58. package/dist/resources/extensions/gsd/templates/plan.md +16 -0
  59. package/dist/resources/extensions/gsd/templates/roadmap.md +13 -0
  60. package/dist/resources/extensions/gsd/templates/slice-summary.md +9 -0
  61. package/dist/resources/extensions/gsd/templates/task-plan.md +24 -0
  62. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -1
  63. package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -3
  64. package/dist/resources/extensions/gsd/verdict-parser.js +84 -0
  65. package/dist/resources/extensions/gsd/worktree-command.js +1 -1
  66. package/dist/resources/extensions/gsd/worktree-resolver.js +24 -0
  67. package/dist/resources/extensions/gsd/worktree.js +3 -2
  68. package/dist/resources/extensions/remote-questions/config.js +3 -5
  69. package/dist/resources/extensions/search-the-web/native-search.js +8 -3
  70. package/dist/resources/extensions/search-the-web/tool-search.js +19 -2
  71. package/dist/resources/skills/github-workflows/references/gh/SKILL.md +22 -1
  72. package/dist/web/standalone/.next/BUILD_ID +1 -1
  73. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  74. package/dist/web/standalone/.next/build-manifest.json +4 -4
  75. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  76. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  77. package/dist/web/standalone/.next/required-server-files.json +4 -4
  78. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  79. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  81. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  89. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  92. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  93. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  95. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  105. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  143. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  149. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  163. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  165. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  167. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  169. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/index.html +1 -1
  179. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  180. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  181. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  182. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  183. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  184. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  185. package/dist/web/standalone/.next/server/app/page.js +2 -2
  186. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  188. package/dist/web/standalone/.next/server/chunks/229.js +2 -2
  189. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  190. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/middleware.js +2 -2
  193. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  195. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  196. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  197. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  198. package/dist/web/standalone/.next/static/chunks/4024.7c75ac378de0f2b5.js +9 -0
  199. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  200. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  201. package/dist/web/standalone/.next/static/chunks/app/page-6654a8cca61a3d1c.js +1 -0
  202. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  203. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  204. package/dist/web/standalone/.next/static/chunks/{webpack-0a4cd455ec4197d2.js → webpack-2473ce2c3879fff4.js} +1 -1
  205. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  206. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  207. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  208. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  209. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  210. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  211. package/dist/web/standalone/server.js +1 -1
  212. package/dist/worktree-cli.js +1 -1
  213. package/package.json +1 -1
  214. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  215. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  216. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  217. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  218. package/packages/pi-ai/dist/providers/openai-codex-responses.js +39 -10
  219. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  220. package/packages/pi-ai/src/providers/openai-codex-responses.ts +39 -8
  221. package/packages/pi-coding-agent/dist/core/blob-store.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/blob-store.js +8 -3
  223. package/packages/pi-coding-agent/dist/core/blob-store.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/discovery-cache.d.ts.map +1 -1
  225. package/packages/pi-coding-agent/dist/core/discovery-cache.js +9 -2
  226. package/packages/pi-coding-agent/dist/core/discovery-cache.js.map +1 -1
  227. package/packages/pi-coding-agent/dist/core/retry-handler.js +1 -1
  228. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  229. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  230. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -32
  231. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  232. package/packages/pi-coding-agent/dist/modes/rpc/jsonl.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/modes/rpc/jsonl.js +5 -0
  234. package/packages/pi-coding-agent/dist/modes/rpc/jsonl.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  236. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +0 -1
  237. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  238. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
  239. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  240. package/packages/pi-coding-agent/package.json +1 -1
  241. package/packages/pi-coding-agent/src/core/blob-store.ts +6 -3
  242. package/packages/pi-coding-agent/src/core/discovery-cache.ts +9 -2
  243. package/packages/pi-coding-agent/src/core/retry-handler.ts +1 -1
  244. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +7 -32
  245. package/packages/pi-coding-agent/src/modes/rpc/jsonl.ts +6 -0
  246. package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +0 -2
  247. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -2
  248. package/pkg/package.json +1 -1
  249. package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +8 -4
  250. package/src/resources/extensions/gsd/auto/infra-errors.ts +1 -0
  251. package/src/resources/extensions/gsd/auto/phases.ts +10 -11
  252. package/src/resources/extensions/gsd/auto/resolve.ts +3 -3
  253. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -2
  254. package/src/resources/extensions/gsd/auto/session.ts +5 -0
  255. package/src/resources/extensions/gsd/auto/types.ts +13 -0
  256. package/src/resources/extensions/gsd/auto-artifact-paths.ts +19 -21
  257. package/src/resources/extensions/gsd/auto-dashboard.ts +5 -2
  258. package/src/resources/extensions/gsd/auto-dispatch.ts +40 -5
  259. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  260. package/src/resources/extensions/gsd/auto-post-unit.ts +36 -31
  261. package/src/resources/extensions/gsd/auto-prompts.ts +113 -19
  262. package/src/resources/extensions/gsd/auto-recovery.ts +65 -199
  263. package/src/resources/extensions/gsd/auto-start.ts +7 -27
  264. package/src/resources/extensions/gsd/auto-timers.ts +2 -2
  265. package/src/resources/extensions/gsd/auto-verification.ts +4 -7
  266. package/src/resources/extensions/gsd/auto-worktree.ts +309 -110
  267. package/src/resources/extensions/gsd/auto.ts +11 -10
  268. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +93 -0
  269. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +8 -0
  270. package/src/resources/extensions/gsd/branch-patterns.ts +16 -0
  271. package/src/resources/extensions/gsd/commands/handlers/auto.ts +46 -3
  272. package/src/resources/extensions/gsd/doctor-checks.ts +5 -1291
  273. package/src/resources/extensions/gsd/doctor-engine-checks.ts +182 -0
  274. package/src/resources/extensions/gsd/doctor-environment.ts +30 -7
  275. package/src/resources/extensions/gsd/doctor-git-checks.ts +415 -0
  276. package/src/resources/extensions/gsd/doctor-global-checks.ts +84 -0
  277. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +626 -0
  278. package/src/resources/extensions/gsd/doctor.ts +9 -1
  279. package/src/resources/extensions/gsd/extension-manifest.json +1 -1
  280. package/src/resources/extensions/gsd/git-service.ts +19 -26
  281. package/src/resources/extensions/gsd/gsd-db.ts +150 -2
  282. package/src/resources/extensions/gsd/guided-flow-queue.ts +11 -12
  283. package/src/resources/extensions/gsd/markdown-renderer.ts +37 -4
  284. package/src/resources/extensions/gsd/preferences-types.ts +5 -1
  285. package/src/resources/extensions/gsd/preferences-validation.ts +37 -0
  286. package/src/resources/extensions/gsd/prompts/complete-milestone.md +27 -8
  287. package/src/resources/extensions/gsd/prompts/complete-slice.md +9 -8
  288. package/src/resources/extensions/gsd/prompts/discuss-headless.md +223 -56
  289. package/src/resources/extensions/gsd/prompts/execute-task.md +16 -13
  290. package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
  291. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
  292. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  293. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  294. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  295. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  296. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  297. package/src/resources/extensions/gsd/prompts/plan-slice.md +8 -3
  298. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +3 -0
  299. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  300. package/src/resources/extensions/gsd/prompts/run-uat.md +4 -4
  301. package/src/resources/extensions/gsd/repo-identity.ts +28 -0
  302. package/src/resources/extensions/gsd/roadmap-slices.ts +2 -2
  303. package/src/resources/extensions/gsd/session-forensics.ts +6 -11
  304. package/src/resources/extensions/gsd/session-lock.ts +92 -64
  305. package/src/resources/extensions/gsd/state.ts +38 -5
  306. package/src/resources/extensions/gsd/templates/milestone-summary.md +8 -0
  307. package/src/resources/extensions/gsd/templates/plan.md +16 -0
  308. package/src/resources/extensions/gsd/templates/roadmap.md +13 -0
  309. package/src/resources/extensions/gsd/templates/slice-summary.md +9 -0
  310. package/src/resources/extensions/gsd/templates/task-plan.md +24 -0
  311. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +2 -2
  312. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +2 -2
  313. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +35 -0
  314. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +1 -81
  315. package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +1 -1
  316. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +14 -12
  317. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  318. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  319. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +9 -12
  320. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +115 -1
  321. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +65 -1
  322. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +50 -0
  323. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +1 -1
  324. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +189 -0
  325. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +156 -0
  326. package/src/resources/extensions/gsd/tests/git-service.test.ts +68 -9
  327. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  328. package/src/resources/extensions/gsd/tests/infra-error.test.ts +12 -2
  329. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +39 -0
  330. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  331. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  332. package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +2 -2
  333. package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +6 -6
  334. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +347 -0
  335. package/src/resources/extensions/gsd/tests/queue-completed-milestone-perf.test.ts +155 -0
  336. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +2 -1
  337. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +32 -0
  338. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +26 -0
  339. package/src/resources/extensions/gsd/tests/run-uat.test.ts +87 -15
  340. package/src/resources/extensions/gsd/tests/session-lock-transient-read.test.ts +223 -0
  341. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +44 -4
  342. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -1
  343. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +2 -1
  344. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +0 -16
  345. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +67 -0
  346. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +1 -1
  347. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +204 -0
  348. package/src/resources/extensions/gsd/tools/plan-slice.ts +16 -0
  349. package/src/resources/extensions/gsd/tools/validate-milestone.ts +3 -3
  350. package/src/resources/extensions/gsd/types.ts +30 -0
  351. package/src/resources/extensions/gsd/verdict-parser.ts +95 -0
  352. package/src/resources/extensions/gsd/verification-gate.ts +0 -2
  353. package/src/resources/extensions/gsd/worktree-command.ts +1 -1
  354. package/src/resources/extensions/gsd/worktree-resolver.ts +31 -0
  355. package/src/resources/extensions/gsd/worktree.ts +3 -2
  356. package/src/resources/extensions/remote-questions/config.ts +3 -5
  357. package/src/resources/extensions/search-the-web/native-search.ts +8 -3
  358. package/src/resources/extensions/search-the-web/tool-search.ts +22 -2
  359. package/src/resources/skills/github-workflows/references/gh/SKILL.md +22 -1
  360. package/dist/resources/extensions/gsd/auto-worktree-sync.js +0 -191
  361. package/dist/resources/extensions/gsd/resource-version.js +0 -97
  362. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +0 -9
  363. package/dist/web/standalone/.next/static/chunks/app/page-12dd5ece0df4badc.js +0 -1
  364. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  365. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  366. package/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -234
  367. package/src/resources/extensions/gsd/resource-version.ts +0 -101
  368. /package/dist/web/standalone/.next/static/{zGWUKFTfjCQerNgsPpAbF → vNN0h0emdEi8l_npi8poE}/_buildManifest.js +0 -0
  369. /package/dist/web/standalone/.next/static/{zGWUKFTfjCQerNgsPpAbF → vNN0h0emdEi8l_npi8poE}/_ssgManifest.js +0 -0
@@ -13,9 +13,19 @@ export function handleExtensionUIRequest(event, writeToStdin) {
13
13
  const { id, method } = event;
14
14
  let response;
15
15
  switch (method) {
16
- case 'select':
17
- response = { type: 'extension_ui_response', id, value: event.options?.[0] ?? '' };
16
+ case 'select': {
17
+ // Lock-guard prompts list "View status" first, but headless needs "Force start"
18
+ // to proceed. Detect by title and pick the force option.
19
+ const title = String(event.title ?? '');
20
+ let selected = event.options?.[0] ?? '';
21
+ if (title.includes('Auto-mode is running') && event.options) {
22
+ const forceOption = event.options.find(o => o.toLowerCase().includes('force start'));
23
+ if (forceOption)
24
+ selected = forceOption;
25
+ }
26
+ response = { type: 'extension_ui_response', id, value: selected };
18
27
  break;
28
+ }
19
29
  case 'confirm':
20
30
  response = { type: 'extension_ui_response', id, confirmed: true };
21
31
  break;
package/dist/headless.js CHANGED
@@ -37,8 +37,8 @@ export function parseHeadlessArgs(argv) {
37
37
  if (!positionalStarted && arg.startsWith('--')) {
38
38
  if (arg === '--timeout' && i + 1 < args.length) {
39
39
  options.timeout = parseInt(args[++i], 10);
40
- if (Number.isNaN(options.timeout) || options.timeout <= 0) {
41
- process.stderr.write('[headless] Error: --timeout must be a positive integer (milliseconds)\n');
40
+ if (Number.isNaN(options.timeout) || options.timeout < 0) {
41
+ process.stderr.write('[headless] Error: --timeout must be a non-negative integer (milliseconds, 0 to disable)\n');
42
42
  process.exit(1);
43
43
  }
44
44
  }
@@ -132,6 +132,13 @@ async function runHeadlessOnce(options, restartCount) {
132
132
  if (isNewMilestone && options.timeout === 300_000) {
133
133
  options.timeout = 600_000; // 10 minutes
134
134
  }
135
+ // auto-mode sessions are long-running (minutes to hours) with their own internal
136
+ // per-unit timeout via auto-supervisor. Disable the overall timeout unless the
137
+ // user explicitly set --timeout.
138
+ const isAutoMode = options.command === 'auto';
139
+ if (isAutoMode && options.timeout === 300_000) {
140
+ options.timeout = 0;
141
+ }
135
142
  // Supervised mode cannot share stdin with --context -
136
143
  if (options.supervised && options.context === '-') {
137
144
  process.stderr.write('[headless] Error: --supervised cannot be used with --context - (both require stdin)\n');
@@ -267,12 +274,14 @@ async function runHeadlessOnce(options, restartCount) {
267
274
  }
268
275
  // Precompute supervised response timeout
269
276
  const responseTimeout = options.responseTimeout ?? 30_000;
270
- // Overall timeout
271
- const timeoutTimer = setTimeout(() => {
272
- process.stderr.write(`[headless] Timeout after ${options.timeout / 1000}s\n`);
273
- exitCode = 1;
274
- resolveCompletion();
275
- }, options.timeout);
277
+ // Overall timeout (disabled when options.timeout === 0, e.g. auto-mode)
278
+ const timeoutTimer = options.timeout > 0
279
+ ? setTimeout(() => {
280
+ process.stderr.write(`[headless] Timeout after ${options.timeout / 1000}s\n`);
281
+ exitCode = 1;
282
+ resolveCompletion();
283
+ }, options.timeout)
284
+ : null;
276
285
  // Event handler
277
286
  client.onEvent((event) => {
278
287
  const eventObj = event;
@@ -354,7 +363,8 @@ async function runHeadlessOnce(options, restartCount) {
354
363
  interrupted = true;
355
364
  exitCode = 1;
356
365
  client.stop().finally(() => {
357
- clearTimeout(timeoutTimer);
366
+ if (timeoutTimer)
367
+ clearTimeout(timeoutTimer);
358
368
  if (idleTimer)
359
369
  clearTimeout(idleTimer);
360
370
  process.exit(exitCode);
@@ -368,7 +378,8 @@ async function runHeadlessOnce(options, restartCount) {
368
378
  }
369
379
  catch (err) {
370
380
  process.stderr.write(`[headless] Error: Failed to start RPC session: ${err instanceof Error ? err.message : String(err)}\n`);
371
- clearTimeout(timeoutTimer);
381
+ if (timeoutTimer)
382
+ clearTimeout(timeoutTimer);
372
383
  process.exit(1);
373
384
  }
374
385
  // Access stdin writer from the internal process
@@ -376,7 +387,8 @@ async function runHeadlessOnce(options, restartCount) {
376
387
  if (!internalProcess?.stdin) {
377
388
  process.stderr.write('[headless] Error: Cannot access child process stdin\n');
378
389
  await client.stop();
379
- clearTimeout(timeoutTimer);
390
+ if (timeoutTimer)
391
+ clearTimeout(timeoutTimer);
380
392
  process.exit(1);
381
393
  }
382
394
  stdinWriter = (data) => {
@@ -424,7 +436,10 @@ async function runHeadlessOnce(options, restartCount) {
424
436
  if (!options.json) {
425
437
  process.stderr.write('[headless] Milestone ready — chaining into auto-mode...\n');
426
438
  }
427
- // Reset completion state for the auto-mode phase
439
+ // Reset completion state for the auto-mode phase.
440
+ // Disable the overall timeout — auto-mode has its own internal supervisor.
441
+ if (timeoutTimer)
442
+ clearTimeout(timeoutTimer);
428
443
  completed = false;
429
444
  milestoneReady = false;
430
445
  blocked = false;
@@ -443,7 +458,8 @@ async function runHeadlessOnce(options, restartCount) {
443
458
  }
444
459
  }
445
460
  // Cleanup
446
- clearTimeout(timeoutTimer);
461
+ if (timeoutTimer)
462
+ clearTimeout(timeoutTimer);
447
463
  if (idleTimer)
448
464
  clearTimeout(idleTimer);
449
465
  pendingResponseTimers.forEach((timer) => clearTimeout(timer));
@@ -17,6 +17,7 @@ export const INFRA_ERROR_CODES = new Set([
17
17
  "EDQUOT", // disk quota exceeded
18
18
  "EMFILE", // too many open files (process)
19
19
  "ENFILE", // too many open files (system)
20
+ "EAGAIN", // resource temporarily unavailable (resource exhaustion)
20
21
  "ECONNREFUSED", // connection refused (offline / local server down)
21
22
  "ENOTFOUND", // DNS lookup failed (offline / no network)
22
23
  "ENETUNREACH", // network unreachable (offline / no route)
@@ -721,18 +721,18 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
721
721
  deps.updateSessionLock(deps.lockBase(), unitType, unitId, sessionFile);
722
722
  deps.writeLock(deps.lockBase(), unitType, unitId, sessionFile);
723
723
  // Tag the most recent window entry with error info for stuck detection
724
- if (unitResult.status === "error" || unitResult.status === "cancelled") {
725
- const lastEntry = loopState.recentUnits[loopState.recentUnits.length - 1];
726
- if (lastEntry) {
724
+ const lastEntry = loopState.recentUnits[loopState.recentUnits.length - 1];
725
+ if (lastEntry) {
726
+ if (unitResult.errorContext) {
727
+ lastEntry.error = `${unitResult.errorContext.category}:${unitResult.errorContext.message}`.slice(0, 200);
728
+ }
729
+ else if (unitResult.status === "error" || unitResult.status === "cancelled") {
727
730
  lastEntry.error = `${unitResult.status}:${unitType}/${unitId}`;
728
731
  }
729
- }
730
- else if (unitResult.event?.messages?.length) {
731
- const lastMsg = unitResult.event.messages[unitResult.event.messages.length - 1];
732
- const msgStr = typeof lastMsg === "string" ? lastMsg : JSON.stringify(lastMsg);
733
- if (/error|fail|exception/i.test(msgStr)) {
734
- const lastEntry = loopState.recentUnits[loopState.recentUnits.length - 1];
735
- if (lastEntry) {
732
+ else if (unitResult.event?.messages?.length) {
733
+ const lastMsg = unitResult.event.messages[unitResult.event.messages.length - 1];
734
+ const msgStr = typeof lastMsg === "string" ? lastMsg : JSON.stringify(lastMsg);
735
+ if (/error|fail|exception/i.test(msgStr)) {
736
736
  lastEntry.error = msgStr.slice(0, 200);
737
737
  }
738
738
  }
@@ -779,7 +779,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
779
779
  s.unitDispatchCount.delete(`${unitType}/${unitId}`);
780
780
  s.unitRecoveryCount.delete(`${unitType}/${unitId}`);
781
781
  }
782
- deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: ic.nextSeq(), eventType: "unit-end", data: { unitType, unitId, status: unitResult.status, artifactVerified }, causedBy: { flowId: ic.flowId, seq: unitStartSeq } });
782
+ deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: ic.nextSeq(), eventType: "unit-end", data: { unitType, unitId, status: unitResult.status, artifactVerified, ...(unitResult.errorContext ? { errorContext: unitResult.errorContext } : {}) }, causedBy: { flowId: ic.flowId, seq: unitStartSeq } });
783
783
  return { action: "next", data: { unitStartedAt: s.currentUnit.startedAt } };
784
784
  }
785
785
  // ─── runFinalize ──────────────────────────────────────────────────────────────
@@ -64,12 +64,12 @@ export function isSessionSwitchInFlight() {
64
64
  * blocks to ensure the autoLoop is never stuck awaiting a promise that
65
65
  * will never resolve. Safe to call when no resolver is pending (no-op).
66
66
  */
67
- export function resolveAgentEndCancelled() {
67
+ export function resolveAgentEndCancelled(errorContext) {
68
68
  if (_currentResolve) {
69
69
  debugLog("resolveAgentEndCancelled", { status: "resolving-cancelled" });
70
70
  const r = _currentResolve;
71
71
  _currentResolve = null;
72
- r({ status: "cancelled" });
72
+ r({ status: "cancelled", ...(errorContext ? { errorContext } : {}) });
73
73
  }
74
74
  }
75
75
  // ─── resetPendingResolve (test helper) ───────────────────────────────────────
@@ -41,13 +41,13 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
41
41
  unitId,
42
42
  error: msg,
43
43
  });
44
- return { status: "cancelled" };
44
+ return { status: "cancelled", errorContext: { message: `Session creation failed: ${msg}`, category: "session-failed", isTransient: true } };
45
45
  }
46
46
  if (sessionTimeoutHandle)
47
47
  clearTimeout(sessionTimeoutHandle);
48
48
  if (sessionResult.cancelled) {
49
49
  debugLog("runUnit-session-timeout", { unitType, unitId });
50
- return { status: "cancelled" };
50
+ return { status: "cancelled", errorContext: { message: "Session creation timed out", category: "timeout", isTransient: true } };
51
51
  }
52
52
  if (!s.active) {
53
53
  return { status: "cancelled" };
@@ -61,6 +61,9 @@ export class AutoSession {
61
61
  lastStateRebuildAt = 0;
62
62
  // ── Sidecar queue ─────────────────────────────────────────────────────
63
63
  sidecarQueue = [];
64
+ // ── Isolation degradation ────────────────────────────────────────────
65
+ /** Set to true when worktree creation fails; prevents merge of nonexistent branch. */
66
+ isolationDegraded = false;
64
67
  // ── Dispatch circuit breakers ──────────────────────────────────────
65
68
  rewriteAttemptCount = 0;
66
69
  // ── Metrics ──────────────────────────────────────────────────────────────
@@ -140,6 +143,7 @@ export class AutoSession {
140
143
  this.pendingQuickTasks = [];
141
144
  this.sidecarQueue = [];
142
145
  this.rewriteAttemptCount = 0;
146
+ this.isolationDegraded = false;
143
147
  // Signal handler
144
148
  this.sigtermHandler = null;
145
149
  // Loop promise state lives in auto-loop.ts module scope
@@ -4,14 +4,13 @@
4
4
  // auto-recovery.ts (Phase 5 dead-code cleanup). The artifact verification
5
5
  // function was removed entirely — callers now query WorkflowEngine directly.
6
6
  import { resolveMilestonePath, resolveSlicePath, relMilestoneFile, relSliceFile, buildMilestoneFileName, buildSliceFileName, buildTaskFileName, } from "./paths.js";
7
+ import { parseUnitId } from "./unit-id.js";
7
8
  import { join } from "node:path";
8
9
  /**
9
10
  * Resolve the expected artifact for a unit to an absolute path.
10
11
  */
11
12
  export function resolveExpectedArtifactPath(unitType, unitId, base) {
12
- const parts = unitId.split("/");
13
- const mid = parts[0];
14
- const sid = parts[1];
13
+ const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
15
14
  switch (unitType) {
16
15
  case "discuss-milestone": {
17
16
  const dir = resolveMilestonePath(base, mid);
@@ -39,10 +38,9 @@ export function resolveExpectedArtifactPath(unitType, unitId, base) {
39
38
  }
40
39
  case "run-uat": {
41
40
  const dir = resolveSlicePath(base, mid, sid);
42
- return dir ? join(dir, buildSliceFileName(sid, "UAT-RESULT")) : null;
41
+ return dir ? join(dir, buildSliceFileName(sid, "UAT")) : null;
43
42
  }
44
43
  case "execute-task": {
45
- const tid = parts[2];
46
44
  const dir = resolveSlicePath(base, mid, sid);
47
45
  return dir && tid
48
46
  ? join(dir, "tasks", buildTaskFileName(tid, "SUMMARY"))
@@ -66,6 +64,9 @@ export function resolveExpectedArtifactPath(unitType, unitId, base) {
66
64
  }
67
65
  case "rewrite-docs":
68
66
  return null;
67
+ case "gate-evaluate":
68
+ // Gate evaluate writes to DB quality_gates table — verified via state derivation
69
+ return null;
69
70
  case "reactive-execute":
70
71
  // Reactive execute produces multiple task summaries — verified separately
71
72
  return null;
@@ -74,9 +75,7 @@ export function resolveExpectedArtifactPath(unitType, unitId, base) {
74
75
  }
75
76
  }
76
77
  export function diagnoseExpectedArtifact(unitType, unitId, base) {
77
- const parts = unitId.split("/");
78
- const mid = parts[0];
79
- const sid = parts[1];
78
+ const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
80
79
  switch (unitType) {
81
80
  case "discuss-milestone":
82
81
  return `${relMilestoneFile(base, mid, "CONTEXT")} (milestone context from discussion)`;
@@ -89,7 +88,6 @@ export function diagnoseExpectedArtifact(unitType, unitId, base) {
89
88
  case "plan-slice":
90
89
  return `${relSliceFile(base, mid, sid, "PLAN")} (slice plan)`;
91
90
  case "execute-task": {
92
- const tid = parts[2];
93
91
  return `Task ${tid} marked [x] in ${relSliceFile(base, mid, sid, "PLAN")} + summary written`;
94
92
  }
95
93
  case "complete-slice":
@@ -101,7 +99,7 @@ export function diagnoseExpectedArtifact(unitType, unitId, base) {
101
99
  case "reassess-roadmap":
102
100
  return `${relSliceFile(base, mid, sid, "ASSESSMENT")} (roadmap reassessment)`;
103
101
  case "run-uat":
104
- return `${relSliceFile(base, mid, sid, "UAT-RESULT")} (UAT result)`;
102
+ return `${relSliceFile(base, mid, sid, "UAT")} (UAT result)`;
105
103
  case "validate-milestone":
106
104
  return `${relMilestoneFile(base, mid, "VALIDATION")} (milestone validation report)`;
107
105
  case "complete-milestone":
@@ -18,15 +18,16 @@ import { computeProgressScore } from "./progress-score.js";
18
18
  import { getActiveWorktreeName } from "./worktree-command.js";
19
19
  import { loadEffectiveGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
20
20
  import { resolveServiceTierIcon, getEffectiveServiceTier } from "./service-tier.js";
21
+ import { parseUnitId } from "./unit-id.js";
21
22
  // ─── UAT Slice Extraction ─────────────────────────────────────────────────────
22
23
  /**
23
24
  * Extract the target slice ID from a run-uat unit ID (e.g. "M001/S01" → "S01").
24
25
  * Returns null if the format doesn't match.
25
26
  */
26
27
  export function extractUatSliceId(unitId) {
27
- const parts = unitId.split("/");
28
- if (parts.length >= 2 && parts[1].startsWith("S"))
29
- return parts[1];
28
+ const { slice } = parseUnitId(unitId);
29
+ if (slice?.startsWith("S"))
30
+ return slice;
30
31
  return null;
31
32
  }
32
33
  // ─── Unit Description Helpers ─────────────────────────────────────────────────
@@ -115,6 +116,8 @@ export function describeNextUnit(state) {
115
116
  return { label: `Replan ${sid}: ${sTitle}`, description: "Blocker found — replan the slice." };
116
117
  case "completing-milestone":
117
118
  return { label: "Complete milestone", description: "Write milestone summary." };
119
+ case "evaluating-gates":
120
+ return { label: `Evaluate gates for ${sid}: ${sTitle}`, description: "Parallel quality gate assessment before execution." };
118
121
  default:
119
122
  return { label: "Continue", description: "Execute the next step." };
120
123
  }
@@ -8,13 +8,14 @@
8
8
  * data structure that is inspectable, testable per-rule, and extensible
9
9
  * without modifying orchestration code.
10
10
  */
11
- import { loadFile, loadActiveOverrides } from "./files.js";
12
- import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
11
+ import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
12
+ import { isDbAvailable, getMilestoneSlices, getPendingGates, markAllGatesOmitted } from "./gsd-db.js";
13
+ import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
13
14
  import { resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveTaskFile, relSliceFile, buildMilestoneFileName, } from "./paths.js";
14
15
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
15
16
  import { join } from "node:path";
16
17
  import { hasImplementationArtifacts } from "./auto-recovery.js";
17
- import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
18
+ import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
18
19
  function missingSliceStop(mid, phase) {
19
20
  return {
20
21
  action: "stop",
@@ -104,15 +105,15 @@ export const DISPATCH_RULES = [
104
105
  return null;
105
106
  }
106
107
  for (const sliceId of completedSliceIds) {
107
- const resultFile = resolveSliceFile(basePath, mid, sliceId, "UAT-RESULT");
108
+ const resultFile = resolveSliceFile(basePath, mid, sliceId, "UAT");
108
109
  if (!resultFile)
109
110
  continue;
110
111
  const content = await loadFile(resultFile);
111
112
  if (!content)
112
113
  continue;
113
- const verdictMatch = content.match(/verdict:\s*([\w-]+)/i);
114
- const verdict = verdictMatch?.[1]?.toLowerCase();
115
- if (verdict && verdict !== "pass" && verdict !== "passed") {
114
+ const verdict = extractVerdict(content);
115
+ const uatType = extractUatType(content);
116
+ if (verdict && !isAcceptableUatVerdict(verdict, uatType)) {
116
117
  return {
117
118
  action: "stop",
118
119
  reason: `UAT verdict for ${sliceId} is "${verdict}" — blocking progression until resolved.\nReview the UAT result and update the verdict to PASS, or re-run /gsd auto after fixing.`,
@@ -246,6 +247,32 @@ export const DISPATCH_RULES = [
246
247
  };
247
248
  },
248
249
  },
250
+ {
251
+ name: "evaluating-gates → gate-evaluate",
252
+ match: async ({ state, mid, midTitle, basePath, prefs }) => {
253
+ if (state.phase !== "evaluating-gates")
254
+ return null;
255
+ if (!state.activeSlice)
256
+ return missingSliceStop(mid, state.phase);
257
+ const sid = state.activeSlice.id;
258
+ const sTitle = state.activeSlice.title;
259
+ // Gate evaluation is opt-in via preferences
260
+ const gateConfig = prefs?.gate_evaluation;
261
+ if (!gateConfig?.enabled) {
262
+ markAllGatesOmitted(mid, sid);
263
+ return { action: "skip" };
264
+ }
265
+ const pending = getPendingGates(mid, sid, "slice");
266
+ if (pending.length === 0)
267
+ return { action: "skip" };
268
+ return {
269
+ action: "dispatch",
270
+ unitType: "gate-evaluate",
271
+ unitId: `${mid}/${sid}/gates+${pending.map(g => g.gate_id).join(",")}`,
272
+ prompt: await buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, basePath),
273
+ };
274
+ },
275
+ },
249
276
  {
250
277
  name: "replanning-slice → replan-slice",
251
278
  match: async ({ state, mid, midTitle, basePath }) => {
@@ -15,17 +15,27 @@ import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
15
15
  import { loadPrompt } from "./prompt-loader.js";
16
16
  import { resolveSliceFile, resolveTaskFile, resolveMilestoneFile, resolveTasksDir, buildTaskFileName, } from "./paths.js";
17
17
  import { invalidateAllCaches } from "./cache.js";
18
+ import { parseUnitId } from "./unit-id.js";
18
19
  import { closeoutUnit } from "./auto-unit-closeout.js";
19
20
  import { autoCommitCurrentBranch, } from "./worktree.js";
20
21
  import { verifyExpectedArtifact, resolveExpectedArtifactPath, } from "./auto-recovery.js";
21
22
  import { regenerateIfMissing } from "./workflow-projections.js";
22
- import { syncStateToProjectRoot } from "./auto-worktree-sync.js";
23
+ import { syncStateToProjectRoot } from "./auto-worktree.js";
23
24
  import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getAdapter } from "./gsd-db.js";
24
25
  import { renderPlanCheckboxes } from "./markdown-renderer.js";
25
26
  import { consumeSignal } from "./session-status-io.js";
26
27
  import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
27
28
  import { hasPendingCaptures, loadPendingCaptures } from "./captures.js";
28
29
  import { debugLog } from "./debug-logger.js";
30
+ /** Unit types that only touch `.gsd/` internal state files (no code changes).
31
+ * Auto-commit is skipped for these — their state files are picked up by the
32
+ * next actual task commit via `smartStage()`. */
33
+ const LIFECYCLE_ONLY_UNITS = new Set([
34
+ "research-milestone", "discuss-milestone", "plan-milestone",
35
+ "validate-milestone", "research-slice", "plan-slice",
36
+ "replan-slice", "complete-slice", "run-uat",
37
+ "reassess-roadmap", "rewrite-docs",
38
+ ]);
29
39
  import { existsSync, unlinkSync } from "node:fs";
30
40
  import { join } from "node:path";
31
41
  import { _resetHasChangesCache } from "./native-git-bridge.js";
@@ -38,13 +48,20 @@ import { _resetHasChangesCache } from "./native-git-bridge.js";
38
48
  * in postUnitPostVerification() eventually ingests rogue files, but explicit
39
49
  * detection provides immediate diagnostics so operators know the prompt failed.
40
50
  */
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ function hasNonEmptyFields(row, fields) {
53
+ if (!row)
54
+ return false;
55
+ return fields.some(f => String(row[f] || "").trim().length > 0);
56
+ }
57
+ const MILESTONE_PLANNING_FIELDS = ["title", "vision", "requirement_coverage", "boundary_map_markdown"];
58
+ const SLICE_PLANNING_FIELDS = ["title", "demo", "risk", "depends"];
41
59
  export function detectRogueFileWrites(unitType, unitId, basePath) {
42
60
  if (!isDbAvailable())
43
61
  return [];
44
- const parts = unitId.split("/");
62
+ const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
45
63
  const rogues = [];
46
64
  if (unitType === "execute-task") {
47
- const [mid, sid, tid] = parts;
48
65
  if (!mid || !sid || !tid)
49
66
  return [];
50
67
  const summaryPath = resolveTaskFile(basePath, mid, sid, tid, "SUMMARY");
@@ -56,7 +73,6 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
56
73
  }
57
74
  }
58
75
  else if (unitType === "complete-slice") {
59
- const [mid, sid] = parts;
60
76
  if (!mid || !sid)
61
77
  return [];
62
78
  const summaryPath = resolveSliceFile(basePath, mid, sid, "SUMMARY");
@@ -68,33 +84,25 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
68
84
  }
69
85
  }
70
86
  else if (unitType === "plan-milestone") {
71
- const [mid] = parts;
72
87
  if (!mid)
73
88
  return [];
74
89
  const roadmapPath = resolveMilestoneFile(basePath, mid, "ROADMAP");
75
90
  if (!roadmapPath || !existsSync(roadmapPath))
76
91
  return [];
77
92
  const dbRow = getMilestone(mid);
78
- const hasPlanningState = !!dbRow && (String(dbRow.title || "").trim().length > 0 ||
79
- String(dbRow.vision || "").trim().length > 0 ||
80
- String(dbRow.requirement_coverage || "").trim().length > 0 ||
81
- String(dbRow.boundary_map_markdown || "").trim().length > 0);
93
+ const hasPlanningState = hasNonEmptyFields(dbRow, MILESTONE_PLANNING_FIELDS);
82
94
  if (!hasPlanningState) {
83
95
  rogues.push({ path: roadmapPath, unitType, unitId });
84
96
  }
85
97
  }
86
98
  else if (unitType === "plan-slice" || unitType === "replan-slice") {
87
- const [mid, sid] = parts;
88
99
  if (!mid || !sid)
89
100
  return [];
90
101
  const planPath = resolveSliceFile(basePath, mid, sid, "PLAN");
91
102
  if (!planPath || !existsSync(planPath))
92
103
  return [];
93
104
  const dbRow = getSlice(mid, sid);
94
- const hasPlanningState = !!dbRow && (String(dbRow.title || "").trim().length > 0 ||
95
- String(dbRow.demo || "").trim().length > 0 ||
96
- String(dbRow.risk || "").trim().length > 0 ||
97
- String(dbRow.depends || "").trim().length > 0);
105
+ const hasPlanningState = hasNonEmptyFields(dbRow, SLICE_PLANNING_FIELDS);
98
106
  if (!hasPlanningState) {
99
107
  rogues.push({ path: planPath, unitType, unitId });
100
108
  }
@@ -105,7 +113,6 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
105
113
  }
106
114
  }
107
115
  else if (unitType === "reassess-roadmap") {
108
- const [mid, sid] = parts;
109
116
  if (!mid || !sid)
110
117
  return [];
111
118
  const assessPath = resolveSliceFile(basePath, mid, sid, "ASSESSMENT");
@@ -121,7 +128,6 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
121
128
  }
122
129
  }
123
130
  else if (unitType === "plan-task") {
124
- const [mid, sid, tid] = parts;
125
131
  if (!mid || !sid || !tid)
126
132
  return [];
127
133
  const taskPlanPath = resolveTaskFile(basePath, mid, sid, tid, "PLAN");
@@ -171,8 +177,7 @@ export async function postUnitPreVerification(pctx, opts) {
171
177
  try {
172
178
  let taskContext;
173
179
  if (s.currentUnit.type === "execute-task") {
174
- const parts = s.currentUnit.id.split("/");
175
- const [mid, sid, tid] = parts;
180
+ const { milestone: mid, slice: sid, task: tid } = parseUnitId(s.currentUnit.id);
176
181
  if (mid && sid && tid) {
177
182
  const summaryPath = resolveTaskFile(s.basePath, mid, sid, tid, "SUMMARY");
178
183
  if (summaryPath) {
@@ -210,9 +215,14 @@ export async function postUnitPreVerification(pctx, opts) {
210
215
  // code files only in the working tree where they are destroyed by
211
216
  // `git worktree remove --force` during teardown.
212
217
  _resetHasChangesCache();
213
- const commitMsg = autoCommitCurrentBranch(s.basePath, s.currentUnit.type, s.currentUnit.id, taskContext);
214
- if (commitMsg) {
215
- ctx.ui.notify(`Committed: ${commitMsg.split("\n")[0]}`, "info");
218
+ // Skip auto-commit for lifecycle-only units (#2553) they only touch
219
+ // `.gsd/` internal state files. Those files are picked up by the next
220
+ // actual task commit via smartStage().
221
+ if (!LIFECYCLE_ONLY_UNITS.has(s.currentUnit.type)) {
222
+ const commitMsg = autoCommitCurrentBranch(s.basePath, s.currentUnit.type, s.currentUnit.id, taskContext);
223
+ if (commitMsg) {
224
+ ctx.ui.notify(`Committed: ${commitMsg.split("\n")[0]}`, "info");
225
+ }
216
226
  }
217
227
  }
218
228
  catch (e) {
@@ -270,8 +280,7 @@ export async function postUnitPreVerification(pctx, opts) {
270
280
  // Reactive state cleanup on slice completion
271
281
  if (s.currentUnit.type === "complete-slice") {
272
282
  try {
273
- const parts = s.currentUnit.id.split("/");
274
- const [mid, sid] = parts;
283
+ const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
275
284
  if (mid && sid) {
276
285
  const { clearReactiveState } = await import("./reactive-graph.js");
277
286
  clearReactiveState(s.basePath, mid, sid);
@@ -342,8 +351,7 @@ export async function postUnitPreVerification(pctx, opts) {
342
351
  // from DB data before giving up (e.g. research-slice produces PLAN from engine).
343
352
  if (!triggerArtifactVerified) {
344
353
  try {
345
- const parts = s.currentUnit.id.split("/");
346
- const [mid, sid] = parts;
354
+ const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
347
355
  if (mid && sid) {
348
356
  const regenerated = regenerateIfMissing(s.basePath, mid, sid, "PLAN");
349
357
  if (regenerated) {
@@ -430,8 +438,7 @@ export async function postUnitPostVerification(pctx) {
430
438
  ctx.ui.notify(`Hook requested retry of ${trigger.unitType} ${trigger.unitId} — resetting task state.`, "info");
431
439
  // ── State reset: undo the completion so deriveState re-derives the unit ──
432
440
  try {
433
- const parts = trigger.unitId.split("/");
434
- const [mid, sid, tid] = parts;
441
+ const { milestone: mid, slice: sid, task: tid } = parseUnitId(trigger.unitId);
435
442
  // 1. Reset task status in DB and re-render plan checkboxes
436
443
  if (mid && sid && tid) {
437
444
  try {