gsd-pi 2.44.0 → 2.45.0-dev.e0ee972

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 (505) hide show
  1. package/README.md +30 -12
  2. package/dist/help-text.js +1 -1
  3. package/dist/loader.js +34 -0
  4. package/dist/resources/extensions/gsd/activity-log.js +7 -0
  5. package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
  6. package/dist/resources/extensions/gsd/auto/phases.js +52 -45
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
  8. package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
  9. package/dist/resources/extensions/gsd/auto-start.js +31 -2
  10. package/dist/resources/extensions/gsd/auto-timers.js +57 -3
  11. package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
  12. package/dist/resources/extensions/gsd/auto-worktree.js +14 -10
  13. package/dist/resources/extensions/gsd/auto.js +34 -8
  14. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +168 -11
  15. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
  16. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  17. package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
  18. package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
  19. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  20. package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
  21. package/dist/resources/extensions/gsd/db-writer.js +40 -22
  22. package/dist/resources/extensions/gsd/doctor-checks.js +1 -1
  23. package/dist/resources/extensions/gsd/doctor.js +10 -2
  24. package/dist/resources/extensions/gsd/git-service.js +8 -3
  25. package/dist/resources/extensions/gsd/gsd-db.js +17 -2
  26. package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
  27. package/dist/resources/extensions/gsd/preferences-types.js +2 -2
  28. package/dist/resources/extensions/gsd/preferences.js +17 -5
  29. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  30. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  31. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  32. package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  33. package/dist/resources/extensions/gsd/prompts/rethink.md +78 -0
  34. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  35. package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
  36. package/dist/resources/extensions/gsd/repo-identity.js +45 -7
  37. package/dist/resources/extensions/gsd/rethink.js +115 -0
  38. package/dist/resources/extensions/gsd/state.js +41 -3
  39. package/dist/resources/extensions/gsd/tools/plan-slice.js +1 -0
  40. package/dist/resources/extensions/gsd/tools/plan-task.js +1 -0
  41. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -0
  42. package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
  43. package/dist/resources/extensions/gsd/workflow-logger.js +138 -0
  44. package/dist/resources/extensions/gsd/worktree-manager.js +34 -3
  45. package/dist/resources/extensions/gsd/worktree-resolver.js +43 -0
  46. package/dist/resources/extensions/mcp-client/index.js +14 -0
  47. package/dist/resources/extensions/voice/index.js +11 -16
  48. package/dist/resources/extensions/voice/linux-ready.js +67 -0
  49. package/dist/web/standalone/.next/BUILD_ID +1 -1
  50. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  51. package/dist/web/standalone/.next/build-manifest.json +4 -4
  52. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  53. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  54. package/dist/web/standalone/.next/required-server-files.json +3 -3
  55. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  56. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  58. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  66. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.rsc +5 -5
  69. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +5 -5
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  75. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  82. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  120. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  126. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  140. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  142. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  144. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  146. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/index.html +1 -1
  156. package/dist/web/standalone/.next/server/app/index.rsc +6 -6
  157. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  158. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +6 -6
  159. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  161. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  162. package/dist/web/standalone/.next/server/app/page.js +2 -2
  163. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  165. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  166. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  167. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/middleware.js +2 -2
  170. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  172. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  173. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  174. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  175. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +9 -0
  176. package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
  177. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  178. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  179. package/dist/web/standalone/.next/static/chunks/app/page-6654a8cca61a3d1c.js +1 -0
  180. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  181. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  182. package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
  183. package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
  184. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  185. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  186. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  187. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  188. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  189. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  190. package/dist/web/standalone/server.js +1 -1
  191. package/package.json +1 -1
  192. package/packages/native/dist/stream-process/index.js +2 -2
  193. package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
  194. package/packages/native/src/stream-process/index.ts +2 -2
  195. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
  196. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  197. package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
  198. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  199. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  200. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  201. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
  203. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  205. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  206. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
  207. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  209. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  210. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  211. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +4 -0
  212. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -1
  213. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +10 -5
  214. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts +2 -0
  216. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts.map +1 -0
  217. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js +185 -0
  218. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js.map +1 -0
  219. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
  220. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
  221. package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
  222. package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
  223. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +239 -10
  224. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  225. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +13 -1
  226. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  227. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  228. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  229. package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
  230. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -1
  231. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  232. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  233. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  234. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  236. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  237. package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
  238. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  239. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  240. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/main.js +17 -0
  243. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
  245. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  250. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
  251. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
  257. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  267. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
  269. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  271. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
  272. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  274. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  275. package/packages/pi-coding-agent/package.json +1 -1
  276. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  277. package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
  278. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
  279. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  280. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
  281. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  282. package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
  283. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
  284. package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
  285. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
  286. package/packages/pi-coding-agent/src/core/model-registry.ts +51 -4
  287. package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
  288. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  289. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  290. package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
  291. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  292. package/packages/pi-coding-agent/src/main.ts +19 -0
  293. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
  294. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
  295. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  296. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
  297. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
  298. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
  299. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
  300. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
  301. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  302. package/pkg/package.json +1 -1
  303. package/src/resources/extensions/gsd/activity-log.ts +1 -0
  304. package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
  305. package/src/resources/extensions/gsd/auto/phases.ts +61 -59
  306. package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
  307. package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
  308. package/src/resources/extensions/gsd/auto-start.ts +39 -2
  309. package/src/resources/extensions/gsd/auto-timers.ts +64 -3
  310. package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
  311. package/src/resources/extensions/gsd/auto-worktree.ts +17 -11
  312. package/src/resources/extensions/gsd/auto.ts +40 -6
  313. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +160 -11
  314. package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
  315. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  316. package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
  317. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  318. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  319. package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
  320. package/src/resources/extensions/gsd/db-writer.ts +41 -27
  321. package/src/resources/extensions/gsd/doctor-checks.ts +1 -1
  322. package/src/resources/extensions/gsd/doctor.ts +9 -3
  323. package/src/resources/extensions/gsd/git-service.ts +6 -2
  324. package/src/resources/extensions/gsd/gsd-db.ts +21 -2
  325. package/src/resources/extensions/gsd/journal.ts +6 -1
  326. package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
  327. package/src/resources/extensions/gsd/preferences-types.ts +2 -2
  328. package/src/resources/extensions/gsd/preferences.ts +18 -4
  329. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  330. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  331. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  332. package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  333. package/src/resources/extensions/gsd/prompts/rethink.md +78 -0
  334. package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  335. package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
  336. package/src/resources/extensions/gsd/repo-identity.ts +46 -7
  337. package/src/resources/extensions/gsd/rethink.ts +154 -0
  338. package/src/resources/extensions/gsd/state.ts +41 -1
  339. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  340. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  341. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  342. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
  343. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  344. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  345. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  346. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  347. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  348. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  349. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  350. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  351. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  352. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  353. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  354. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  355. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  356. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  357. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  358. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
  359. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  360. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  361. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  362. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  363. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  364. package/src/resources/extensions/gsd/tests/db-writer.test.ts +465 -416
  365. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  366. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  367. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
  368. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +210 -181
  369. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  370. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  371. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  372. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  373. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  374. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  375. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  376. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  377. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  378. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  379. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  380. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  381. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  382. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  383. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  384. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  385. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  386. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  387. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  388. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
  389. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  390. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  391. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  392. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  393. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  394. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  395. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  396. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  397. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  398. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  399. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  400. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  401. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  402. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  403. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  404. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  405. package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
  406. package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
  407. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  408. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  409. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  410. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  411. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  412. package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
  413. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  414. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
  415. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  416. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  417. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  418. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
  419. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  420. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  421. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  422. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  423. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  424. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  425. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  426. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  427. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +75 -37
  428. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  429. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  430. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  431. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  432. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  433. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  434. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  435. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  436. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  437. package/src/resources/extensions/gsd/tests/preferences.test.ts +34 -9
  438. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -7
  439. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  440. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  441. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  442. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  443. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  444. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  445. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  446. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
  447. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  448. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  449. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  450. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  451. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  452. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  453. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  454. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  455. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  456. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  457. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  458. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  459. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
  460. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
  461. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  462. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
  463. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  464. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  465. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +10 -11
  466. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  467. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  468. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  469. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  470. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  471. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  472. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  473. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  474. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
  475. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  476. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  477. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  478. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  479. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  480. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  481. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  482. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
  483. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
  484. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  485. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  486. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  487. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
  488. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -0
  489. package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -0
  490. package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
  491. package/src/resources/extensions/gsd/workflow-logger.ts +193 -0
  492. package/src/resources/extensions/gsd/worktree-manager.ts +41 -5
  493. package/src/resources/extensions/gsd/worktree-resolver.ts +44 -0
  494. package/src/resources/extensions/mcp-client/index.ts +20 -0
  495. package/src/resources/extensions/voice/index.ts +11 -21
  496. package/src/resources/extensions/voice/linux-ready.ts +87 -0
  497. package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
  498. package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
  499. package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +0 -1
  500. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  501. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  502. package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
  503. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
  504. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → dFMji9G1LZ-Tv36el9pRT}/_buildManifest.js +0 -0
  505. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → dFMji9G1LZ-Tv36el9pRT}/_ssgManifest.js +0 -0
