gsd-pi 2.64.0-dev.f8aad9b → 2.65.0-dev.16e10d7

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 (473) hide show
  1. package/dist/headless.js +3 -1
  2. package/dist/mcp-server.js +6 -2
  3. package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +22 -7
  4. package/dist/resources/extensions/bg-shell/process-manager.js +6 -1
  5. package/dist/resources/extensions/browser-tools/capture.js +20 -1
  6. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +94 -8
  9. package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
  10. package/dist/resources/extensions/gsd/auto-post-unit.js +115 -7
  11. package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
  12. package/dist/resources/extensions/gsd/auto-recovery.js +12 -8
  13. package/dist/resources/extensions/gsd/auto-start.js +35 -1
  14. package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
  15. package/dist/resources/extensions/gsd/auto-verification.js +138 -1
  16. package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
  17. package/dist/resources/extensions/gsd/auto.js +2 -2
  18. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +34 -13
  20. package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -0
  21. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
  22. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +12 -1
  24. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +16 -0
  25. package/dist/resources/extensions/gsd/bootstrap/system-context.js +20 -0
  26. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  27. package/dist/resources/extensions/gsd/commands/context.js +8 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +21 -0
  29. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +104 -0
  30. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  31. package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
  32. package/dist/resources/extensions/gsd/config-overlay.js +312 -0
  33. package/dist/resources/extensions/gsd/detection.js +1 -1
  34. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
  35. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  36. package/dist/resources/extensions/gsd/doctor.js +2 -1
  37. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  38. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  39. package/dist/resources/extensions/gsd/guided-flow.js +220 -29
  40. package/dist/resources/extensions/gsd/md-importer.js +14 -7
  41. package/dist/resources/extensions/gsd/notification-overlay.js +256 -0
  42. package/dist/resources/extensions/gsd/notification-store.js +273 -0
  43. package/dist/resources/extensions/gsd/notification-widget.js +56 -0
  44. package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
  45. package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
  46. package/dist/resources/extensions/gsd/pre-execution-checks.js +471 -0
  47. package/dist/resources/extensions/gsd/preferences-types.js +7 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +78 -1
  49. package/dist/resources/extensions/gsd/preferences.js +13 -2
  50. package/dist/resources/extensions/gsd/preparation.js +1092 -0
  51. package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
  52. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  53. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  55. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  56. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  57. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  58. package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
  59. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  60. package/dist/resources/extensions/gsd/quick.js +19 -15
  61. package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
  62. package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
  63. package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
  64. package/dist/resources/extensions/gsd/session-lock.js +23 -1
  65. package/dist/resources/extensions/gsd/state.js +100 -12
  66. package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  67. package/dist/resources/extensions/gsd/tools/complete-slice.js +12 -3
  68. package/dist/resources/extensions/gsd/tools/complete-task.js +16 -4
  69. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
  70. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
  71. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
  72. package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
  73. package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
  74. package/dist/resources/extensions/gsd/triage-resolution.js +25 -9
  75. package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
  76. package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
  77. package/dist/resources/extensions/gsd/workflow-projections.js +4 -7
  78. package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -4
  79. package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
  80. package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
  81. package/dist/resources/extensions/gsd/worktree.js +9 -0
  82. package/dist/resources/extensions/shared/interview-ui.js +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
  85. package/dist/web/standalone/.next/build-manifest.json +3 -3
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  88. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  89. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  90. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/api/notifications/route.js +3 -0
  106. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -0
  107. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -0
  108. package/dist/web/standalone/.next/server/app/index.html +1 -1
  109. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
  116. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  117. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  120. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  121. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  122. package/dist/web/standalone/.next/static/Z3TgDP0c7kG9j8CVQVGcl/_buildManifest.js +1 -0
  123. package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
  124. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -0
  125. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-8805a20e15762c3c.js +1 -0
  126. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-8805a20e15762c3c.js +1 -0
  127. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-8805a20e15762c3c.js +1 -0
  128. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-8805a20e15762c3c.js +1 -0
  129. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-8805a20e15762c3c.js +1 -0
  130. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-8805a20e15762c3c.js +1 -0
  131. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-8805a20e15762c3c.js +1 -0
  132. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-8805a20e15762c3c.js +1 -0
  133. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-8805a20e15762c3c.js +1 -0
  134. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-8805a20e15762c3c.js +1 -0
  135. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-8805a20e15762c3c.js +1 -0
  136. package/dist/web/standalone/.next/static/chunks/app/api/files/route-8805a20e15762c3c.js +1 -0
  137. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-8805a20e15762c3c.js +1 -0
  138. package/dist/web/standalone/.next/static/chunks/app/api/git/route-8805a20e15762c3c.js +1 -0
  139. package/dist/web/standalone/.next/static/chunks/app/api/history/route-8805a20e15762c3c.js +1 -0
  140. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-8805a20e15762c3c.js +1 -0
  141. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-8805a20e15762c3c.js +1 -0
  142. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-8805a20e15762c3c.js +1 -0
  143. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-8805a20e15762c3c.js +1 -0
  144. package/dist/web/standalone/.next/static/chunks/app/api/notifications/route-8805a20e15762c3c.js +1 -0
  145. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-8805a20e15762c3c.js +1 -0
  146. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-8805a20e15762c3c.js +1 -0
  147. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-8805a20e15762c3c.js +1 -0
  148. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-8805a20e15762c3c.js +1 -0
  149. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-8805a20e15762c3c.js +1 -0
  150. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-8805a20e15762c3c.js +1 -0
  151. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-8805a20e15762c3c.js +1 -0
  152. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-8805a20e15762c3c.js +1 -0
  153. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-8805a20e15762c3c.js +1 -0
  154. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-8805a20e15762c3c.js +1 -0
  155. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-8805a20e15762c3c.js +1 -0
  156. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-8805a20e15762c3c.js +1 -0
  157. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-8805a20e15762c3c.js +1 -0
  158. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-8805a20e15762c3c.js +1 -0
  159. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-8805a20e15762c3c.js +1 -0
  160. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-8805a20e15762c3c.js +1 -0
  161. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-8805a20e15762c3c.js +1 -0
  162. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-8805a20e15762c3c.js +1 -0
  163. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-8805a20e15762c3c.js +1 -0
  164. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-8805a20e15762c3c.js +1 -0
  165. package/dist/web/standalone/.next/static/chunks/app/api/update/route-8805a20e15762c3c.js +1 -0
  166. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-8805a20e15762c3c.js +1 -0
  167. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-8805a20e15762c3c.js +1 -0
  168. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-8805a20e15762c3c.js +1 -0
  169. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
  170. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
  171. package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
  172. package/package.json +1 -1
  173. package/packages/pi-agent-core/dist/agent-loop.js +26 -9
  174. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  175. package/packages/pi-agent-core/src/agent-loop.test.ts +100 -4
  176. package/packages/pi-agent-core/src/agent-loop.ts +43 -12
  177. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts +2 -0
  178. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts.map +1 -0
  179. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +38 -0
  180. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -0
  181. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -0
  183. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts +2 -0
  185. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts.map +1 -0
  186. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +24 -0
  187. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -0
  188. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/resource-loader.js +4 -1
  190. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
  193. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
  195. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
  197. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
  199. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  200. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
  201. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  202. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  203. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  204. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +28 -5
  205. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  206. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
  207. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -0
  209. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
  211. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +40 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  214. package/packages/pi-coding-agent/package.json +1 -1
  215. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +64 -0
  216. package/packages/pi-coding-agent/src/core/agent-session.ts +10 -0
  217. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +42 -0
  218. package/packages/pi-coding-agent/src/core/resource-loader.ts +5 -1
  219. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
  220. package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
  221. package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
  222. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
  223. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +29 -4
  224. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
  225. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
  226. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +38 -0
  227. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts +2 -0
  228. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts.map +1 -0
  229. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +66 -0
  230. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -0
  231. package/packages/pi-tui/dist/components/image.d.ts +2 -0
  232. package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
  233. package/packages/pi-tui/dist/components/image.js +4 -0
  234. package/packages/pi-tui/dist/components/image.js.map +1 -1
  235. package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
  236. package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
  237. package/packages/pi-tui/dist/components/image.test.js +32 -0
  238. package/packages/pi-tui/dist/components/image.test.js.map +1 -0
  239. package/packages/pi-tui/dist/components/loader.d.ts +4 -2
  240. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  241. package/packages/pi-tui/dist/components/loader.js +27 -9
  242. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  243. package/packages/pi-tui/dist/components/text.d.ts.map +1 -1
  244. package/packages/pi-tui/dist/components/text.js +2 -0
  245. package/packages/pi-tui/dist/components/text.js.map +1 -1
  246. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
  247. package/packages/pi-tui/dist/overlay-layout.js +12 -1
  248. package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
  249. package/packages/pi-tui/dist/tui.d.ts +4 -0
  250. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  251. package/packages/pi-tui/dist/tui.js +35 -0
  252. package/packages/pi-tui/dist/tui.js.map +1 -1
  253. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +82 -0
  254. package/packages/pi-tui/src/components/image.test.ts +36 -0
  255. package/packages/pi-tui/src/components/image.ts +5 -0
  256. package/packages/pi-tui/src/components/loader.ts +27 -10
  257. package/packages/pi-tui/src/components/text.ts +1 -0
  258. package/packages/pi-tui/src/overlay-layout.ts +13 -1
  259. package/packages/pi-tui/src/tui.ts +34 -0
  260. package/pkg/package.json +1 -1
  261. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +19 -7
  262. package/src/resources/extensions/bg-shell/process-manager.ts +8 -2
  263. package/src/resources/extensions/browser-tools/capture.ts +19 -1
  264. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  265. package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
  266. package/src/resources/extensions/gsd/auto-dispatch.ts +105 -8
  267. package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
  268. package/src/resources/extensions/gsd/auto-post-unit.ts +138 -6
  269. package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
  270. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  271. package/src/resources/extensions/gsd/auto-start.ts +38 -0
  272. package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
  273. package/src/resources/extensions/gsd/auto-verification.ts +190 -2
  274. package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
  275. package/src/resources/extensions/gsd/auto.ts +2 -1
  276. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
  277. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +35 -13
  278. package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
  279. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
  280. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
  281. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -1
  282. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +20 -0
  283. package/src/resources/extensions/gsd/bootstrap/system-context.ts +28 -0
  284. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  285. package/src/resources/extensions/gsd/commands/context.ts +7 -1
  286. package/src/resources/extensions/gsd/commands/handlers/core.ts +24 -0
  287. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +140 -0
  288. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  289. package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
  290. package/src/resources/extensions/gsd/config-overlay.ts +331 -0
  291. package/src/resources/extensions/gsd/detection.ts +1 -1
  292. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
  293. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  294. package/src/resources/extensions/gsd/doctor.ts +2 -1
  295. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  296. package/src/resources/extensions/gsd/gsd-db.ts +13 -2
  297. package/src/resources/extensions/gsd/guided-flow.ts +254 -30
  298. package/src/resources/extensions/gsd/md-importer.ts +13 -6
  299. package/src/resources/extensions/gsd/notification-overlay.ts +295 -0
  300. package/src/resources/extensions/gsd/notification-store.ts +293 -0
  301. package/src/resources/extensions/gsd/notification-widget.ts +68 -0
  302. package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
  303. package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
  304. package/src/resources/extensions/gsd/pre-execution-checks.ts +581 -0
  305. package/src/resources/extensions/gsd/preferences-types.ts +53 -0
  306. package/src/resources/extensions/gsd/preferences-validation.ts +78 -1
  307. package/src/resources/extensions/gsd/preferences.ts +13 -2
  308. package/src/resources/extensions/gsd/preparation.ts +1419 -0
  309. package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
  310. package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  311. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  312. package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  313. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  314. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  315. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  316. package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
  317. package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  318. package/src/resources/extensions/gsd/quick.ts +20 -15
  319. package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
  320. package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
  321. package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
  322. package/src/resources/extensions/gsd/session-lock.ts +17 -1
  323. package/src/resources/extensions/gsd/state.ts +101 -11
  324. package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  325. package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
  326. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
  327. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
  328. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
  329. package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +36 -0
  330. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
  331. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
  332. package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
  333. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
  334. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
  335. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
  336. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +76 -0
  337. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
  338. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
  339. package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
  340. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
  341. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
  342. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
  343. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
  344. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
  345. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
  346. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +5 -3
  347. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  348. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
  349. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
  350. package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
  351. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
  352. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
  353. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
  354. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +73 -0
  355. package/src/resources/extensions/gsd/tests/notification-store.test.ts +282 -0
  356. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
  357. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
  358. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
  359. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
  360. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
  361. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
  362. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +1197 -0
  363. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
  364. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
  365. package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
  366. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
  367. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
  368. package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
  369. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
  370. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
  371. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
  372. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
  373. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
  374. package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
  375. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
  376. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
  377. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
  378. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
  379. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
  380. package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
  381. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
  382. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
  383. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
  384. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
  385. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
  386. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
  387. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
  388. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
  389. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
  390. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
  391. package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
  392. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
  393. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
  394. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
  395. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +163 -0
  396. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
  397. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
  398. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
  399. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
  400. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
  401. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
  402. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
  403. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
  404. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
  405. package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
  406. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
  407. package/src/resources/extensions/gsd/tools/complete-slice.ts +13 -3
  408. package/src/resources/extensions/gsd/tools/complete-task.ts +16 -4
  409. package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
  410. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
  411. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
  412. package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
  413. package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
  414. package/src/resources/extensions/gsd/triage-resolution.ts +29 -10
  415. package/src/resources/extensions/gsd/types.ts +4 -0
  416. package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
  417. package/src/resources/extensions/gsd/workflow-logger.ts +13 -0
  418. package/src/resources/extensions/gsd/workflow-projections.ts +4 -6
  419. package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -3
  420. package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
  421. package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
  422. package/src/resources/extensions/gsd/worktree.ts +10 -0
  423. package/src/resources/extensions/shared/interview-ui.ts +1 -1
  424. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
  425. package/dist/web/standalone/.next/static/F1mOwzgCW9R8N3Pt1Et87/_buildManifest.js +0 -1
  426. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
  427. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +0 -1
  428. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +0 -1
  429. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +0 -1
  430. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  431. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  432. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +0 -1
  433. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +0 -1
  434. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +0 -1
  435. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +0 -1
  436. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +0 -1
  437. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +0 -1
  438. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +0 -1
  439. package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +0 -1
  440. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +0 -1
  441. package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +0 -1
  442. package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +0 -1
  443. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +0 -1
  444. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +0 -1
  445. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +0 -1
  446. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +0 -1
  447. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +0 -1
  448. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +0 -1
  449. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +0 -1
  450. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +0 -1
  451. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +0 -1
  452. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +0 -1
  453. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +0 -1
  454. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +0 -1
  455. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +0 -1
  456. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +0 -1
  457. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +0 -1
  458. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +0 -1
  459. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +0 -1
  460. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +0 -1
  461. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +0 -1
  462. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  463. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +0 -1
  464. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  465. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +0 -1
  466. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +0 -1
  467. package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +0 -1
  468. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +0 -1
  469. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +0 -1
  470. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +0 -1
  471. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +0 -1
  472. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +0 -1
  473. /package/dist/web/standalone/.next/static/{F1mOwzgCW9R8N3Pt1Et87 → Z3TgDP0c7kG9j8CVQVGcl}/_ssgManifest.js +0 -0
