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
@@ -0,0 +1,204 @@
1
+ /**
2
+ * worktree-sync-overwrite-loop.test.ts — Regression tests for #1886.
3
+ *
4
+ * Reproduces the infinite validate-milestone loop caused by two bugs
5
+ * in syncProjectRootToWorktree:
6
+ *
7
+ * 1. safeCopyRecursive overwrites worktree-authoritative files (e.g.
8
+ * VALIDATION.md written by validate-milestone gets clobbered by the
9
+ * stale project root copy that lacks the file).
10
+ *
11
+ * 2. completed-units.json is not forward-synced from project root to
12
+ * worktree, so the worktree never learns about already-completed units.
13
+ *
14
+ * Covers:
15
+ * - syncProjectRootToWorktree does NOT overwrite existing worktree files
16
+ * - syncProjectRootToWorktree copies files missing from the worktree
17
+ * - completed-units.json is forward-synced from project root to worktree
18
+ * - completed-units.json sync uses force:true (project root is authoritative)
19
+ */
20
+
21
+ import {
22
+ mkdtempSync,
23
+ mkdirSync,
24
+ writeFileSync,
25
+ rmSync,
26
+ existsSync,
27
+ readFileSync,
28
+ } from "node:fs";
29
+ import { join } from "node:path";
30
+ import { tmpdir } from "node:os";
31
+
32
+ import { syncProjectRootToWorktree } from "../auto-worktree.ts";
33
+ import { createTestContext } from "./test-helpers.ts";
34
+
35
+ const { assertTrue, assertEq, report } = createTestContext();
36
+
37
+ function createBase(name: string): string {
38
+ const base = mkdtempSync(join(tmpdir(), `gsd-wt-1886-${name}-`));
39
+ mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
40
+ return base;
41
+ }
42
+
43
+ function cleanup(base: string): void {
44
+ rmSync(base, { recursive: true, force: true });
45
+ }
46
+
47
+ async function main(): Promise<void> {
48
+ // ─── 1. Worktree VALIDATION.md must NOT be overwritten by project root ──
49
+ console.log(
50
+ "\n=== 1. #1886: worktree VALIDATION.md preserved (not overwritten) ===",
51
+ );
52
+ {
53
+ const mainBase = createBase("main");
54
+ const wtBase = createBase("wt");
55
+
56
+ try {
57
+ // Project root has an older CONTEXT but no VALIDATION
58
+ const prM004 = join(mainBase, ".gsd", "milestones", "M004");
59
+ mkdirSync(prM004, { recursive: true });
60
+ writeFileSync(join(prM004, "M004-CONTEXT.md"), "# old context");
61
+
62
+ // Worktree has CONTEXT + VALIDATION (written by validate-milestone)
63
+ const wtM004 = join(wtBase, ".gsd", "milestones", "M004");
64
+ mkdirSync(wtM004, { recursive: true });
65
+ writeFileSync(join(wtM004, "M004-CONTEXT.md"), "# worktree context");
66
+ writeFileSync(
67
+ join(wtM004, "M004-VALIDATION.md"),
68
+ "verdict: pass\nremediation_round: 1",
69
+ );
70
+
71
+ syncProjectRootToWorktree(mainBase, wtBase, "M004");
72
+
73
+ // VALIDATION.md must still exist in worktree
74
+ assertTrue(
75
+ existsSync(join(wtM004, "M004-VALIDATION.md")),
76
+ "#1886: VALIDATION.md still exists after sync",
77
+ );
78
+ assertEq(
79
+ readFileSync(join(wtM004, "M004-VALIDATION.md"), "utf-8"),
80
+ "verdict: pass\nremediation_round: 1",
81
+ "#1886: VALIDATION.md content preserved",
82
+ );
83
+
84
+ // CONTEXT.md should NOT be overwritten — worktree version is authoritative
85
+ assertEq(
86
+ readFileSync(join(wtM004, "M004-CONTEXT.md"), "utf-8"),
87
+ "# worktree context",
88
+ "#1886: existing worktree CONTEXT.md not overwritten",
89
+ );
90
+ } finally {
91
+ cleanup(mainBase);
92
+ cleanup(wtBase);
93
+ }
94
+ }
95
+
96
+ // ─── 2. Missing files ARE still copied from project root ────────────────
97
+ console.log("\n=== 2. #1886: missing worktree files still copied ===");
98
+ {
99
+ const mainBase = createBase("main");
100
+ const wtBase = createBase("wt");
101
+
102
+ try {
103
+ const prM004 = join(mainBase, ".gsd", "milestones", "M004");
104
+ mkdirSync(prM004, { recursive: true });
105
+ writeFileSync(join(prM004, "M004-CONTEXT.md"), "# from project root");
106
+ writeFileSync(join(prM004, "M004-ROADMAP.md"), "# roadmap");
107
+
108
+ // Worktree has no M004 directory at all
109
+ syncProjectRootToWorktree(mainBase, wtBase, "M004");
110
+
111
+ assertTrue(
112
+ existsSync(join(wtBase, ".gsd", "milestones", "M004", "M004-CONTEXT.md")),
113
+ "#1886: missing CONTEXT.md copied from project root",
114
+ );
115
+ assertTrue(
116
+ existsSync(join(wtBase, ".gsd", "milestones", "M004", "M004-ROADMAP.md")),
117
+ "#1886: missing ROADMAP.md copied from project root",
118
+ );
119
+ } finally {
120
+ cleanup(mainBase);
121
+ cleanup(wtBase);
122
+ }
123
+ }
124
+
125
+ // ─── 3. completed-units.json forward-synced from project root ───────────
126
+ console.log(
127
+ "\n=== 3. #1886: completed-units.json forward-synced to worktree ===",
128
+ );
129
+ {
130
+ const mainBase = createBase("main");
131
+ const wtBase = createBase("wt");
132
+
133
+ try {
134
+ // Project root has completed units (authoritative after crash recovery)
135
+ writeFileSync(
136
+ join(mainBase, ".gsd", "completed-units.json"),
137
+ JSON.stringify(["validate-milestone/M004"]),
138
+ );
139
+
140
+ // Worktree has empty completed-units
141
+ writeFileSync(
142
+ join(wtBase, ".gsd", "completed-units.json"),
143
+ JSON.stringify([]),
144
+ );
145
+
146
+ syncProjectRootToWorktree(mainBase, wtBase, "M004");
147
+
148
+ const wtCompleted = JSON.parse(
149
+ readFileSync(join(wtBase, ".gsd", "completed-units.json"), "utf-8"),
150
+ );
151
+ assertEq(
152
+ wtCompleted,
153
+ ["validate-milestone/M004"],
154
+ "#1886: completed-units.json synced from project root (force:true)",
155
+ );
156
+ } finally {
157
+ cleanup(mainBase);
158
+ cleanup(wtBase);
159
+ }
160
+ }
161
+
162
+ // ─── 4. completed-units.json: no-op when project root has no file ───────
163
+ console.log(
164
+ "\n=== 4. #1886: completed-units.json no-op when missing in project root ===",
165
+ );
166
+ {
167
+ const mainBase = createBase("main");
168
+ const wtBase = createBase("wt");
169
+
170
+ try {
171
+ // Project root milestone dir must exist for sync to run
172
+ const prM004 = join(mainBase, ".gsd", "milestones", "M004");
173
+ mkdirSync(prM004, { recursive: true });
174
+
175
+ // No completed-units.json in project root
176
+ // Worktree has its own
177
+ writeFileSync(
178
+ join(wtBase, ".gsd", "completed-units.json"),
179
+ JSON.stringify(["some-unit/M001"]),
180
+ );
181
+
182
+ syncProjectRootToWorktree(mainBase, wtBase, "M004");
183
+
184
+ const wtCompleted = JSON.parse(
185
+ readFileSync(join(wtBase, ".gsd", "completed-units.json"), "utf-8"),
186
+ );
187
+ assertEq(
188
+ wtCompleted,
189
+ ["some-unit/M001"],
190
+ "#1886: worktree completed-units.json untouched when project root has none",
191
+ );
192
+ } finally {
193
+ cleanup(mainBase);
194
+ cleanup(wtBase);
195
+ }
196
+ }
197
+
198
+ report();
199
+ }
200
+
201
+ main().catch((error) => {
202
+ console.error(error);
203
+ process.exit(1);
204
+ });
@@ -6,8 +6,10 @@ import {
6
6
  insertTask,
7
7
  upsertSlicePlanning,
8
8
  upsertTaskPlanning,
9
+ insertGateRow,
9
10
  _getAdapter,
10
11
  } from "../gsd-db.js";