@@ -18,6 +18,9 @@ export const INFRA_ERROR_CODES: ReadonlySet<string> = new Set([
18
18
  "EDQUOT", // disk quota exceeded
19
19
  "EMFILE", // too many open files (process)
20
20
  "ENFILE", // too many open files (system)
21
+ "ECONNREFUSED", // connection refused (offline / local server down)
22
+ "ENOTFOUND", // DNS lookup failed (offline / no network)
23
+ "ENETUNREACH", // network unreachable (offline / no route)
21
24
  ]);
22
25
 
23
26
  /**
@@ -27,7 +27,10 @@ import { debugLog } from "../debug-logger.js";
27
27
  import { gsdRoot } from "../paths.js";
28
28
  import { atomicWriteSync } from "../atomic-write.js";
29
29
  import { PROJECT_FILES } from "../detection.js";
30
+ import { MergeConflictError } from "../git-service.js";
30
31
  import { join } from "node:path";
32
+ import { existsSync, cpSync } from "node:fs";
33
+ import { logWarning, logError } from "../workflow-logger.js";
31
34
 
32
35
  // ─── generateMilestoneReport ──────────────────────────────────────────────────
33
36
 
@@ -162,8 +165,8 @@ export async function runPreDispatch(
162
165
  debugLog("autoLoop", { phase: "exit", reason: "health-gate-failed" });
163
166
  return { action: "break", reason: "health-gate-failed" };
164
167
  }
165
- } catch {
166
- // Non-fatal
168
+ } catch (e) {
169
+ logWarning("engine", "Pre-dispatch health gate threw unexpectedly", { error: String(e) });
167
170
  }
168
171
 
169
172
  // Sync project root artifacts into worktree
@@ -233,26 +236,24 @@ export async function runPreDispatch(
233
236
  loopState.stuckRecoveryAttempts = 0;
234
237
 
235
238
  // Worktree lifecycle on milestone transition — merge current, enter next
236
- deps.resolver.mergeAndExit(s.currentMilestoneId!, ctx.ui);
237
-
238
- // Opt-in: create draft PR on milestone completion
239
- if (prefs?.git?.auto_pr) {
240
- try {
241
- const { createDraftPR } = await import("../git-service.js");
242
- const prUrl = createDraftPR(
243
- s.basePath,
244
- s.currentMilestoneId!,
245
- `[GSD] ${s.currentMilestoneId} complete`,
246
- `Milestone ${s.currentMilestoneId} completed by GSD auto-mode.\n\nSee .gsd/${s.currentMilestoneId}/ for details.`,
239
+ try {
240
+ deps.resolver.mergeAndExit(s.currentMilestoneId!, ctx.ui);
241
+ } catch (mergeErr) {
242
+ if (mergeErr instanceof MergeConflictError) {
243
+ // Real code conflicts — stop the loop instead of retrying forever (#2330)
244
+ ctx.ui.notify(
245
+ `Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`,
246
+ "error",
247
247
  );
248
- if (prUrl) {
249
- ctx.ui.notify(`Draft PR created: ${prUrl}`, "info");
250
- }
251
- } catch {
252
- // Non-fatal — PR creation is best-effort
248
+ await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
249
+ return { action: "break", reason: "merge-conflict" };
253
250
  }
251
+ // Non-conflict merge errors — log and continue
252
+ logWarning("engine", "Milestone merge failed with non-conflict error", { milestone: s.currentMilestoneId!, error: String(mergeErr) });
254
253
  }
255
254
 
255
+ // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
256
+
256
257
  deps.invalidateAllCaches();
257
258
 
258
259
  state = await deps.deriveState(s.basePath);
@@ -279,11 +280,21 @@ export async function runPreDispatch(
279
280
  // Reset completed-units tracking for the new milestone — stale entries
280
281
  // from the previous milestone cause the dispatch loop to skip units
281
282
  // that haven't actually been completed in the new milestone's context.
283
+ // Archive the old completed-units.json instead of wiping it (#2313).
282
284
  s.completedUnits = [];
283
285
  try {
284
286
  const completedKeysPath = join(gsdRoot(s.basePath), "completed-units.json");
287
+ if (existsSync(completedKeysPath) && s.currentMilestoneId) {
288
+ const archivePath = join(
289
+ gsdRoot(s.basePath),
290
+ `completed-units-${s.currentMilestoneId}.json`,
291
+ );
292
+ cpSync(completedKeysPath, archivePath);
293
+ }
285
294
  atomicWriteSync(completedKeysPath, JSON.stringify([], null, 2));
286
- } catch { /* non-fatal */ }
295
+ } catch (e) {
296
+ logWarning("engine", "Failed to archive completed-units on milestone transition", { error: String(e) });
297
+ }
287
298
 