@@ -18,6 +18,7 @@ import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
18
18
  import { loadPrompt } from "./prompt-loader.js";
19
19
  import {
20
20
  resolveSliceFile,
21
+ resolveSlicePath,
21
22
  resolveTaskFile,
22
23
  resolveMilestoneFile,
23
24
  resolveTasksDir,
@@ -38,7 +39,7 @@ import {
38
39
  } from "./auto-recovery.js";
39
40
  import { regenerateIfMissing } from "./workflow-projections.js";
40
41
  import { syncStateToProjectRoot } from "./auto-worktree.js";
41
- import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getAdapter } from "./gsd-db.js";
42
+ import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, updateSliceStatus, _getAdapter } from "./gsd-db.js";
42
43
  import { renderPlanCheckboxes } from "./markdown-renderer.js";
43
44
  import { consumeSignal } from "./session-status-io.js";
44
45
  import {
@@ -59,6 +60,10 @@ import { validateFileChanges } from "./safety/file-change-validator.js";
59
60
  import { validateContent } from "./safety/content-validator.js";
60
61
  import { resolveSafetyHarnessConfig } from "./safety/safety-harness.js";
61
62
  import { resolveExpectedArtifactPath as resolveArtifactForContent } from "./auto-artifact-paths.js";
63
+ import { loadEffectiveGSDPreferences } from "./preferences.js";
64
+ import { getSliceTasks } from "./gsd-db.js";
65
+ import { runPreExecutionChecks, type PreExecutionResult } from "./pre-execution-checks.js";
66
+ import { writePreExecutionEvidence } from "./verification-evidence.js";
62
67
 
63
68
  /** Maximum verification retry attempts before escalating to blocker placeholder (#2653). */
64
69
  const MAX_VERIFICATION_RETRIES = 3;
@@ -156,7 +161,14 @@ export function detectRogueFileWrites(
156
161
 
157
162
  const dbRow = getSlice(mid, sid);
158
163
  if (!dbRow || dbRow.status !== "complete") {
159
- rogues.push({ path: summaryPath, unitType, unitId });
164
+ // Auto-remediate: SUMMARY exists on disk but DB is stale — sync DB to
165
+ // match filesystem instead of reporting as rogue (#3633).
166
+ try {
167
+ updateSliceStatus(mid, sid, "complete", new Date().toISOString());
168
+ } catch {
169
+ // If DB update fails, fall back to rogue detection so the issue is visible
170
+ rogues.push({ path: summaryPath, unitType, unitId });
171
+ }
160
172
  }
161
173
  } else if (unitType === "plan-milestone") {
162
174
  if (!mid) return [];
@@ -577,11 +589,14 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
577
589
  "error",
578
590
  );
579
591
  } else if (!triggerArtifactVerified) {
580
- // #2883: If the artifact is missing because the tool invocation itself
581
- // failed (malformed/truncated JSON arguments), retrying will produce the
582
- // same failure. Pause auto-mode instead of entering a stuck retry loop.
592
+ // #2883/#3595: If the artifact is missing because the tool invocation
593
+ // failed (malformed JSON) or was skipped (queued user message), retrying
594
+ // will produce the same failure. Pause auto-mode instead of looping.
583
595
  if (s.lastToolInvocationError) {
584
- const errMsg = `Tool invocation failed for ${s.currentUnit.type}: ${s.lastToolInvocationError}. Structured argument generation failed — pausing auto-mode.`;
596
+ const isUserSkip = /queued user message/i.test(s.lastToolInvocationError);
597
+ const errMsg = isUserSkip
598
+ ? `Tool skipped for ${s.currentUnit.type}: ${s.lastToolInvocationError}. Queued user message interrupted the turn — pausing auto-mode.`
599
+ : `Tool invocation failed for ${s.currentUnit.type}: ${s.lastToolInvocationError}. Structured argument generation failed — pausing auto-mode.`;
585
600
  debugLog("postUnit", { phase: "tool-invocation-error-pause", unitType: s.currentUnit.type, unitId: s.currentUnit.id, error: s.lastToolInvocationError });
586
601
  ctx.ui.notify(errMsg, "error");
587
602
  s.lastToolInvocationError = null;
@@ -772,6 +787,123 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
772
787
  }
773
788
  }