12
+ import type { GateId } from "../types.js";
11
13
  import { invalidateStateCache } from "../state.js";
12
14
  import { renderPlanFromDb } from "../markdown-renderer.js";
13
15
  import { renderAllProjections } from "../workflow-projections.js";
@@ -190,6 +192,20 @@ export async function handlePlanSlice(
190
192
  fullPlanMd: task.fullPlanMd,
191
193
  });
192
194
  }
195
+
196
+ // Seed quality gate rows inside the transaction — all-or-nothing with
197
+ // the plan data so a crash can't leave orphaned gates without tasks.
198
+ const sliceGates: GateId[] = ["Q3", "Q4"];
199
+ for (const gid of sliceGates) {
200
+ insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: gid, scope: "slice" });
201
+ }
202
+ const taskGates: GateId[] = ["Q5", "Q6", "Q7"];
203
+ for (const task of params.tasks) {
204
+ for (const gid of taskGates) {
205
+ insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: gid, scope: "task", taskId: task.taskId });
206
+ }
207
+ }
208
+ insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: "Q8", scope: "slice" });
193
209
  });
194
210
  } catch (err) {
195
211
  return { error: `db write failed: ${(err as Error).message}` };
@@ -14,6 +14,7 @@ import {
14
14
  import { resolveMilestonePath, clearPathCache } from "../paths.js";
15
15
  import { saveFile, clearParseCache } from "../files.js";
16
16
  import { invalidateStateCache } from "../state.js";
17
+ import { VALIDATION_VERDICTS, isValidMilestoneVerdict } from "../verdict-parser.js";
17
18
 
18
19
  export interface ValidateMilestoneParams {
19
20
  milestoneId: string;
@@ -71,9 +72,8 @@ export async function handleValidateMilestone(
71
72
  if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
72
73
  return { error: "milestoneId is required and must be a non-empty string" };
73
74
  }
74
- const validVerdicts = ["pass", "needs-attention", "needs-remediation"];
75
- if (!validVerdicts.includes(params.verdict)) {
76
- return { error: `verdict must be one of: ${validVerdicts.join(", ")}` };
75
+ if (!isValidMilestoneVerdict(params.verdict)) {
76
+ return { error: `verdict must be one of: ${VALIDATION_VERDICTS.join(", ")}` };
77
77
  }
78
78
 
79
79
  // ── Filesystem render ──────────────────────────────────────────────────
@@ -11,6 +11,7 @@ export type Phase =
11
11
  | "discussing"
12
12
  | "researching"
13
13
  | "planning"
14
+ | "evaluating-gates"
14
15
  | "executing"
15
16
  | "verifying"
16
17
  | "summarizing"
@@ -557,3 +558,32 @@ export interface CompleteSliceParams {
557
558
  /** Optional caller-provided reason this action was triggered */
558
559
  triggerReason?: string;
559
560
  }
561
+
562
+ // ─── Quality Gates ───────────────────────────────────────────────────────
563
+
564
+ export type GateId = "Q3" | "Q4" | "Q5" | "Q6" | "Q7" | "Q8";
565
+ export type GateScope = "slice" | "task";
566
+ export type GateStatus = "pending" | "complete" | "omitted";
567
+ export type GateVerdict = "pass" | "flag" | "omitted" | "";
568
+
569
+ export interface GateRow {
570
+ milestone_id: string;
571
+ slice_id: string;
572
+ gate_id: GateId;
573
+ scope: GateScope;
574
+ task_id: string;
575
+ status: GateStatus;
576
+ verdict: GateVerdict;
577
+ rationale: string;
578
+ findings: string;
579
+ evaluated_at: string | null;
580
+ }
581
+
582
+ /** Configuration for parallel quality gate evaluation during slice planning. */
583
+ export interface GateEvaluationConfig {
584
+ enabled: boolean;
585
+ /** Which slice-scoped gates to evaluate in parallel. Default: ['Q3', 'Q4']. */
586
+ slice_gates?: string[];
587
+ /** Whether to evaluate task-level gates (Q5/Q6/Q7) via reactive-execute. Default: true when enabled. */
588
+ task_gates?: boolean;
589
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Centralized verdict extraction, normalization, and schema validation.
3
+ *
4
+ * All verdict-related logic lives here so that normalization rules
5
+ * (e.g. `passed` → `pass`) are applied consistently across the codebase.
6
+ */
7
+
8
+ import { extractUatType } from "./files.js";
9
+ import type { UatType } from "./files.js";
10
+
11
+ // ── Verdict extraction ──────────────────────────────────────────────────
12
+
13
+ /**
14
+ * Extract and normalize the `verdict` value from YAML frontmatter.
15
+ *
16
+ * Normalization:
17
+ * - lowercased
18
+ * - `passed` → `pass`
19
+ *
20
+ * Returns `undefined` when frontmatter is absent or has no `verdict` field.
21
+ */
22
+ export function extractVerdict(content: string): string | undefined {
23
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
24
+ if (!fmMatch) return undefined;
25
+ const verdictMatch = fmMatch[1].match(/verdict:\s*([\w-]+)/i);
26
+ if (!verdictMatch) return undefined;
27
+ let v = verdictMatch[1].toLowerCase();
28
+ if (v === "passed") v = "pass";
29
+ return v;
30
+ }
31
+
32
+ /**
33
+ * Returns `true` when the content's frontmatter contains a `verdict` field.
34
+ */
35
+ export function hasVerdict(content: string): boolean {
36
+ return /verdict:\s*[\w-]+/i.test(content);
37
+ }
38
+
39
+ // ── UAT verdict schema ──────────────────────────────────────────────────
40
+
41
+ /**
42
+ * Base verdicts that are always acceptable for UAT results.
43
+ */
44
+ export const UAT_ACCEPTABLE_VERDICTS: readonly string[] = ["pass", "passed"];
45
+
46
+ /**
47
+ * UAT types whose results may legitimately produce a `partial` verdict
48
+ * when all automatable checks pass but human-only checks remain.
49
+ */
50
+ const PARTIAL_ELIGIBLE_UAT_TYPES: readonly UatType[] = [
51
+ "mixed",
52
+ "human-experience",
53
+ "live-runtime",
54
+ ];
55
+
56
+ /**
57
+ * Check whether a verdict is acceptable for a given UAT type.
58
+ *
59
+ * `pass` / `passed` are always acceptable. `partial` is acceptable only for
60
+ * UAT types that include non-automatable human checks.
61
+ */
62
+ export function isAcceptableUatVerdict(verdict: string, uatType: UatType | undefined): boolean {
63
+ if (UAT_ACCEPTABLE_VERDICTS.includes(verdict)) return true;
64
+ if (verdict === "partial" && uatType && (PARTIAL_ELIGIBLE_UAT_TYPES as readonly string[]).includes(uatType)) {
65
+ return true;
66
+ }
67
+ return false;
68
+ }
69
+
70
+ // ── Milestone validation verdict schema ─────────────────────────────────
71
+
72
+ /**
73
+ * Valid verdicts for the `validate-milestone` tool.
74
+ */
75
+ export const VALIDATION_VERDICTS = ["pass", "needs-attention", "needs-remediation"] as const;
76
+ export type ValidationVerdict = (typeof VALIDATION_VERDICTS)[number];
77
+
78
+ /**
79
+ * Check whether a string is a valid milestone validation verdict.
80
+ */
81
+ export function isValidMilestoneVerdict(verdict: string): verdict is ValidationVerdict {
82
+ return (VALIDATION_VERDICTS as readonly string[]).includes(verdict);
83
+ }
84
+
85
+ // ── UAT type helper ─────────────────────────────────────────────────────
86
+
87
+ /**
88
+ * Extract the UAT type from content, defaulting to `"artifact-driven"`.
89
+ *
90
+ * The `"artifact-driven"` fallback is the original default used throughout
91
+ * the codebase when a UAT file lacks an explicit `## UAT Type` section.
92
+ */
93
+ export function getUatType(content: string): UatType {
94
+ return extractUatType(content) ?? "artifact-driven";
95
+ }
@@ -220,8 +220,6 @@ function sanitizeCommand(cmd: string): string | null {
220
220
  }
221
221
 
222
222
  export interface RunVerificationGateOptions {
223
- basePath: string;
224
- unitId: string;
225
223
  cwd: string;
226
224
  preferenceCommands?: string[];
227
225
  taskPlanVerify?: string;
@@ -661,7 +661,7 @@ async function handleMerge(
661
661
  // --- Deterministic merge path (preferred) ---
662
662
  // Try a direct squash-merge first. Only fall back to LLM on conflict.
663
663
  const commitType = inferCommitType(name);
664
- const commitMessage = `${commitType}(${name}): merge worktree ${name}`;
664
+ const commitMessage = `${commitType}: merge worktree ${name}\n\nGSD-Worktree: ${name}`;
665
665
 
666
666
  // Reconcile worktree DB into main DB before squash merge
667
667
  const wtDbPath = join(worktreePath(basePath, name), ".gsd", "gsd.db");
@@ -150,6 +150,18 @@ export class WorktreeResolver {
150
150
  */
151
151
  enterMilestone(milestoneId: string, ctx: NotifyCtx): void {
152
152
  this.validateMilestoneId(milestoneId);
153
+
154
+ // If worktree creation failed earlier this session, skip all future attempts
155
+ if (this.s.isolationDegraded) {
156
+ debugLog("WorktreeResolver", {
157
+ action: "enterMilestone",
158
+ milestoneId,
159
+ skipped: true,
160
+ reason: "isolation-degraded",
161
+ });
162
+ return;
163
+ }
164
+
153
165
  if (!this.deps.shouldUseWorktreeIsolation()) {
154
166
  debugLog("WorktreeResolver", {
155
167
  action: "enterMilestone",
@@ -220,6 +232,9 @@ export class WorktreeResolver {
220
232
  `Auto-worktree creation for ${milestoneId} failed: ${msg}. Continuing in project root.`,
221
233
  "warning",
222
234
  );
235
+ // Degrade isolation for the rest of this session so mergeAndExit
236
+ // doesn't try to merge a nonexistent worktree branch (#2483)
237
+ this.s.isolationDegraded = true;
223
238
  // Do NOT update s.basePath — stay in project root
224
239
  }
225
240
  }
@@ -304,6 +319,22 @@ export class WorktreeResolver {
304
319
  */
305
320
  mergeAndExit(milestoneId: string, ctx: NotifyCtx): void {
306
321
  this.validateMilestoneId(milestoneId);
322
+
323
+ // If worktree creation failed earlier, skip merge — work is on current branch (#2483)
324
+ if (this.s.isolationDegraded) {
325
+ debugLog("WorktreeResolver", {
326
+ action: "mergeAndExit",
327
+ milestoneId,
328
+ skipped: true,
329
+ reason: "isolation-degraded",
330
+ });
331
+ ctx.notify(
332
+ `Skipping worktree merge for ${milestoneId} — isolation was degraded (worktree creation failed earlier). Work is on the current branch.`,
333
+ "info",
334
+ );
335
+ return;
336
+ }
337
+
307
338
  const mode = this.deps.getIsolationMode();
308
339
  debugLog("WorktreeResolver", {
309
340
  action: "mergeAndExit",
@@ -235,8 +235,9 @@ export function getSliceBranchName(milestoneId: string, sliceId: string, worktre
235
235
  return `gsd/${milestoneId}/${sliceId}`;
236
236
  }
237
237
 
238
- /** Regex that matches both plain and worktree-namespaced slice branches. */
239
- export const SLICE_BRANCH_RE = /^gsd\/(?:([a-zA-Z0-9_-]+)\/)?(M\d+(?:-[a-z0-9]{6})?)\/(S\d+)$/;
238
+ /** Re-export for backward compatibility canonical definition in branch-patterns.ts */
239
+ export { SLICE_BRANCH_RE } from "./branch-patterns.js";
240
+ import { SLICE_BRANCH_RE } from "./branch-patterns.js";
240
241
 
241
242
  /**
242
243
  * Parse a slice branch name into its components.
@@ -2,7 +2,7 @@
2
2
  * Remote Questions — configuration resolution and validation
3
3
  */
4
4
 
5
- import { join } from "node:path";
5
+ import { AuthStorage } from "@gsd/pi-coding-agent";
6
6
  import { loadEffectiveGSDPreferences, type RemoteQuestionsConfig } from "../gsd/preferences.js";
7
7
  import type { RemoteChannel } from "./types.js";
8
8
 
@@ -54,9 +54,7 @@ function hydrateRemoteTokensFromAuth(): void {
54
54
  if (needed.length === 0) return;
55
55
 
56
56
  try {
57
- const { AuthStorage } = require("@gsd/pi-coding-agent") as typeof import("@gsd/pi-coding-agent");
58
- const authPath = join(process.env.HOME ?? "~", ".gsd", "agent", "auth.json");
59
- const auth = AuthStorage.create(authPath);
57
+ const auth = AuthStorage.create();
60
58
 
61
59
  for (const [providerId, envVar] of needed) {
62
60
  try {
@@ -72,7 +70,7 @@ function hydrateRemoteTokensFromAuth(): void {
72
70
  }
73
71
  }
74
72
  } catch {
75
- // AuthStorage unavailable (unit tests, stripped build) — skip silently.
73
+ // AuthStorage unavailable or auth.json missing/unreadable — skip silently.
76
74
  }
77
75
  }
78
76
 
@@ -176,11 +176,15 @@ export function registerNativeSearchHooks(pi: NativeSearchPI): { getIsAnthropic:
176
176
  );
177
177
  payload.tools = tools;
178
178
 
179
- // ── Session-level search budget (#1309) ──────────────────────────────
179
+ // ── Session-level search budget (#1309, #compaction-safe) ─────────────
180
180
  // Count web_search_tool_result blocks in the conversation history to
181
181
  // determine how many native searches have already been used this session.
182
182
  // The Anthropic API's max_uses resets per request, so without this guard,
183
183
  // pause_turn → resubmit cycles allow unlimited total searches.
184
+ //
185
+ // Use the monotonic high-water mark: take the max of the history count
186
+ // and the running counter. This prevents budget resets when context
187
+ // compaction removes web_search_tool_result blocks from history.
184
188
  if (Array.isArray(messages)) {
185
189
  let historySearchCount = 0;
186
190
  for (const msg of messages) {
@@ -192,8 +196,9 @@ export function registerNativeSearchHooks(pi: NativeSearchPI): { getIsAnthropic:
192
196
  }
193
197
  }
194
198
  }
195
- // Sync counter from history (handles session restore / context replay)
196
- sessionSearchCount = historySearchCount;
199
+ // High-water mark: never decrease the counter, even if compaction
200
+ // removes web_search_tool_result blocks from the visible history.
201
+ sessionSearchCount = Math.max(sessionSearchCount, historySearchCount);
197
202
  }
198
203
 
199
204
  const remaining = Math.max(0, MAX_NATIVE_SEARCHES_PER_SESSION - sessionSearchCount);
@@ -106,14 +106,20 @@ searchCache.startPurgeInterval(60_000);
106
106
 
107
107
  // Consecutive duplicate search guard (#949)
108
108
  // Tracks recent query keys to detect and break search loops.
109
- const MAX_CONSECUTIVE_DUPES = 3;
109
+ const MAX_CONSECUTIVE_DUPES = 1;
110
110
  let lastSearchKey = "";
111
111
  let consecutiveDupeCount = 0;
112
112
 
113
- /** Reset session-scoped duplicate-search guard state. */
113
+ // Session-level total search budget (all queries, not just duplicates).
114
+ // Prevents unbounded search accumulation across varied queries.
115
+ const MAX_SEARCHES_PER_SESSION = 15;
116
+ let sessionTotalSearches = 0;
117
+
118
+ /** Reset session-scoped search guard state (both duplicate and budget). */
114
119
  export function resetSearchLoopGuardState(): void {
115
120
  lastSearchKey = "";
116
121
  consecutiveDupeCount = 0;
122
+ sessionTotalSearches = 0;
117
123
  }
118
124
 
119
125
  // Summarizer responses: max 50 entries, 15-minute TTL
@@ -357,6 +363,17 @@ export function registerSearchTool(pi: ExtensionAPI) {
357
363
  };
358
364
  }
359
365
 
366
+ // ------------------------------------------------------------------
367
+ // Session-level search budget
368
+ // ------------------------------------------------------------------
369
+ if (sessionTotalSearches >= MAX_SEARCHES_PER_SESSION) {
370
+ return {
371
+ content: [{ type: "text" as const, text: `⚠️ Search budget exhausted: ${sessionTotalSearches}/${MAX_SEARCHES_PER_SESSION} searches used this session. The information you need should already be in previous search results. Stop searching and use those results to proceed with your task.` }],
372
+ isError: true,
373
+ details: { errorKind: "budget_exhausted", error: `Session search budget exhausted (${MAX_SEARCHES_PER_SESSION})` } satisfies Partial<SearchDetails>,
374
+ };
375
+ }
376
+
360
377
  const count = params.count ?? 5;
361
378
  const wantSummary = params.summary ?? false;
362
379
 
@@ -410,6 +427,9 @@ export function registerSearchTool(pi: ExtensionAPI) {
410
427
  consecutiveDupeCount = 1;
411
428
  }
412
429
 
430
+ // Count every search that passes the guards toward the session budget.
431
+ sessionTotalSearches++;
432
+
413
433
  const cached = searchCache.get(cacheKey);
414
434
 
415
435
  if (cached) {
@@ -103,9 +103,12 @@ gh issue list -R gsd-build/gsd-2
103
103
  gh issue list -R gsd-build/gsd-2 --label "priority:p1" --state open
104
104
 
105
105
  # Create issue with labels and milestone
106
+ # NOTE: Do NOT use labels for issue classification (bug, feature, etc.)
107
+ # Use labels for metadata (priority, status, auto-generated) only.
108
+ # Issue classification uses GitHub Issue Types, set via GraphQL after creation.
106
109
  gh issue create -R gsd-build/gsd-2 \
107
110
  --title "feat: add feature X" \
108
- --label "priority:p1" --label "type:feature" \
111
+ --label "priority:p1" \
109
112
  --milestone "v1.0"
110
113
 
111
114
  # View issue
@@ -120,6 +123,24 @@ gh issue edit <number> -R gsd-build/gsd-2 \
120
123
  --remove-label "status:needs-grooming"
121
124
  ```
122
125
 
126
+ ### Issue Types (Classification)
127
+
128
+ `gh issue create` has no `--type` flag. Issue types (Bug, Feature Request, etc.) are set via GraphQL after creation:
129
+
130
+ ```bash
131
+ # Step 1: Create the issue (returns URL)
132
+ ISSUE_URL=$(gh issue create -R gsd-build/gsd-2 \
133
+ --title "..." --body "...")
134
+
135
+ # Step 2: Set the issue type via GraphQL
136
+ ISSUE_NUM=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')
137
+ ISSUE_ID=$(gh api graphql -f query='{ repository(owner:"gsd-build",name:"gsd-2") { issue(number:'"$ISSUE_NUM"') { id } } }' --jq '.data.repository.issue.id')
138
+ TYPE_ID=$(gh api graphql -f query='{ repository(owner:"gsd-build",name:"gsd-2") { issueTypes(first:20) { nodes { id name } } } }' --jq '.data.repository.issueTypes.nodes[] | select(.name=="Bug") | .id')
139
+ gh api graphql -f query='mutation { updateIssue(input:{id:"'"$ISSUE_ID"'",issueTypeId:"'"$TYPE_ID"'"}) { issue { number } } }'
140
+ ```
141
+
142
+ Replace `"Bug"` with the appropriate type name (`"Feature Request"`, `"Task"`, etc.).
143
+
123
144
  ### Labels
124
145
 
125
146
  ```bash