288
299
  // Rebuild STATE.md immediately so it reflects the new active milestone.
289
300
  // This bypasses the 30-second throttle in the normal rebuild path —
@@ -291,8 +302,8 @@ export async function runPreDispatch(
291
302
  // immediate write.
292
303
  try {
293
304
  await deps.rebuildState(s.basePath);
294
- } catch {
295
- // Non-fatal — STATE.md will be rebuilt on the next regular cycle
305
+ } catch (e) {
306
+ logWarning("engine", "STATE.md rebuild failed after milestone transition", { error: String(e) });
296
307
  }
297
308
  }
298
309
 
@@ -322,25 +333,20 @@ export async function runPreDispatch(
322
333
  if (incomplete.length === 0 && state.registry.length > 0) {
323
334
  // All milestones complete — merge milestone branch before stopping
324
335
  if (s.currentMilestoneId) {
325
- deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
326
-
327
- // Opt-in: create draft PR on milestone completion
328
- if (prefs?.git?.auto_pr) {
329
- try {
330
- const { createDraftPR } = await import("../git-service.js");
331
- const prUrl = createDraftPR(
332
- s.basePath,
333
- s.currentMilestoneId,
334
- `[GSD] ${s.currentMilestoneId} complete`,
335
- `Milestone ${s.currentMilestoneId} completed by GSD auto-mode.\n\nSee .gsd/${s.currentMilestoneId}/ for details.`,
336
+ try {
337
+ deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
338
+ } catch (mergeErr) {
339
+ if (mergeErr instanceof MergeConflictError) {
340
+ ctx.ui.notify(
341
+ `Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`,
342
+ "error",
336
343
  );
337
- if (prUrl) {
338
- ctx.ui.notify(`Draft PR created: ${prUrl}`, "info");
339
- }
340
- } catch {
341
- // Non-fatal — PR creation is best-effort
344
+ await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
345
+ return { action: "break", reason: "merge-conflict" };
342
346
  }
343
347
  }
348
+
349
+ // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
344
350
  }
345
351
  deps.sendDesktopNotification(
346
352
  "GSD",
@@ -422,25 +428,20 @@ export async function runPreDispatch(
422
428
  if (state.phase === "complete") {
423
429
  // Milestone merge on complete (before closeout so branch state is clean)
424
430
  if (s.currentMilestoneId) {
425
- deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
426
-
427
- // Opt-in: create draft PR on milestone completion
428
- if (prefs?.git?.auto_pr) {
429
- try {
430
- const { createDraftPR } = await import("../git-service.js");
431
- const prUrl = createDraftPR(
432
- s.basePath,
433
- s.currentMilestoneId,
434
- `[GSD] ${s.currentMilestoneId} complete`,
435
- `Milestone ${s.currentMilestoneId} completed by GSD auto-mode.\n\nSee .gsd/${s.currentMilestoneId}/ for details.`,
431
+ try {
432
+ deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
433
+ } catch (mergeErr) {
434
+ if (mergeErr instanceof MergeConflictError) {
435
+ ctx.ui.notify(
436
+ `Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`,
437
+ "error",
436
438
  );
437
- if (prUrl) {
438
- ctx.ui.notify(`Draft PR created: ${prUrl}`, "info");
439
- }
440
- } catch {
441
- // Non-fatal — PR creation is best-effort
439
+ await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
440
+ return { action: "break", reason: "merge-conflict" };
442
441
  }
443
442
  }
443
+
444
+ // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
444
445
  }
445
446
  deps.sendDesktopNotification(
446
447
  "GSD",
@@ -860,6 +861,7 @@ export async function runUnitPhase(
860
861
  lastProgressAt: s.currentUnit.startedAt,
861
862
  progressCount: 0,
862
863
  lastProgressKind: "dispatch",
864
+ recoveryAttempts: 0, // Reset so re-dispatched units get full recovery budget (#2322)
863
865
  },
864
866
  );
865
867
 
@@ -921,8 +923,8 @@ export async function runUnitPhase(
921
923
  (decisionsContent?.length ?? 0) +
922
924
  (requirementsContent?.length ?? 0) +
923
925
  (projectContent?.length ?? 0);
924
- } catch {
925
- // Non-fatal
926
+ } catch (e) {
927
+ logWarning("engine", "Baseline char count measurement failed", { error: String(e) });
926
928
  }
927
929
  }
928
930
 
@@ -932,9 +934,7 @@ export async function runUnitPhase(
932
934
  } catch (reorderErr) {
933
935
  const msg =
934
936
  reorderErr instanceof Error ? reorderErr.message : String(reorderErr);
935
- process.stderr.write(
936
- `[gsd] prompt reorder failed (non-fatal): ${msg}\n`,
937
- );
937
+ logWarning("engine", "Prompt reorder failed", { error: msg });
938
938
  }
939
939
 
940
940
  // Select and apply model (with tier escalation on retry — normal units only)
@@ -1137,7 +1137,9 @@ export async function runUnitPhase(
1137
1137
  const completedKeysPath = join(gsdRoot(s.basePath), "completed-units.json");
1138
1138
  const keys = s.completedUnits.map((u) => `${u.type}/${u.id}`);
1139
1139
  atomicWriteSync(completedKeysPath, JSON.stringify(keys, null, 2));
1140
- } catch { /* non-fatal: disk flush failure */ }
1140
+ } catch (e) {
1141
+ logWarning("engine", "Failed to flush completed-units to disk", { error: String(e) });
1142
+ }
1141
1143
 
1142
1144
  deps.clearUnitRuntimeRecord(s.basePath, unitType, unitId);
1143
1145
  s.unitDispatchCount.delete(`${unitType}/${unitId}`);
@@ -11,6 +11,7 @@ import { NEW_SESSION_TIMEOUT_MS } from "./session.js";
11
11
  import type { UnitResult } from "./types.js";
12
12
  import { _setCurrentResolve, _setSessionSwitchInFlight } from "./resolve.js";
13
13
  import { debugLog } from "../debug-logger.js";
14
+ import { logWarning, logError } from "../workflow-logger.js";
14
15
 
15
16
  /**
16
17
  * Execute a single unit: create a new session, send the prompt, and await
@@ -85,7 +86,9 @@ export async function runUnit(
85
86
  if (process.cwd() !== s.basePath) {
86
87
  process.chdir(s.basePath);
87
88
  }
88
- } catch { /* non-fatal — chdir may fail if dir was removed */ }
89
+ } catch (e) {
90
+ logWarning("engine", "Failed to chdir to basePath before dispatch", { basePath: s.basePath, error: String(e) });
91
+ }
89
92
 
90
93
  // ── Send the prompt ──
91
94
  debugLog("runUnit", { phase: "send-message", unitType, unitId });
@@ -115,8 +118,8 @@ export async function runUnit(
115
118
  if (typeof cmdCtxAny?.clearQueue === "function") {
116
119
  (cmdCtxAny.clearQueue as () => unknown)();
117
120
  }
118
- } catch {
119
- // Non-fatal clearQueue may not be available in all contexts
121
+ } catch (e) {
122
+ logWarning("engine", "clearQueue failed after unit completion", { error: String(e) });
120
123
  }
121
124
 
122
125
  return result;
@@ -1307,6 +1307,12 @@ export async function buildCompleteMilestonePrompt(
1307
1307
  roadmapPath: roadmapRel,
1308
1308
  inlinedContext,
1309
1309
  milestoneSummaryPath,
1310
+ skillActivation: buildSkillActivationBlock({
1311
+ base,
1312
+ milestoneId: mid,
1313
+ milestoneTitle: midTitle,
1314
+ extraContext: [inlinedContext],
1315
+ }),
1310
1316
  });
1311
1317
  }
1312
1318
 
@@ -1390,6 +1396,12 @@ export async function buildValidateMilestonePrompt(
1390
1396
  inlinedContext,
1391
1397
  validationPath: validationOutputPath,
1392
1398
  remediationRound: String(remediationRound),
1399
+ skillActivation: buildSkillActivationBlock({
1400
+ base,
1401
+ milestoneId: mid,
1402
+ milestoneTitle: midTitle,
1403
+ extraContext: [inlinedContext],
1404
+ }),
1393
1405
  });
1394
1406
  }
1395
1407
 
@@ -1500,6 +1512,12 @@ export async function buildRunUatPrompt(
1500
1512
  uatResultPath,
1501
1513
  uatType,
1502
1514
  inlinedContext,
1515
+ skillActivation: buildSkillActivationBlock({
1516
+ base,
1517
+ milestoneId: mid,
1518
+ sliceId,
1519
+ extraContext: [inlinedContext],
1520
+ }),
1503
1521
  });
1504
1522
  }
1505
1523
 
@@ -1552,11 +1570,16 @@ export async function buildReassessRoadmapPrompt(
1552
1570
  milestoneTitle: midTitle,
1553
1571
  completedSliceId,
1554
1572
  roadmapPath: roadmapRel,
1555
- completedSliceSummaryPath: summaryRel,
1556
1573
  assessmentPath,
1557
1574
  inlinedContext,
1558
1575
  deferredCaptures,
1559
1576
  commitInstruction: reassessCommitInstruction,
1577
+ skillActivation: buildSkillActivationBlock({
1578
+ base,
1579
+ milestoneId: mid,
1580
+ milestoneTitle: midTitle,
1581
+ extraContext: [inlinedContext, deferredCaptures],
1582
+ }),
1560
1583
  });