774
789
 
790
+ // ── Pre-execution checks (after plan-slice completes) ──
791
+ if (
792
+ s.currentUnit &&
793
+ s.currentUnit.type === "plan-slice"
794
+ ) {
795
+ let preExecPauseNeeded = false;
796
+ await runSafely("postUnitPostVerification", "pre-execution-checks", async () => {
797
+ try {
798
+ // Check preferences — respect enhanced_verification and enhanced_verification_pre
799
+ const prefs = loadEffectiveGSDPreferences()?.preferences;
800
+ const enhancedEnabled = prefs?.enhanced_verification !== false; // default true
801
+ const preEnabled = prefs?.enhanced_verification_pre !== false; // default true
802
+
803
+ if (!enhancedEnabled || !preEnabled) {
804
+ debugLog("postUnitPostVerification", {
805
+ phase: "pre-execution-checks",
806
+ skipped: true,
807
+ reason: "disabled by preferences",
808
+ });
809
+ return;
810
+ }
811
+
812
+ // Parse the unit ID to get milestone/slice IDs
813
+ const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit!.id);
814
+ if (!mid || !sid) {
815
+ debugLog("postUnitPostVerification", {
816
+ phase: "pre-execution-checks",
817
+ skipped: true,
818
+ reason: "could not parse milestone/slice from unit ID",
819
+ });
820
+ return;
821
+ }
822
+
823
+ // Get tasks for this slice from DB
824
+ const tasks = getSliceTasks(mid, sid);
825
+ if (tasks.length === 0) {
826
+ debugLog("postUnitPostVerification", {
827
+ phase: "pre-execution-checks",
828
+ skipped: true,
829
+ reason: "no tasks found for slice",
830
+ });
831
+ return;
832
+ }
833
+
834
+ // Run pre-execution checks
835
+ const result: PreExecutionResult = await runPreExecutionChecks(tasks, s.basePath);
836
+
837
+ // Log summary to stderr in existing verification output format
838
+ const emoji = result.status === "pass" ? "✅" : result.status === "warn" ? "⚠️" : "❌";
839
+ process.stderr.write(
840
+ `gsd-pre-exec: ${emoji} Pre-execution checks ${result.status} for ${mid}/${sid} (${result.durationMs}ms)\n`,
841
+ );
842
+
843
+ // Log individual check results
844
+ for (const check of result.checks) {
845
+ const checkEmoji = check.passed ? "✓" : check.blocking ? "✗" : "⚠";
846
+ process.stderr.write(
847
+ `gsd-pre-exec: ${checkEmoji} [${check.category}] ${check.target}: ${check.message}\n`,
848
+ );
849
+ }
850
+
851
+ // Write evidence JSON to slice artifacts directory
852
+ const slicePath = resolveSlicePath(s.basePath, mid, sid);
853
+ if (slicePath) {
854
+ writePreExecutionEvidence(result, slicePath, mid, sid);
855
+ }
856
+
857
+ // Notify UI
858
+ if (result.status === "fail") {
859
+ const blockingCount = result.checks.filter(c => !c.passed && c.blocking).length;
860
+ ctx.ui.notify(
861
+ `Pre-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found`,
862
+ "error",
863
+ );
864
+ preExecPauseNeeded = true;
865
+ } else if (result.status === "warn") {
866
+ ctx.ui.notify(
867
+ `Pre-execution checks passed with warnings`,
868
+ "warning",
869
+ );
870
+ // Strict mode: treat warnings as blocking
871
+ if (prefs?.enhanced_verification_strict === true) {
872
+ preExecPauseNeeded = true;
873
+ }
874
+ }
875
+
876
+ debugLog("postUnitPostVerification", {
877
+ phase: "pre-execution-checks",
878
+ status: result.status,
879
+ checkCount: result.checks.length,
880
+ durationMs: result.durationMs,
881
+ });
882
+ } catch (preExecError) {
883
+ // Fail-closed: if runPreExecutionChecks throws, pause auto-mode instead of silently continuing
884
+ const errorMessage = preExecError instanceof Error ? preExecError.message : String(preExecError);
885
+ debugLog("postUnitPostVerification", {
886
+ phase: "pre-execution-checks",
887
+ error: errorMessage,
888
+ failClosed: true,
889
+ });
890
+ logError("engine", `gsd-pre-exec: Pre-execution checks threw an error: ${errorMessage}`);
891
+ ctx.ui.notify(
892
+ `Pre-execution checks error: ${errorMessage} — pausing for human review`,
893
+ "error",
894
+ );
895
+ preExecPauseNeeded = true;
896
+ }
897
+ });
898
+
899
+ // Check for blocking failures after runSafely completes
900
+ if (preExecPauseNeeded) {
901
+ debugLog("postUnitPostVerification", { phase: "pre-execution-checks", pausing: true, reason: "blocking failures detected" });
902
+ await pauseAuto(ctx, pi);
903
+ return "stopped";
904
+ }
905
+ }
906
+
775
907
  // ── Triage check ──
776
908
  if (
777
909
  !s.stepMode &&
@@ -858,6 +858,7 @@ export async function buildDiscussMilestonePrompt(mid: string, midTitle: string,
858
858
  inlinedTemplates: discussTemplates,
859
859
  structuredQuestionsAvailable: "true",
860
860
  commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
861
+ fastPathInstruction: "",
861
862
  });
862
863
 
863
864
  // If a CONTEXT-DRAFT.md exists, append it as seed material
@@ -1801,6 +1802,36 @@ const GATE_QUESTIONS: Record<string, { question: string; guidance: string }> = {
1801
1802
  },
1802
1803
  };
1803
1804
 
1805
+ export async function buildParallelResearchSlicesPrompt(
1806
+ mid: string,
1807
+ midTitle: string,
1808
+ slices: Array<{ id: string; title: string }>,
1809
+ basePath: string,
1810
+ ): Promise<string> {
1811
+ // Build individual research-slice prompts for each slice
1812
+ const subagentSections: string[] = [];
1813
+ for (const slice of slices) {
1814
+ const slicePrompt = await buildResearchSlicePrompt(mid, midTitle, slice.id, slice.title, basePath);
1815
+ subagentSections.push([
1816
+ `### ${slice.id}: ${slice.title}`,
1817
+ "",
1818
+ "Use this as the prompt for a `subagent` call (agent: `gsd-executor` or the default agent):",
1819
+ "",
1820
+ "```",
1821
+ slicePrompt,
1822
+ "```",
1823
+ ].join("\n"));
1824
+ }
1825
+
1826
+ return loadPrompt("parallel-research-slices", {
1827
+ mid,
1828
+ midTitle,
1829
+ sliceCount: String(slices.length),
1830
+ sliceList: slices.map((s) => `- **${s.id}**: ${s.title}`).join("\n"),
1831
+ subagentPrompts: subagentSections.join("\n\n---\n\n"),
1832
+ });
1833
+ }
1834
+
1804
1835
  export async function buildGateEvaluatePrompt(
1805
1836
  mid: string, midTitle: string, sid: string, sTitle: string,
1806
1837
  base: string,
@@ -286,7 +286,7 @@ export function verifyExpectedArtifact(
286
286
  if (!hasCheckboxTask && !hasHeadingTask) return false;
287
287
  }
288
288
 
289
- // execute-task: DB status is authoritative. Fall back to heading-style plan
289
+ // execute-task: DB status is authoritative. Fall back to checked-checkbox
290
290
  // detection when the DB is unavailable (unmigrated projects).
291
291
  if (unitType === "execute-task") {
292
292
  const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
@@ -297,20 +297,22 @@ export function verifyExpectedArtifact(
297
297
  if (dbTask.status !== "complete" && dbTask.status !== "done") return false;
298
298
  } else if (!isDbAvailable()) {
299
299
  // LEGACY: Pre-migration fallback for projects without DB.
300
- // Fall back to plan heading check (format detection, not reconciliation).
301
- // Heading-style entries (### T01 --) count as verified because the
302
- // summary file existence (checked above) is the real signal.
300
+ // Require a CHECKED checkbox a bare heading or unchecked checkbox
301
+ // does not prove gsd_complete_task ran. Summary file on disk alone
302
+ // is not sufficient evidence (could be a rogue write) (#3607).
303
303
  const planAbs = resolveSliceFile(base, mid, sid, "PLAN");
304
304
  if (planAbs && existsSync(planAbs)) {
305
305
  const planContent = readFileSync(planAbs, "utf-8");
306
306
  const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
307
- const hdRe = new RegExp(`^#{2,4}\\s+${escapedTid}\\s*(?:--|—|:)`, "m");
308
307
  const cbRe = new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m");
309
- if (!hdRe.test(planContent) && !cbRe.test(planContent)) return false;
308
+ if (!cbRe.test(planContent)) return false;
309
+ } else {
310
+ return false; // no plan file → cannot verify
310
311
  }
312
+ } else {
313
+ // DB available but task row not found — completion tool never ran (#3607)
314
+ return false;
311
315
  }
312
- // else: DB available but task not found — summary file exists (checked above),
313
- // so treat as verified (task may not be imported yet)
314
316
  }
315
317
  }