1561
1584
  }
1562
1585
 
@@ -297,11 +297,14 @@ export async function bootstrapAutoSession(
297
297
  }
298
298
  }
299
299
 
300
- // Milestone branch recovery (#601)
300
+ // Milestone branch recovery (#601, #2358)
301
+ // Detect survivor milestone branches in both pre-planning and complete phases.
302
+ // In phase=complete, the milestone artifacts exist but finalization (merge,
303
+ // worktree cleanup) was never run — the survivor branch must be merged.
301
304
  let hasSurvivorBranch = false;
302
305
  if (
303
306
  state.activeMilestone &&
304
- state.phase === "pre-planning" &&
307
+ (state.phase === "pre-planning" || state.phase === "complete") &&
305
308
  shouldUseWorktreeIsolation() &&
306
309
  !detectWorktreeName(base) &&
307
310
  !base.includes(`${pathSep}.gsd${pathSep}worktrees${pathSep}`)
@@ -343,6 +346,26 @@ export async function bootstrapAutoSession(
343
346
  }
344
347
  }
345
348
 
349
+ // Survivor branch exists and milestone is complete (#2358):
350
+ // The milestone artifacts were written but finalization (merge, worktree
351
+ // cleanup) never ran. Run mergeAndExit to finalize, then re-derive state
352
+ // so the normal "all milestones complete" or "next milestone" path runs.
353
+ if (hasSurvivorBranch && state.phase === "complete") {
354
+ const mid = state.activeMilestone!.id;
355
+ ctx.ui.notify(
356
+ `Milestone ${mid} is complete but branch/worktree was not finalized. Running merge now.`,
357
+ "info",
358
+ );
359
+ const resolver = buildResolver();
360
+ resolver.mergeAndExit(mid, {
361
+ notify: ctx.ui.notify.bind(ctx.ui),
362
+ });
363
+ invalidateAllCaches();
364
+ state = await deriveState(base);
365
+ // Clear survivor flag — finalization is done
366
+ hasSurvivorBranch = false;
367
+ }
368
+
346
369
  if (!hasSurvivorBranch) {
347
370
  // No active work — start a new milestone via discuss flow
348
371
  if (!state.activeMilestone || state.phase === "complete") {
@@ -551,6 +574,20 @@ export async function bootstrapAutoSession(
551
574
  }
552
575
  }
553
576
 
577
+ // Gate: abort bootstrap if the DB file exists but the provider is
578
+ // still unavailable after both open attempts above. Without this,
579
+ // auto-mode starts but every gsd_task_complete / gsd_slice_complete
580
+ // call returns "db_unavailable", triggering artifact-retry which
581
+ // re-dispatches the same task — producing an infinite loop (#2419).
582
+ if (existsSync(gsdDbPath) && !isDbAvailable()) {
583
+ ctx.ui.notify(
584
+ "SQLite database exists but failed to open. Auto-mode cannot proceed without a working database provider. " +
585
+ "Check for corrupt gsd.db or missing native SQLite bindings.",
586
+ "error",
587
+ );
588
+ return releaseLockAndReturn();
589
+ }
590
+
554
591
  // Initialize metrics
555
592
  initMetrics(s.basePath);
556
593
 
@@ -8,6 +8,7 @@
8
8
 
9
9
  import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
10
10
  import { readUnitRuntimeRecord, writeUnitRuntimeRecord } from "./unit-runtime.js";
11
+ import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
11
12
  import { resolveAutoSupervisorConfig } from "./preferences.js";
12
13
  import type { GSDPreferences } from "./preferences.js";
13
14
  import { computeBudgets, resolveExecutorContextWindow } from "./context-budget.js";
@@ -32,6 +33,8 @@ export interface SupervisionContext {
32
33
  buildSnapshotOpts: () => CloseoutOptions & Record<string, unknown>;
33
34
  buildRecoveryContext: () => RecoveryContext;
34
35
  pauseAuto: (ctx?: ExtensionContext, pi?: ExtensionAPI) => Promise<void>;
36
+ /** Optional task estimate string (e.g. "30m", "2h") for timeout scaling (#2243). */
37
+ taskEstimate?: string;
35
38
  }
36
39
 
37
40
  /**
@@ -41,13 +44,71 @@ export interface SupervisionContext {
41
44
  * 3. Hard timeout (pause + recovery)
42
45
  * 4. Context-pressure monitor (continue-here)
43
46
  */
47
+
48
+ /**
49
+ * Parse a task estimate string (e.g. "30m", "2h", "1h30m") into minutes.
50
+ * Returns null if the string cannot be parsed.
51
+ */
52
+ export function parseEstimateMinutes(estimate: string): number | null {
53
+ if (!estimate || typeof estimate !== "string") return null;
54
+ const trimmed = estimate.trim();
55
+ if (!trimmed) return null;
56
+
57
+ let totalMinutes = 0;
58
+ let matched = false;
59
+
60
+ // Match hours component
61
+ const hoursMatch = trimmed.match(/(\d+)\s*h/i);
62
+ if (hoursMatch) {
63
+ totalMinutes += Number(hoursMatch[1]) * 60;
64
+ matched = true;
65
+ }
66
+
67
+ // Match minutes component
68
+ const minutesMatch = trimmed.match(/(\d+)\s*m/i);
69
+ if (minutesMatch) {
70
+ totalMinutes += Number(minutesMatch[1]);
71
+ matched = true;
72
+ }
73
+
74
+ return matched ? totalMinutes : null;
75
+ }
76
+
44
77
  export function startUnitSupervision(sctx: SupervisionContext): void {
45
78
  const { s, ctx, pi, unitType, unitId, prefs, buildSnapshotOpts, buildRecoveryContext, pauseAuto } = sctx;
46
79
 
47
80
  const supervisor = resolveAutoSupervisorConfig();
48
- const softTimeoutMs = (supervisor.soft_timeout_minutes ?? 0) * 60 * 1000;
49
- const idleTimeoutMs = (supervisor.idle_timeout_minutes ?? 0) * 60 * 1000;
50
- const hardTimeoutMs = (supervisor.hard_timeout_minutes ?? 0) * 60 * 1000;
81
+
82
+ // Scale timeouts based on task estimate annotations (#2243).
83
+ // If the task has an est: annotation, use it to extend the hard and soft timeouts
84
+ // so longer tasks don't get prematurely timed out.
85
+ let taskEstimate = sctx.taskEstimate;
86
+ if (!taskEstimate && unitType === "task" && isDbAvailable()) {
87
+ // Look up the task estimate from the DB (#2243).
88
+ try {
89
+ if (s.currentMilestoneId) {
90
+ const slices = getMilestoneSlices(s.currentMilestoneId);
91
+ for (const slice of slices) {
92
+ const tasks = getSliceTasks(s.currentMilestoneId, slice.id);
93
+ const task = tasks.find(t => t.id === unitId);
94
+ if (task?.estimate) {
95
+ taskEstimate = task.estimate;
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ } catch {
101
+ // Non-fatal — fall through with no estimate
102
+ }
103
+ }
104
+ const estimateMinutes = taskEstimate ? parseEstimateMinutes(taskEstimate) : null;
105
+ const timeoutScale = estimateMinutes && estimateMinutes > 0
106
+ ? Math.max(1, estimateMinutes / 10) // 10min task = 1x, 30min = 3x, 2h = 12x
107
+ : 1;
108
+
109
+ const softTimeoutMs = (supervisor.soft_timeout_minutes ?? 0) * 60 * 1000 * timeoutScale;
110
+ const idleTimeoutMs = (supervisor.idle_timeout_minutes ?? 0) * 60 * 1000; // idle not scaled — idle is idle
111
+ const hardTimeoutMs = (supervisor.hard_timeout_minutes ?? 0) * 60 * 1000 * timeoutScale;
51
112
 
52
113
  // ── 1. Soft timeout warning ──
53
114
  s.wrapupWarningHandle = setTimeout(() => {
@@ -93,6 +93,11 @@ export function syncStateToProjectRoot(
93
93
  { force: true },
94
94
  );
95
95
 
96
+ // 3. metrics.json — session cost/token tracking (#2313).
97
+ // Without this, metrics accumulated in the worktree are invisible from the
98
+ // project root and never appear in the dashboard or skill-health reports.
99
+ safeCopy(join(wtGsd, "metrics.json"), join(prGsd, "metrics.json"), { force: true });
100
+
96
101
  // 4. Runtime records — unit dispatch state used by selfHealRuntimeRecords().
97
102
  // Without this, a crash during a unit leaves the runtime record only in the
98
103
  // worktree. If the next session resolves basePath before worktree re-entry,
@@ -42,6 +42,7 @@ import {
42
42
  } from "./worktree.js";
43
43
  import { MergeConflictError, readIntegrationBranch, RUNTIME_EXCLUSION_PATHS } from "./git-service.js";
44
44
  import { debugLog } from "./debug-logger.js";
45
+ import { logWarning } from "./workflow-logger.js";
45
46
  import { loadEffectiveGSDPreferences } from "./preferences.js";
46
47
  import {
47
48
  nativeGetCurrentBranch,
@@ -162,6 +163,7 @@ export function syncGsdStateToWorktree(
162
163
  "OVERRIDES.md",
163
164
  "QUEUE.md",
164
165
  "completed-units.json",
166
+ "metrics.json",
165
167
  ];
166
168
  for (const f of rootFiles) {
167
169
  const src = join(mainGsd, f);
@@ -325,8 +327,9 @@ export function syncWorktreeStateBack(
325
327
  // ── 1. Sync root-level .gsd/ files back ──────────────────────────────
326
328
  // The worktree is authoritative — complete-milestone updates REQUIREMENTS,
327
329
  // PROJECT, etc. These must overwrite main's copies so they survive teardown.
328
- // Also includes QUEUE.md and completed-units.json which are written during
329
- // milestone closeout and lost on teardown without explicit sync (#1787).
330
+ // Also includes QUEUE.md, completed-units.json, and metrics.json which are
331
+ // written during milestone closeout and lost on teardown without explicit sync
332
+ // (#1787, #2313).
330
333
  const rootFiles = [
331
334
  "DECISIONS.md",
332
335
  "REQUIREMENTS.md",
@@ -335,6 +338,7 @@ export function syncWorktreeStateBack(
335
338
  "OVERRIDES.md",
336
339
  "QUEUE.md",
337
340
  "completed-units.json",
341
+ "metrics.json",
338
342
  ];
339
343
  for (const f of rootFiles) {
340
344
  const src = join(wtGsd, f);
@@ -697,7 +701,7 @@ export function createAutoWorktree(
697
701
  const hookError = runWorktreePostCreateHook(basePath, info.path);
698
702
  if (hookError) {
699
703
  // Non-fatal — log but don't prevent worktree usage
700
- console.error(`[GSD] ${hookError}`);
704
+ logWarning("reconcile", hookError, { worktree: info.name });
701
705
  }
702
706
 
703
707
  const previousCwd = process.cwd();
@@ -790,10 +794,12 @@ export function teardownAutoWorktree(
790
794
  // backslashes (#1436), leaving ~1 GB+ orphaned directories.
791
795
  const wtDir = worktreePath(originalBasePath, milestoneId);
792
796
  if (existsSync(wtDir)) {
793
- console.error(
794
- `[GSD] WARNING: Worktree directory still exists after teardown: ${wtDir}\n` +
795
- ` This is likely an orphaned directory consuming disk space.\n` +
796
- ` Remove it manually with: rm -rf "${wtDir.replaceAll("\\", "/")}"`,
797
+ logWarning(
798
+ "reconcile",
799
+ `Worktree directory still exists after teardown: ${wtDir}. ` +
800
+ `This is likely an orphaned directory consuming disk space. ` +
801
+ `Remove it manually with: rm -rf "${wtDir.replaceAll("\\", "/")}"`,
802
+ { worktree: milestoneId },
797
803
  );
798
804
  // Attempt a direct filesystem removal as a fallback
799
805
  try {
@@ -1320,9 +1326,9 @@ export function mergeMilestoneToMain(
1320
1326
  }
1321
1327
  }
1322
1328
 
1323
- // 9b. Auto-create PR if enabled (requires push_branches + push succeeded)
1329
+ // 9b. Auto-create PR if enabled (#2302: no longer gated on pushed/auto_push)
1324
1330
  let prCreated = false;
1325
- if (prefs.auto_pr === true && pushed) {
1331
+ if (prefs.auto_pr === true && !nothingToCommit) {
1326
1332
  const remote = prefs.remote ?? "origin";
1327
1333
  const prTarget = prefs.pr_target_branch ?? mainBranch;
1328
1334
  try {
@@ -1332,9 +1338,9 @@ export function mergeMilestoneToMain(
1332
1338
  stdio: ["ignore", "pipe", "pipe"],
1333
1339
  encoding: "utf-8",
1334
1340
  });
1335
- // Create PR via gh CLI
1341
+ // Create PR via gh CLI with explicit --head and --base (#2302)
1336
1342
  execFileSync("gh", [
1337
- "pr", "create",
1343
+ "pr", "create", "--draft",
1338
1344
  "--base", prTarget,
1339
1345
  "--head", milestoneBranch,
1340
1346
  "--title", `Milestone ${milestoneId} complete`,
@@ -250,9 +250,9 @@ const STATE_REBUILD_MIN_INTERVAL_MS = 30_000;
250
250
 
251
251
  export function shouldUseWorktreeIsolation(): boolean {
252
252
  const prefs = loadEffectiveGSDPreferences()?.preferences?.git;
253
- if (prefs?.isolation === "none") return false;
254
- if (prefs?.isolation === "branch") return false;
255
- return true; // default: worktree
253
+ if (prefs?.isolation === "worktree") return true;
254
+ // Default is false — worktree isolation requires explicit opt-in
255
+ return false;
256
256
  }
257
257
 
258
258
  /** Crash recovery prompt — set by startAuto, consumed by the main loop */
@@ -610,14 +610,48 @@ export async function stopAuto(
610
610
  }
611
611
 
612
612
  // ── Step 4: Auto-worktree exit ──
613
+ // When the milestone is complete (has a SUMMARY), merge the worktree branch
614
+ // back to main so code isn't stranded on the worktree branch (#2317).
615
+ // For incomplete milestones, preserve the branch for later resumption.
613
616
  try {
614
617
  if (s.currentMilestoneId) {
615
618
  const notifyCtx = ctx
616
619
  ? { notify: ctx.ui.notify.bind(ctx.ui) }
617
620
  : { notify: () => {} };
618
- buildResolver().exitMilestone(s.currentMilestoneId, notifyCtx, {
619
- preserveBranch: true,
620
- });
621
+ const resolver = buildResolver();
622
+
623
+ // Check if the milestone is complete — SUMMARY file is the authoritative signal.
624
+ let milestoneComplete = false;
625
+ try {
626
+ const summaryPath = resolveMilestoneFile(
627
+ s.originalBasePath || s.basePath,
628
+ s.currentMilestoneId,
629
+ "SUMMARY",
630
+ );
631
+ if (!summaryPath) {
632
+ // Also check in the worktree path (SUMMARY may not be synced yet)
633
+ const wtSummaryPath = resolveMilestoneFile(
634
+ s.basePath,
635
+ s.currentMilestoneId,
636
+ "SUMMARY",
637
+ );
638
+ milestoneComplete = wtSummaryPath !== null;
639
+ } else {
640
+ milestoneComplete = true;
641
+ }
642
+ } catch {
643
+ // Non-fatal — fall through to preserveBranch path
644
+ }
645
+
646
+ if (milestoneComplete) {
647
+ // Milestone is complete — merge worktree branch back to main
648
+ resolver.mergeAndExit(s.currentMilestoneId, notifyCtx);
649
+ } else {
650
+ // Milestone still in progress — preserve branch for later resumption
651
+ resolver.exitMilestone(s.currentMilestoneId, notifyCtx, {
652
+ preserveBranch: true,
653
+ });
654
+ }
621
655
  }
622
656
  } catch (e) {
623
657
  debugLog("stop-cleanup-worktree", { error: e instanceof Error ? e.message : String(e) });