316
318
 
@@ -44,6 +44,9 @@ import {
44
44
  nativeInit,
45
45
  nativeAddAll,
46
46
  nativeCommit,
47
+ nativeGetCurrentBranch,
48
+ nativeDetectMainBranch,
49
+ nativeCheckoutBranch,
47
50
  } from "./native-git-bridge.js";
48
51
  import { GitServiceImpl } from "./git-service.js";
49
52
  import {
@@ -528,6 +531,22 @@ export async function bootstrapAutoSession(
528
531
  setActiveMilestoneId(base, s.currentMilestoneId);
529
532
  }
530
533
 
534
+ // Guard against stale milestone branch when isolation:none (#3613).
535
+ // A prior session with isolation:branch/worktree may have left HEAD on
536
+ // milestone/<MID>. Auto-checkout back to the integration branch.
537
+ if (getIsolationMode() === "none" && nativeIsRepo(base)) {
538
+ try {
539
+ const currentBranch = nativeGetCurrentBranch(base);
540
+ if (currentBranch.startsWith("milestone/")) {
541
+ const integrationBranch = nativeDetectMainBranch(base);
542
+ nativeCheckoutBranch(base, integrationBranch);
543
+ logWarning("bootstrap", `Returned to "${integrationBranch}" — HEAD was on stale milestone branch "${currentBranch}" (isolation: none does not use milestone branches).`);
544
+ }
545
+ } catch (err) {
546
+ logWarning("bootstrap", `Could not auto-checkout from stale milestone branch: ${err instanceof Error ? err.message : String(err)}`);
547
+ }
548
+ }
549
+
531
550
  // ── Auto-worktree setup ──
532
551
  s.originalBasePath = base;
533
552
 
@@ -614,6 +633,25 @@ export async function bootstrapAutoSession(
614
633
  };
615
634
  }
616
635
 
636
+ // Apply worker model override from parallel orchestrator (#worker-model).
637
+ // GSD_WORKER_MODEL is injected by the coordinator when parallel.worker_model
638
+ // is configured, so parallel milestone workers use a cheaper model than the
639
+ // coordinator session (e.g. Haiku for execution, Sonnet for planning).
640
+ const workerModelOverride = process.env.GSD_WORKER_MODEL;
641
+ if (workerModelOverride && process.env.GSD_PARALLEL_WORKER === "1") {
642
+ const availableModels = ctx.modelRegistry.getAvailable();
643
+ const { resolveModelId } = await import("./auto-model-selection.js");
644
+ const overrideModel = resolveModelId(workerModelOverride, availableModels, ctx.model?.provider);
645
+ if (overrideModel) {
646
+ const ok = await pi.setModel(overrideModel, { persist: false });
647
+ if (ok) {
648
+ // Update start model so all subsequent units use this as the baseline
649
+ s.autoModeStartModel = { provider: overrideModel.provider, id: overrideModel.id };
650
+ ctx.ui.notify(`Worker model override: ${overrideModel.provider}/${overrideModel.id}`, "info");
651
+ }
652
+ }
653
+ }
654
+
617
655
  // Snapshot installed skills
618
656
  if (resolveSkillDiscoveryMode() !== "off") {
619
657
  snapshotSkills();
@@ -102,3 +102,13 @@ export function isToolInvocationError(errorMsg: string): boolean {
102
102
  if (!errorMsg) return false;
103
103
  return TOOL_INVOCATION_ERROR_RE.test(errorMsg);
104
104
  }
105
+
106
+ /**
107
+ * Returns true if the error message indicates the tool was skipped because
108
+ * a queued user message interrupted the turn (#3595). Retrying will produce
109
+ * the same skip, so the unit should be paused rather than retried.
110
+ */
111
+ export function isQueuedUserMessageSkip(errorMsg: string): boolean {
112
+ if (!errorMsg) return false;
113
+ return /^Skipped due to queued user message\.?$/i.test(errorMsg.trim());
114
+ }
@@ -11,9 +11,10 @@
11
11
  */
12
12
 
13
13
  import type { ExtensionContext, ExtensionAPI } from "@gsd/pi-coding-agent";
14
+ import { mkdirSync, writeFileSync } from "node:fs";
14
15
  import { resolveSliceFile, resolveSlicePath } from "./paths.js";
15
16
  import { parseUnitId } from "./unit-id.js";
16
- import { isDbAvailable, getTask } from "./gsd-db.js";
17
+ import { isDbAvailable, getTask, getSliceTasks, type TaskRow } from "./gsd-db.js";
17
18
  import { loadEffectiveGSDPreferences } from "./preferences.js";
18
19
  import {
19
20
  runVerificationGate,
@@ -21,9 +22,11 @@ import {
21
22
  captureRuntimeErrors,
22
23
  runDependencyAudit,
23
24
  } from "./verification-gate.js";
24
- import { writeVerificationJSON } from "./verification-evidence.js";
25
+ import { writeVerificationJSON, type PostExecutionCheckJSON, type EvidenceJSON } from "./verification-evidence.js";
25
26
  import { logWarning } from "./workflow-logger.js";
27
+ import { runPostExecutionChecks, type PostExecutionResult } from "./post-execution-checks.js";
26
28
  import type { AutoSession } from "./auto/session.js";
29
+ import type { VerificationResult as VerificationGateResult } from "./types.js";
27
30
  import { join } from "node:path";
28
31
 
29
32
  export interface VerificationContext {
@@ -183,11 +186,140 @@ export async function runPostUnitVerification(
183
186
  return "continue";
184
187
  }
185
188
 
189
+ // ── Post-execution checks (run after main verification passes for execute-task units) ──
190
+ let postExecChecks: PostExecutionCheckJSON[] | undefined;
191
+ let postExecBlockingFailure = false;
192
+
193
+ if (result.passed && mid && sid && tid) {
194
+ // Check preferences — respect enhanced_verification and enhanced_verification_post
195
+ const enhancedEnabled = prefs?.enhanced_verification !== false; // default true
196
+ const postEnabled = prefs?.enhanced_verification_post !== false; // default true
197
+
198
+ if (enhancedEnabled && postEnabled && isDbAvailable()) {
199
+ try {
200
+ // Get the completed task from DB
201
+ const taskRow = getTask(mid, sid, tid);
202
+ if (taskRow && taskRow.key_files && taskRow.key_files.length > 0) {
203
+ // Get all tasks in the slice
204
+ const allTasks = getSliceTasks(mid, sid);
205
+ // Filter to prior completed tasks (status = 'complete' or 'done', before current task)
206
+ const priorTasks = allTasks.filter(
207
+ (t: TaskRow) =>
208
+ (t.status === "complete" || t.status === "done") &&
209
+ t.id !== tid &&
210
+ t.sequence < taskRow.sequence
211
+ );
212
+
213
+ // Run post-execution checks
214
+ const postExecResult: PostExecutionResult = runPostExecutionChecks(
215
+ taskRow,
216
+ priorTasks,
217
+ s.basePath
218
+ );
219
+
220
+ // Store checks for evidence JSON
221
+ postExecChecks = postExecResult.checks;
222
+
223
+ // Log summary to stderr with gsd-post-exec: prefix
224
+ const emoji =
225
+ postExecResult.status === "pass"
226
+ ? "✅"
227
+ : postExecResult.status === "warn"
228
+ ? "⚠️"
229
+ : "❌";
230
+ process.stderr.write(
231
+ `gsd-post-exec: ${emoji} Post-execution checks ${postExecResult.status} for ${mid}/${sid}/${tid} (${postExecResult.durationMs}ms)\n`
232
+ );
233
+
234
+ // Log individual check results
235
+ for (const check of postExecResult.checks) {
236
+ const checkEmoji = check.passed
237
+ ? "✓"
238
+ : check.blocking
239
+ ? "✗"
240
+ : "⚠";
241
+ process.stderr.write(
242
+ `gsd-post-exec: ${checkEmoji} [${check.category}] ${check.target}: ${check.message}\n`
243
+ );
244
+ }
245
+
246
+ // Check for blocking failures
247
+ if (postExecResult.status === "fail") {
248
+ postExecBlockingFailure = true;
249
+ const blockingCount = postExecResult.checks.filter(
250
+ (c) => !c.passed && c.blocking
251
+ ).length;
252
+ ctx.ui.notify(
253
+ `Post-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found`,
254
+ "error"
255
+ );
256
+ } else if (postExecResult.status === "warn") {
257
+ ctx.ui.notify(
258
+ `Post-execution checks passed with warnings`,
259
+ "warning"
260
+ );
261
+ // Strict mode: treat warnings as blocking
262
+ if (prefs?.enhanced_verification_strict === true) {
263
+ postExecBlockingFailure = true;
264
+ }
265
+ }
266
+ }
267
+ } catch (postExecErr) {
268
+ // Post-execution check errors are non-fatal — log and continue
269
+ logWarning("engine", `gsd-post-exec: error — ${(postExecErr as Error).message}`);
270
+ }
271
+ }
272
+ }
273
+
274
+ // Re-write verification evidence JSON with post-execution checks
275
+ if (postExecChecks && postExecChecks.length > 0 && mid && sid && tid) {
276
+ try {
277
+ const sDir = resolveSlicePath(s.basePath, mid, sid);
278
+ if (sDir) {
279
+ const tasksDir = join(sDir, "tasks");
280
+ // Add postExecutionChecks to the result for the JSON write
281
+ const resultWithPostExec = {
282
+ ...result,
283
+ // Mark as failed if there was a blocking post-exec failure
284
+ passed: result.passed && !postExecBlockingFailure,
285
+ };
286
+ // Manually write with postExecutionChecks field
287
+ writeVerificationJSONWithPostExec(
288
+ resultWithPostExec,
289
+ tasksDir,
290
+ tid,
291
+ s.currentUnit.id,
292
+ postExecChecks,
293
+ postExecBlockingFailure ? attempt + 1 : undefined,
294
+ postExecBlockingFailure ? maxRetries : undefined
295
+ );
296
+ }
297
+ } catch (evidenceErr) {
298
+ logWarning("engine", `verification-evidence: post-exec write error — ${(evidenceErr as Error).message}`);
299
+ }
300
+ }
301
+
302
+ // Update result.passed based on post-execution checks
303
+ if (postExecBlockingFailure) {
304
+ result.passed = false;
305
+ }
306
+
186
307
  // ── Auto-fix retry logic ──
187
308
  if (result.passed) {
188
309
  s.verificationRetryCount.delete(s.currentUnit.id);
189
310
  s.pendingVerificationRetry = null;
190
311
  return "continue";
312
+ } else if (postExecBlockingFailure) {
313
+ // Post-execution failures are cross-task consistency issues — retrying the same task won't fix them.
314
+ // Skip retry and pause immediately for human review.
315
+ s.verificationRetryCount.delete(s.currentUnit.id);
316
+ s.pendingVerificationRetry = null;
317
+ ctx.ui.notify(
318
+ `Post-execution checks failed — cross-task consistency issue detected, pausing for human review`,
319
+ "error",
320
+ );
321
+ await pauseAuto(ctx, pi);
322
+ return "pause";
191
323
  } else if (autoFixEnabled && attempt + 1 <= maxRetries) {
192
324
  const nextAttempt = attempt + 1;
193
325
  s.verificationRetryCount.set(s.currentUnit.id, nextAttempt);
@@ -231,3 +363,59 @@ export async function runPostUnitVerification(
231
363
  return "continue";
232
364
  }
233
365
  }
366
+
367
+ /**
368
+ * Write verification evidence JSON with post-execution checks included.
369
+ * This is a variant of writeVerificationJSON that adds the postExecutionChecks field.
370
+ */
371
+ function writeVerificationJSONWithPostExec(
372
+ result: VerificationGateResult,
373
+ tasksDir: string,
374
+ taskId: string,
375
+ unitId: string,
376
+ postExecutionChecks: PostExecutionCheckJSON[],
377
+ retryAttempt?: number,
378
+ maxRetries?: number,
379
+ ): void {
380
+ mkdirSync(tasksDir, { recursive: true });
381
+
382
+ const evidence: EvidenceJSON = {
383
+ schemaVersion: 1,
384
+ taskId,
385
+ unitId: unitId ?? taskId,
386
+ timestamp: result.timestamp,
387
+ passed: result.passed,
388
+ discoverySource: result.discoverySource,
389
+ checks: result.checks.map((check) => ({
390
+ command: check.command,
391
+ exitCode: check.exitCode,
392
+ durationMs: check.durationMs,
393
+ verdict: check.exitCode === 0 ? "pass" : "fail",
394
+ })),
395
+ ...(retryAttempt !== undefined ? { retryAttempt } : {}),
396
+ ...(maxRetries !== undefined ? { maxRetries } : {}),
397
+ postExecutionChecks,
398
+ };
399
+
400
+ if (result.runtimeErrors && result.runtimeErrors.length > 0) {
401
+ evidence.runtimeErrors = result.runtimeErrors.map(e => ({
402
+ source: e.source,
403
+ severity: e.severity,
404
+ message: e.message,
405
+ blocking: e.blocking,
406
+ }));
407
+ }
408
+
409
+ if (result.auditWarnings && result.auditWarnings.length > 0) {
410
+ evidence.auditWarnings = result.auditWarnings.map(w => ({
411
+ name: w.name,
412
+ severity: w.severity,
413
+ title: w.title,
414
+ url: w.url,
415
+ fixAvailable: w.fixAvailable,
416
+ }));
417
+ }
418
+
419
+ const filePath = join(tasksDir, `${taskId}-VERIFY.json`);
420
+ writeFileSync(filePath, JSON.stringify(evidence, null, 2) + "\n", "utf-8");
421
+ }
@@ -188,8 +188,10 @@ function clearProjectRootStateFiles(basePath: string, milestoneId: string): void
188
188
  try {
189
189
  unlinkSync(file);
190
190
  } catch (err) {
191
- /* non-fatal — file may not exist */
192
- logWarning("worktree", `file unlink failed: ${err instanceof Error ? err.message : String(err)}`);
191
+ // ENOENT is expected — file may not exist (#3597)
192
+ if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
193
+ logWarning("worktree", `file unlink failed: ${err instanceof Error ? err.message : String(err)}`);
194
+ }
193
195
  }
194
196
  }
195
197
 
@@ -218,8 +220,11 @@ function clearProjectRootStateFiles(basePath: string, milestoneId: string): void
218
220
  try {
219
221
  unlinkSync(join(basePath, f));
220
222
  } catch (err) {
221
- /* non-fatal */
222
- logWarning("worktree", `untracked file unlink failed: ${err instanceof Error ? err.message : String(err)}`);
223
+ // ENOENT/EISDIR are expected for already-removed or directory entries (#3597)
224
+ const code = (err as NodeJS.ErrnoException).code;
225
+ if (code !== "ENOENT" && code !== "EISDIR") {
226
+ logWarning("worktree", `untracked file unlink failed: ${err instanceof Error ? err.message : String(err)}`);
227
+ }
223
228
  }
224
229
  }
225
230
  }
@@ -770,6 +775,9 @@ export function syncWorktreeStateBack(
770
775
  .map((d) => d.name);
771
776
 
772
777
  for (const mid of wtMilestones) {
778
+ // Skip the current milestone being merged — its files are already in the
779
+ // milestone branch and would conflict with the squash merge (#3641).
780
+ if (mid === milestoneId) continue;
773
781
  syncMilestoneDir(wtGsd, mainGsd, mid, synced);
774
782
  }
775
783
  } catch (err) {
@@ -1049,12 +1057,20 @@ export function createAutoWorktree(
1049
1057
  reuseExistingBranch: true,
1050
1058
  });
1051
1059
  } else {
1052
- // Fresh start — create branch from integration branch
1060
+ // Fresh start — create branch from integration branch.
1061
+ // Use the same 3-tier fallback as mergeMilestoneToMain (#3461):
1062
+ // 1. META.json integration branch (explicit per-milestone override)
1063
+ // 2. git.main_branch preference (user's configured working branch)
1064
+ // 3. nativeDetectMainBranch (origin/HEAD auto-detection)
1065
+ // Without tier 2, projects with main_branch=dev but origin/HEAD→master
1066
+ // would fork worktrees from the wrong (stale) branch.
1053
1067
  const integrationBranch =
1054
1068
  readIntegrationBranch(basePath, milestoneId) ?? undefined;
1069
+ const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
1070
+ const startPoint = integrationBranch ?? gitPrefs?.main_branch ?? undefined;
1055
1071
  info = createWorktree(basePath, milestoneId, {
1056
1072
  branch,
1057
- startPoint: integrationBranch,
1073
+ startPoint,
1058
1074
  });
1059
1075
  }
1060
1076
 
@@ -1453,8 +1469,13 @@ export function mergeMilestoneToMain(
1453
1469
  originalBasePath_,
1454
1470
  milestoneId,
1455
1471
  );
1472
+ // Validate prefs.main_branch exists before using it — a stale preference
1473
+ // (e.g. "master" when repo uses "main") causes merge failure (#3589).
1474
+ const validatedPrefBranch = prefs.main_branch && nativeBranchExists(originalBasePath_, prefs.main_branch)
1475
+ ? prefs.main_branch
1476
+ : undefined;
1456
1477
  const mainBranch =
1457
- integrationBranch ?? prefs.main_branch ?? nativeDetectMainBranch(originalBasePath_);
1478
+ integrationBranch ?? validatedPrefBranch ?? nativeDetectMainBranch(originalBasePath_);
1458
1479
 
1459
1480
  // Remove transient project-root state files before any branch or merge
1460
1481
  // operation. Untracked milestone metadata can otherwise block squash merges.
@@ -76,6 +76,7 @@ import {
76
76
  hasInteractiveToolInFlight,
77
77
  clearInFlightTools,
78
78
  isToolInvocationError,
79
+ isQueuedUserMessageSkip,
79
80
  } from "./auto-tool-tracking.js";
80
81
  import { closeoutUnit } from "./auto-unit-closeout.js";
81
82
  import { recoverTimedOutUnit } from "./auto-timeout-recovery.js";
@@ -397,7 +398,7 @@ export function markToolEnd(toolCallId: string): void {
397
398
  */
398
399
  export function recordToolInvocationError(toolName: string, errorMsg: string): void {
399
400
  if (!s.active) return;
400
- if (isToolInvocationError(errorMsg)) {
401
+ if (isToolInvocationError(errorMsg) || isQueuedUserMessageSkip(errorMsg)) {
401
402
  s.lastToolInvocationError = `${toolName}: ${errorMsg}`;
402
403
  }
403
404
  }