gsd-pi 2.44.0-dev.d25d507 → 2.45.0-dev.1afbdaa

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 (407) hide show
  1. package/dist/help-text.js +1 -1
  2. package/dist/loader.js +34 -0
  3. package/dist/resources/extensions/gsd/activity-log.js +7 -0
  4. package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
  5. package/dist/resources/extensions/gsd/auto/phases.js +63 -77
  6. package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
  7. package/dist/resources/extensions/gsd/auto/session.js +0 -11
  8. package/dist/resources/extensions/gsd/auto-artifact-paths.js +112 -0
  9. package/dist/resources/extensions/gsd/auto-post-unit.js +25 -96
  10. package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
  11. package/dist/resources/extensions/gsd/auto-start.js +23 -5
  12. package/dist/resources/extensions/gsd/auto-timers.js +57 -3
  13. package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
  14. package/dist/resources/extensions/gsd/auto-worktree.js +14 -10
  15. package/dist/resources/extensions/gsd/auto.js +42 -60
  16. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +170 -11
  17. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +18 -0
  18. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  19. package/dist/resources/extensions/gsd/commands/context.js +0 -4
  20. package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
  21. package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
  22. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +1 -1
  23. package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
  24. package/dist/resources/extensions/gsd/crash-recovery.js +2 -4
  25. package/dist/resources/extensions/gsd/dashboard-overlay.js +0 -44
  26. package/dist/resources/extensions/gsd/db-writer.js +40 -22
  27. package/dist/resources/extensions/gsd/doctor-checks.js +167 -2
  28. package/dist/resources/extensions/gsd/doctor.js +13 -3
  29. package/dist/resources/extensions/gsd/git-service.js +8 -3
  30. package/dist/resources/extensions/gsd/gsd-db.js +28 -4
  31. package/dist/resources/extensions/gsd/guided-flow.js +1 -2
  32. package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
  33. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  34. package/dist/resources/extensions/gsd/parallel-orchestrator.js +5 -18
  35. package/dist/resources/extensions/gsd/preferences-types.js +2 -2
  36. package/dist/resources/extensions/gsd/preferences.js +8 -4
  37. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
  38. package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  39. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
  40. package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -15
  41. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  42. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  43. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  44. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  45. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  46. package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -3
  47. package/dist/resources/extensions/gsd/prompts/queue.md +2 -2
  48. package/dist/resources/extensions/gsd/prompts/quick-task.md +2 -0
  49. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  50. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  51. package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  52. package/dist/resources/extensions/gsd/prompts/research-slice.md +3 -3
  53. package/dist/resources/extensions/gsd/prompts/rethink.md +83 -0
  54. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  55. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  56. package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
  57. package/dist/resources/extensions/gsd/repo-identity.js +45 -7
  58. package/dist/resources/extensions/gsd/rethink.js +115 -0
  59. package/dist/resources/extensions/gsd/session-lock.js +1 -3
  60. package/dist/resources/extensions/gsd/state.js +48 -3
  61. package/dist/resources/extensions/gsd/sync-lock.js +89 -0
  62. package/dist/resources/extensions/gsd/tools/complete-milestone.js +61 -11
  63. package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -11
  64. package/dist/resources/extensions/gsd/tools/complete-task.js +50 -2
  65. package/dist/resources/extensions/gsd/tools/plan-milestone.js +37 -1
  66. package/dist/resources/extensions/gsd/tools/plan-slice.js +31 -1
  67. package/dist/resources/extensions/gsd/tools/plan-task.js +28 -1
  68. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +32 -2
  69. package/dist/resources/extensions/gsd/tools/reopen-slice.js +86 -0
  70. package/dist/resources/extensions/gsd/tools/reopen-task.js +90 -0
  71. package/dist/resources/extensions/gsd/tools/replan-slice.js +34 -2
  72. package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
  73. package/dist/resources/extensions/gsd/unit-ownership.js +85 -0
  74. package/dist/resources/extensions/gsd/workflow-events.js +102 -0
  75. package/dist/resources/extensions/gsd/workflow-logger.js +193 -0
  76. package/dist/resources/extensions/gsd/workflow-manifest.js +244 -0
  77. package/dist/resources/extensions/gsd/workflow-migration.js +280 -0
  78. package/dist/resources/extensions/gsd/workflow-projections.js +373 -0
  79. package/dist/resources/extensions/gsd/workflow-reconcile.js +411 -0
  80. package/dist/resources/extensions/gsd/worktree-manager.js +34 -3
  81. package/dist/resources/extensions/gsd/worktree-resolver.js +43 -0
  82. package/dist/resources/extensions/gsd/write-intercept.js +84 -0
  83. package/dist/resources/extensions/mcp-client/index.js +14 -0
  84. package/dist/resources/extensions/voice/index.js +11 -16
  85. package/dist/resources/extensions/voice/linux-ready.js +67 -0
  86. package/dist/web/standalone/.next/BUILD_ID +1 -1
  87. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  88. package/dist/web/standalone/.next/build-manifest.json +3 -3
  89. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  90. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  91. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  93. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found/page.js +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  110. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  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_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/index.html +1 -1
  151. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  152. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  153. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  154. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  155. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  156. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  157. package/dist/web/standalone/.next/server/app/page.js +1 -1
  158. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  160. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  163. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  164. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  165. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +9 -0
  166. package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
  167. package/dist/web/standalone/.next/static/chunks/app/{page-b9367c5ae13b99c6.js → page-6654a8cca61a3d1c.js} +1 -1
  168. package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
  169. package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
  170. package/package.json +2 -1
  171. package/packages/native/dist/stream-process/index.js +2 -2
  172. package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
  173. package/packages/native/src/stream-process/index.ts +2 -2
  174. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
  175. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  176. package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
  177. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  178. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
  180. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
  182. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +4 -0
  185. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +10 -5
  187. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -1
  188. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts +2 -0
  189. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts.map +1 -0
  190. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js +185 -0
  191. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js.map +1 -0
  192. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
  193. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
  194. package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
  195. package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
  196. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +239 -10
  197. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +13 -1
  199. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  200. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  201. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
  203. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  205. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  206. package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
  207. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  209. package/packages/pi-coding-agent/dist/main.js +17 -0
  210. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
  212. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
  215. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  217. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
  218. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  220. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  221. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  222. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
  224. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
  225. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
  226. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
  227. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  228. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
  229. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  230. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
  231. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  232. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
  233. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  234. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  235. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
  236. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  237. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  238. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
  239. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  240. package/packages/pi-coding-agent/package.json +1 -1
  241. package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
  242. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
  243. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
  244. package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
  245. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
  246. package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
  247. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
  248. package/packages/pi-coding-agent/src/core/model-registry.ts +51 -4
  249. package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
  250. package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
  251. package/packages/pi-coding-agent/src/main.ts +19 -0
  252. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
  253. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
  254. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  255. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
  256. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
  257. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
  258. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
  259. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
  260. package/pkg/package.json +1 -1
  261. package/src/resources/extensions/gsd/activity-log.ts +1 -0
  262. package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
  263. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -19
  264. package/src/resources/extensions/gsd/auto/phases.ts +69 -91
  265. package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
  266. package/src/resources/extensions/gsd/auto/session.ts +0 -18
  267. package/src/resources/extensions/gsd/auto-artifact-paths.ts +131 -0
  268. package/src/resources/extensions/gsd/auto-dashboard.ts +0 -1
  269. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -106
  270. package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
  271. package/src/resources/extensions/gsd/auto-start.ts +26 -5
  272. package/src/resources/extensions/gsd/auto-timers.ts +64 -3
  273. package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
  274. package/src/resources/extensions/gsd/auto-worktree.ts +17 -11
  275. package/src/resources/extensions/gsd/auto.ts +44 -86
  276. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +162 -11
  277. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
  278. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  279. package/src/resources/extensions/gsd/commands/context.ts +0 -5
  280. package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
  281. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  282. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +1 -1
  283. package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
  284. package/src/resources/extensions/gsd/crash-recovery.ts +1 -5
  285. package/src/resources/extensions/gsd/dashboard-overlay.ts +0 -50
  286. package/src/resources/extensions/gsd/db-writer.ts +41 -27
  287. package/src/resources/extensions/gsd/doctor-checks.ts +180 -2
  288. package/src/resources/extensions/gsd/doctor-types.ts +7 -1
  289. package/src/resources/extensions/gsd/doctor.ts +13 -4
  290. package/src/resources/extensions/gsd/git-service.ts +6 -2
  291. package/src/resources/extensions/gsd/gsd-db.ts +32 -4
  292. package/src/resources/extensions/gsd/guided-flow.ts +1 -2
  293. package/src/resources/extensions/gsd/journal.ts +6 -1
  294. package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
  295. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  296. package/src/resources/extensions/gsd/parallel-orchestrator.ts +5 -21
  297. package/src/resources/extensions/gsd/preferences-types.ts +2 -2
  298. package/src/resources/extensions/gsd/preferences.ts +7 -3
  299. package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
  300. package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  301. package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
  302. package/src/resources/extensions/gsd/prompts/execute-task.md +5 -15
  303. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  304. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  305. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  306. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  307. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  308. package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -3
  309. package/src/resources/extensions/gsd/prompts/queue.md +2 -2
  310. package/src/resources/extensions/gsd/prompts/quick-task.md +2 -0
  311. package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  312. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  313. package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  314. package/src/resources/extensions/gsd/prompts/research-slice.md +3 -3
  315. package/src/resources/extensions/gsd/prompts/rethink.md +83 -0
  316. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  317. package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  318. package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
  319. package/src/resources/extensions/gsd/repo-identity.ts +46 -7
  320. package/src/resources/extensions/gsd/rethink.ts +154 -0
  321. package/src/resources/extensions/gsd/session-lock.ts +0 -4
  322. package/src/resources/extensions/gsd/state.ts +49 -1
  323. package/src/resources/extensions/gsd/sync-lock.ts +94 -0
  324. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +5 -13
  325. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +6 -10
  326. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
  327. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +96 -0
  328. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +264 -228
  329. package/src/resources/extensions/gsd/tests/complete-task.test.ts +317 -250
  330. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
  331. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +2 -8
  332. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -3
  333. package/src/resources/extensions/gsd/tests/db-writer.test.ts +79 -0
  334. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
  335. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +60 -0
  336. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
  337. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  338. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +1 -1
  339. package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
  340. package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
  341. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +15 -24
  342. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
  343. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
  344. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  345. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  346. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
  347. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +8 -9
  348. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +42 -3
  349. package/src/resources/extensions/gsd/tests/parallel-budget-atomicity.test.ts +0 -1
  350. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +0 -7
  351. package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +7 -8
  352. package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +20 -24
  353. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +0 -2
  354. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +9 -6
  355. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +171 -0
  356. package/src/resources/extensions/gsd/tests/preferences.test.ts +7 -9
  357. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +174 -0
  358. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +26 -21
  359. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
  360. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +155 -0
  361. package/src/resources/extensions/gsd/tests/reopen-task.test.ts +165 -0
  362. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +1 -4
  363. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
  364. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +2 -3
  365. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
  366. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +122 -0
  367. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
  368. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
  369. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +175 -0
  370. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +205 -0
  371. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
  372. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +186 -0
  373. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +171 -0
  374. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
  375. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
  376. package/src/resources/extensions/gsd/tests/write-intercept.test.ts +76 -0
  377. package/src/resources/extensions/gsd/tools/complete-milestone.ts +74 -11
  378. package/src/resources/extensions/gsd/tools/complete-slice.ts +68 -11
  379. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -1
  380. package/src/resources/extensions/gsd/tools/plan-milestone.ts +45 -0
  381. package/src/resources/extensions/gsd/tools/plan-slice.ts +40 -0
  382. package/src/resources/extensions/gsd/tools/plan-task.ts +37 -1
  383. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +39 -1
  384. package/src/resources/extensions/gsd/tools/reopen-slice.ts +125 -0
  385. package/src/resources/extensions/gsd/tools/reopen-task.ts +129 -0
  386. package/src/resources/extensions/gsd/tools/replan-slice.ts +41 -1
  387. package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
  388. package/src/resources/extensions/gsd/types.ts +8 -0
  389. package/src/resources/extensions/gsd/unit-ownership.ts +104 -0
  390. package/src/resources/extensions/gsd/workflow-events.ts +154 -0
  391. package/src/resources/extensions/gsd/workflow-logger.ts +243 -0
  392. package/src/resources/extensions/gsd/workflow-manifest.ts +334 -0
  393. package/src/resources/extensions/gsd/workflow-migration.ts +345 -0
  394. package/src/resources/extensions/gsd/workflow-projections.ts +425 -0
  395. package/src/resources/extensions/gsd/workflow-reconcile.ts +503 -0
  396. package/src/resources/extensions/gsd/worktree-manager.ts +41 -5
  397. package/src/resources/extensions/gsd/worktree-resolver.ts +44 -0
  398. package/src/resources/extensions/gsd/write-intercept.ts +90 -0
  399. package/src/resources/extensions/mcp-client/index.ts +20 -0
  400. package/src/resources/extensions/voice/index.ts +11 -21
  401. package/src/resources/extensions/voice/linux-ready.ts +87 -0
  402. package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
  403. package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
  404. package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
  405. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
  406. /package/dist/web/standalone/.next/static/{tokoGmfkYfWf1_Yl_Gz7i → j-BskPs0nxxPeYY-bSrab}/_buildManifest.js +0 -0
  407. /package/dist/web/standalone/.next/static/{tokoGmfkYfWf1_Yl_Gz7i → j-BskPs0nxxPeYY-bSrab}/_ssgManifest.js +0 -0
package/dist/help-text.js CHANGED
@@ -32,7 +32,7 @@ const SUBCOMMAND_HELP = {
32
32
  install: [
33
33
  'Usage: gsd install <source> [-l, --local]',
34
34
  '',
35
- 'Install a package/extension source and run declared lifecycle hooks.',
35
+ 'Install a package/extension source and run post-install validation (dependency checks, setup).',
36
36
  '',
37
37
  'Examples:',
38
38
  ' gsd install npm:@foo/bar',
package/dist/loader.js CHANGED
@@ -26,6 +26,40 @@ if (firstArg === '--help' || firstArg === '-h') {
26
26
  printHelp(gsdVersion);
27
27
  process.exit(0);
28
28
  }
29
+ // ---------------------------------------------------------------------------
30
+ // Runtime dependency checks — fail fast with clear diagnostics before any
31
+ // heavy imports. Reads minimum Node version from the engines field in
32
+ // package.json (already parsed above) and verifies git is available.
33
+ // ---------------------------------------------------------------------------
34
+ {
35
+ const MIN_NODE_MAJOR = 22;
36
+ const red = '\x1b[31m';
37
+ const bold = '\x1b[1m';
38
+ const dim = '\x1b[2m';
39
+ const reset = '\x1b[0m';
40
+ // -- Node version --
41
+ const nodeMajor = parseInt(process.versions.node.split('.')[0], 10);
42
+ if (nodeMajor < MIN_NODE_MAJOR) {
43
+ process.stderr.write(`\n${red}${bold}Error:${reset} GSD requires Node.js >= ${MIN_NODE_MAJOR}.0.0\n` +
44
+ ` You are running Node.js ${process.versions.node}\n\n` +
45
+ `${dim}Install a supported version:${reset}\n` +
46
+ ` nvm install ${MIN_NODE_MAJOR} ${dim}# if using nvm${reset}\n` +
47
+ ` fnm install ${MIN_NODE_MAJOR} ${dim}# if using fnm${reset}\n` +
48
+ ` brew install node@${MIN_NODE_MAJOR} ${dim}# macOS Homebrew${reset}\n\n`);
49
+ process.exit(1);
50
+ }
51
+ // -- git --
52
+ try {
53
+ const { execFileSync } = await import('child_process');
54
+ execFileSync('git', ['--version'], { stdio: 'ignore' });
55
+ }
56
+ catch {
57
+ process.stderr.write(`\n${red}${bold}Error:${reset} GSD requires git but it was not found on PATH.\n\n` +
58
+ `${dim}Install git:${reset}\n` +
59
+ ` https://git-scm.com/downloads\n\n`);
60
+ process.exit(1);
61
+ }
62
+ }
29
63
  import { agentDir, appRoot } from './app-paths.js';
30
64
  import { serializeBundledExtensionPaths } from './bundled-extension-paths.js';
31
65
  import { discoverExtensionEntryPaths } from './extension-discovery.js';
@@ -134,6 +134,13 @@ export function pruneActivityLogs(activityDir, retentionDays) {
134
134
  for (const entry of entries) {
135
135
  if (entry.seq === maxSeq)
136
136
  continue; // always preserve highest-seq
137
+ if (retentionDays === 0) {
138
+ try {
139
+ unlinkSync(entry.filePath);
140
+ }
141
+ catch { /* skip */ }
142
+ continue;
143
+ }
137
144
  try {
138
145
  const mtime = statSync(entry.filePath).mtimeMs;
139
146
  if (Math.floor(mtime) <= cutoff)
@@ -17,6 +17,9 @@ export const INFRA_ERROR_CODES = new Set([
17
17
  "EDQUOT", // disk quota exceeded
18
18
  "EMFILE", // too many open files (process)
19
19
  "ENFILE", // too many open files (system)
20
+ "ECONNREFUSED", // connection refused (offline / local server down)
21
+ "ENOTFOUND", // DNS lookup failed (offline / no network)
22
+ "ENETUNREACH", // network unreachable (offline / no route)
20
23
  ]);
21
24
  /**
22
25
  * Detect whether an error is an unrecoverable infrastructure failure.
@@ -11,10 +11,15 @@ import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, } from "./types.js";
11
11
  import { detectStuck } from "./detect-stuck.js";
12
12
  import { runUnit } from "./run-unit.js";
13
13
  import { debugLog } from "../debug-logger.js";
14
- import { gsdRoot } from "../paths.js";
15
- import { atomicWriteSync } from "../atomic-write.js";
16
14
  import { PROJECT_FILES } from "../detection.js";
15
+ import { MergeConflictError } from "../git-service.js";
17
16
  import { join } from "node:path";
17
+ import { existsSync, cpSync } from "node:fs";
18
+ import { logWarning } from "../workflow-logger.js";
19
+ import { gsdRoot } from "../paths.js";
20
+ import { atomicWriteSync } from "../atomic-write.js";
21
+ import { verifyExpectedArtifact } from "../auto-recovery.js";
22
+ import { writeUnitRuntimeRecord } from "../unit-runtime.js";
18
23
  // ─── generateMilestoneReport ──────────────────────────────────────────────────
19
24
  /**
20
25
  * Generate and write an HTML milestone report snapshot.
@@ -100,8 +105,8 @@ export async function runPreDispatch(ic, loopState) {
100
105
  return { action: "break", reason: "health-gate-failed" };
101
106
  }
102
107
  }
103
- catch {
104
- // Non-fatal
108
+ catch (e) {
109
+ logWarning("engine", "Pre-dispatch health gate threw unexpectedly", { error: String(e) });
105
110
  }
106
111
  // Sync project root artifacts into worktree
107
112
  if (s.originalBasePath &&
@@ -145,20 +150,20 @@ export async function runPreDispatch(ic, loopState) {
145
150
  loopState.recentUnits.length = 0;
146
151
  loopState.stuckRecoveryAttempts = 0;
147
152
  // Worktree lifecycle on milestone transition — merge current, enter next
148
- deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
149
- // Opt-in: create draft PR on milestone completion
150
- if (prefs?.git?.auto_pr) {
151
- try {
152
- const { createDraftPR } = await import("../git-service.js");
153
- const prUrl = createDraftPR(s.basePath, s.currentMilestoneId, `[GSD] ${s.currentMilestoneId} complete`, `Milestone ${s.currentMilestoneId} completed by GSD auto-mode.\n\nSee .gsd/${s.currentMilestoneId}/ for details.`);
154
- if (prUrl) {
155
- ctx.ui.notify(`Draft PR created: ${prUrl}`, "info");
156
- }
157
- }
158
- catch {
159
- // Non-fatal — PR creation is best-effort
153
+ try {
154
+ deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
155
+ }
156
+ catch (mergeErr) {
157
+ if (mergeErr instanceof MergeConflictError) {
158
+ // Real code conflicts stop the loop instead of retrying forever (#2330)
159
+ ctx.ui.notify(`Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`, "error");
160
+ await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
161
+ return { action: "break", reason: "merge-conflict" };
160
162
  }
163
+ // Non-conflict merge errors — log and continue
164
+ logWarning("engine", "Milestone merge failed with non-conflict error", { milestone: s.currentMilestoneId, error: String(mergeErr) });
161
165
  }
166
+ // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
162
167
  deps.invalidateAllCaches();
163
168
  state = await deps.deriveState(s.basePath);
164
169
  mid = state.activeMilestone?.id;
@@ -176,15 +181,18 @@ export async function runPreDispatch(ic, loopState) {
176
181
  .filter((m) => m.status !== "complete" && m.status !== "parked")
177
182
  .map((m) => m.id);
178
183
  deps.pruneQueueOrder(s.basePath, pendingIds);
179
- // Reset completed-units tracking for the new milestone — stale entries
180
- // from the previous milestone cause the dispatch loop to skip units
181
- // that haven't actually been completed in the new milestone's context.
182
- s.completedUnits = [];
184
+ // Archive the old completed-units.json instead of wiping it (#2313).
183
185
  try {
184
186
  const completedKeysPath = join(gsdRoot(s.basePath), "completed-units.json");
187
+ if (existsSync(completedKeysPath) && s.currentMilestoneId) {
188
+ const archivePath = join(gsdRoot(s.basePath), `completed-units-${s.currentMilestoneId}.json`);
189
+ cpSync(completedKeysPath, archivePath);
190
+ }
185
191
  atomicWriteSync(completedKeysPath, JSON.stringify([], null, 2));
186
192
  }
187
- catch { /* non-fatal */ }
193
+ catch (e) {
194
+ logWarning("engine", "Failed to archive completed-units on milestone transition", { error: String(e) });
195
+ }
188
196
  // Rebuild STATE.md immediately so it reflects the new active milestone.
189
197
  // This bypasses the 30-second throttle in the normal rebuild path —
190
198
  // milestone transitions are rare and important enough to warrant an
@@ -192,8 +200,8 @@ export async function runPreDispatch(ic, loopState) {
192
200
  try {
193
201
  await deps.rebuildState(s.basePath);
194
202
  }
195
- catch {
196
- // Non-fatal — STATE.md will be rebuilt on the next regular cycle
203
+ catch (e) {
204
+ logWarning("engine", "STATE.md rebuild failed after milestone transition", { error: String(e) });
197
205
  }
198
206
  }
199
207
  if (mid) {
@@ -209,20 +217,17 @@ export async function runPreDispatch(ic, loopState) {
209
217
  if (incomplete.length === 0 && state.registry.length > 0) {
210
218
  // All milestones complete — merge milestone branch before stopping
211
219
  if (s.currentMilestoneId) {
212
- deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
213
- // Opt-in: create draft PR on milestone completion
214
- if (prefs?.git?.auto_pr) {
215
- try {
216
- const { createDraftPR } = await import("../git-service.js");
217
- const prUrl = createDraftPR(s.basePath, s.currentMilestoneId, `[GSD] ${s.currentMilestoneId} complete`, `Milestone ${s.currentMilestoneId} completed by GSD auto-mode.\n\nSee .gsd/${s.currentMilestoneId}/ for details.`);
218
- if (prUrl) {
219
- ctx.ui.notify(`Draft PR created: ${prUrl}`, "info");
220
- }
221
- }
222
- catch {
223
- // Non-fatal — PR creation is best-effort
220
+ try {
221
+ deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
222
+ }
223
+ catch (mergeErr) {
224
+ if (mergeErr instanceof MergeConflictError) {
225
+ ctx.ui.notify(`Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`, "error");
226
+ await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
227
+ return { action: "break", reason: "merge-conflict" };
224
228
  }
225
229
  }
230
+ // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
226
231
  }
227
232
  deps.sendDesktopNotification("GSD", "All milestones complete!", "success", "milestone");
228
233
  deps.logCmuxEvent(prefs, "All milestones complete.", "success");
@@ -277,20 +282,17 @@ export async function runPreDispatch(ic, loopState) {
277
282
  if (state.phase === "complete") {
278
283
  // Milestone merge on complete (before closeout so branch state is clean)
279
284
  if (s.currentMilestoneId) {
280
- deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
281
- // Opt-in: create draft PR on milestone completion
282
- if (prefs?.git?.auto_pr) {
283
- try {
284
- const { createDraftPR } = await import("../git-service.js");
285
- const prUrl = createDraftPR(s.basePath, s.currentMilestoneId, `[GSD] ${s.currentMilestoneId} complete`, `Milestone ${s.currentMilestoneId} completed by GSD auto-mode.\n\nSee .gsd/${s.currentMilestoneId}/ for details.`);
286
- if (prUrl) {
287
- ctx.ui.notify(`Draft PR created: ${prUrl}`, "info");
288
- }
289
- }
290
- catch {
291
- // Non-fatal — PR creation is best-effort
285
+ try {
286
+ deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
287
+ }
288
+ catch (mergeErr) {
289
+ if (mergeErr instanceof MergeConflictError) {
290
+ ctx.ui.notify(`Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`, "error");
291
+ await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
292
+ return { action: "break", reason: "merge-conflict" };
292
293
  }
293
294
  }
295
+ // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
294
296
  }
295
297
  deps.sendDesktopNotification("GSD", `Milestone ${mid} complete!`, "success", "milestone");
296
298
  deps.logCmuxEvent(prefs, `Milestone ${mid} complete.`, "success");
@@ -364,7 +366,7 @@ export async function runDispatch(ic, preData, loopState) {
364
366
  if (loopState.stuckRecoveryAttempts === 0) {
365
367
  // Level 1: try verifying the artifact, then cache invalidation + retry
366
368
  loopState.stuckRecoveryAttempts++;
367
- const artifactExists = deps.verifyExpectedArtifact(unitType, unitId, s.basePath);
369
+ const artifactExists = verifyExpectedArtifact(unitType, unitId, s.basePath);
368
370
  if (artifactExists) {
369
371
  debugLog("autoLoop", {
370
372
  phase: "stuck-recovery",
@@ -584,13 +586,14 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
584
586
  const unitStartSeq = ic.nextSeq();
585
587
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: unitStartSeq, eventType: "unit-start", data: { unitType, unitId } });
586
588
  deps.captureAvailableSkills();
587
- deps.writeUnitRuntimeRecord(s.basePath, unitType, unitId, s.currentUnit.startedAt, {
589
+ writeUnitRuntimeRecord(s.basePath, unitType, unitId, s.currentUnit.startedAt, {
588
590
  phase: "dispatched",
589
591
  wrapupWarningSent: false,
590
592
  timeoutAt: null,
591
593
  lastProgressAt: s.currentUnit.startedAt,
592
594
  progressCount: 0,
593
595
  lastProgressKind: "dispatch",
596
+ recoveryAttempts: 0, // Reset so re-dispatched units get full recovery budget (#2322)
594
597
  });
595
598
  // Status bar + progress widget
596
599
  ctx.ui.setStatus("gsd-auto", "auto");
@@ -643,8 +646,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
643
646
  (requirementsContent?.length ?? 0) +
644
647
  (projectContent?.length ?? 0);
645
648
  }
646
- catch {
647
- // Non-fatal
649
+ catch (e) {
650
+ logWarning("engine", "Baseline char count measurement failed", { error: String(e) });
648
651
  }
649
652
  }
650
653
  // Cache-optimize prompt section ordering
@@ -653,7 +656,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
653
656
  }
654
657
  catch (reorderErr) {
655
658
  const msg = reorderErr instanceof Error ? reorderErr.message : String(reorderErr);
656
- process.stderr.write(`[gsd] prompt reorder failed (non-fatal): ${msg}\n`);
659
+ logWarning("engine", "Prompt reorder failed", { error: msg });
657
660
  }
658
661
  // Select and apply model (with tier escalation on retry — normal units only)
659
662
  const modelResult = await deps.selectAndApplyModel(ctx, pi, unitType, unitId, s.basePath, prefs, s.verbose, s.autoModeStartModel, sidecarItem ? undefined : { isRetry, previousTier });
@@ -698,7 +701,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
698
701
  });
699
702
  // Write preliminary lock (no session path yet — runUnit creates a new session).
700
703
  // Crash recovery can still identify the in-flight unit from this lock.
701
- deps.writeLock(deps.lockBase(), unitType, unitId, s.completedUnits.length);
704
+ deps.writeLock(deps.lockBase(), unitType, unitId);
702
705
  debugLog("autoLoop", {
703
706
  phase: "runUnit-start",
704
707
  iteration: ic.iteration,
@@ -715,8 +718,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
715
718
  });
716
719
  // Now that runUnit has called newSession(), the session file path is correct.
717
720
  const sessionFile = deps.getSessionFile(ctx);
718
- deps.updateSessionLock(deps.lockBase(), unitType, unitId, s.completedUnits.length, sessionFile);
719
- deps.writeLock(deps.lockBase(), unitType, unitId, s.completedUnits.length, sessionFile);
721
+ deps.updateSessionLock(deps.lockBase(), unitType, unitId, sessionFile);
722
+ deps.writeLock(deps.lockBase(), unitType, unitId, sessionFile);
720
723
  // Tag the most recent window entry with error info for stuck detection
721
724
  if (unitResult.status === "error" || unitResult.status === "cancelled") {
722
725
  const lastEntry = loopState.recentUnits[loopState.recentUnits.length - 1];
@@ -760,8 +763,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
760
763
  warning: "Task completed with 0 tool calls — likely hallucinated, marking as failed",
761
764
  });
762
765
  ctx.ui.notify(`${unitType} ${unitId} completed with 0 tool calls — hallucinated summary, will retry`, "warning");
763
- // Do NOT add to completedUnits fall through to next iteration
764
- // where dispatch will re-derive and re-dispatch this task.
766
+ // Fall through to next iteration where dispatch will re-derive
767
+ // and re-dispatch this task.
765
768
  return { action: "next", data: { unitStartedAt: s.currentUnit.startedAt } };
766
769
  }
767
770
  }
@@ -771,25 +774,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
771
774
  }
772
775
  const skipArtifactVerification = unitType.startsWith("hook/") || unitType === "custom-step";
773
776
  const artifactVerified = skipArtifactVerification ||
774
- deps.verifyExpectedArtifact(unitType, unitId, s.basePath);
777
+ verifyExpectedArtifact(unitType, unitId, s.basePath);
775
778
  if (artifactVerified) {
776
- s.completedUnits.push({
777
- type: unitType,
778
- id: unitId,
779
- startedAt: s.currentUnit.startedAt,
780
- finishedAt: Date.now(),
781
- });
782
- if (s.completedUnits.length > 200) {
783
- s.completedUnits = s.completedUnits.slice(-200);
784
- }
785
- // Flush completed-units to disk so the record survives crashes
786
- try {
787
- const completedKeysPath = join(gsdRoot(s.basePath), "completed-units.json");
788
- const keys = s.completedUnits.map((u) => `${u.type}/${u.id}`);
789
- atomicWriteSync(completedKeysPath, JSON.stringify(keys, null, 2));
790
- }
791
- catch { /* non-fatal: disk flush failure */ }
792
- deps.clearUnitRuntimeRecord(s.basePath, unitType, unitId);
793
779
  s.unitDispatchCount.delete(`${unitType}/${unitId}`);
794
780
  s.unitRecoveryCount.delete(`${unitType}/${unitId}`);
795
781
  }
@@ -822,8 +808,8 @@ export async function runFinalize(ic, iterData, sidecarItem) {
822
808
  // Sidecar items use lightweight pre-verification opts
823
809
  const preVerificationOpts = sidecarItem
824
810
  ? sidecarItem.kind === "hook"
825
- ? { skipSettleDelay: true, skipDoctor: true, skipStateRebuild: true, skipWorktreeSync: true }
826
- : { skipSettleDelay: true, skipStateRebuild: true }
811
+ ? { skipSettleDelay: true, skipWorktreeSync: true }
812
+ : { skipSettleDelay: true }
827
813
  : undefined;
828
814
  const preResult = await deps.postUnitPreVerification(postUnitCtx, preVerificationOpts);
829
815
  if (preResult === "dispatched") {
@@ -6,6 +6,7 @@
6
6
  import { NEW_SESSION_TIMEOUT_MS } from "./session.js";
7
7
  import { _setCurrentResolve, _setSessionSwitchInFlight } from "./resolve.js";
8
8
  import { debugLog } from "../debug-logger.js";
9
+ import { logWarning } from "../workflow-logger.js";
9
10
  /**
10
11
  * Execute a single unit: create a new session, send the prompt, and await
11
12
  * the agent_end promise. Returns a UnitResult describing what happened.
@@ -66,7 +67,9 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
66
67
  process.chdir(s.basePath);
67
68
  }
68
69
  }
69
- catch { /* non-fatal — chdir may fail if dir was removed */ }
70
+ catch (e) {
71
+ logWarning("engine", "Failed to chdir to basePath before dispatch", { basePath: s.basePath, error: String(e) });
72
+ }
70
73
  // ── Send the prompt ──
71
74
  debugLog("runUnit", { phase: "send-message", unitType, unitId });
72
75
  pi.sendMessage({ customType: "gsd-auto", content: prompt, display: s.verbose }, { triggerTurn: true });
@@ -90,8 +93,8 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
90
93
  cmdCtxAny.clearQueue();
91
94
  }
92
95
  }
93
- catch {
94
- // Non-fatal clearQueue may not be available in all contexts
96
+ catch (e) {
97
+ logWarning("engine", "clearQueue failed after unit completion", { error: String(e) });
95
98
  }
96
99
  return result;
97
100
  }
@@ -46,7 +46,6 @@ export class AutoSession {
46
46
  // ── Current unit ─────────────────────────────────────────────────────────
47
47
  currentUnit = null;
48
48
  currentUnitRouting = null;
49
- completedUnits = [];
50
49
  currentMilestoneId = null;
51
50
  // ── Model state ──────────────────────────────────────────────────────────
52
51
  autoModeStartModel = null;
@@ -100,14 +99,6 @@ export class AutoSession {
100
99
  get lockBasePath() {
101
100
  return this.originalBasePath || this.basePath;
102
101
  }
103
- completeCurrentUnit() {
104
- if (!this.currentUnit)
105
- return null;
106
- const done = { ...this.currentUnit, finishedAt: Date.now() };
107
- this.completedUnits.push(done);
108
- this.currentUnit = null;
109
- return done;
110
- }
111
102
  reset() {
112
103
  this.clearTimers();
113
104
  // Lifecycle
@@ -129,7 +120,6 @@ export class AutoSession {
129
120
  // Unit
130
121
  this.currentUnit = null;
131
122
  this.currentUnitRouting = null;
132
- this.completedUnits = [];
133
123
  this.currentMilestoneId = null;
134
124
  // Model
135
125
  this.autoModeStartModel = null;
@@ -164,7 +154,6 @@ export class AutoSession {
164
154
  activeRunDir: this.activeRunDir,
165
155
  currentMilestoneId: this.currentMilestoneId,
166
156
  currentUnit: this.currentUnit,
167
- completedUnits: this.completedUnits.length,
168
157
  unitDispatchCount: Object.fromEntries(this.unitDispatchCount),
169
158
  };
170
159
  }
@@ -0,0 +1,112 @@
1
+ // GSD Auto-mode — Artifact Path Resolution
2
+ //
3
+ // resolveExpectedArtifactPath and diagnoseExpectedArtifact moved here from
4
+ // auto-recovery.ts (Phase 5 dead-code cleanup). The artifact verification
5
+ // function was removed entirely — callers now query WorkflowEngine directly.
6
+ import { resolveMilestonePath, resolveSlicePath, relMilestoneFile, relSliceFile, buildMilestoneFileName, buildSliceFileName, buildTaskFileName, } from "./paths.js";
7
+ import { join } from "node:path";
8
+ /**
9
+ * Resolve the expected artifact for a unit to an absolute path.
10
+ */
11
+ export function resolveExpectedArtifactPath(unitType, unitId, base) {
12
+ const parts = unitId.split("/");
13
+ const mid = parts[0];
14
+ const sid = parts[1];
15
+ switch (unitType) {
16
+ case "discuss-milestone": {
17
+ const dir = resolveMilestonePath(base, mid);
18
+ return dir ? join(dir, buildMilestoneFileName(mid, "CONTEXT")) : null;
19
+ }
20
+ case "research-milestone": {
21
+ const dir = resolveMilestonePath(base, mid);
22
+ return dir ? join(dir, buildMilestoneFileName(mid, "RESEARCH")) : null;
23
+ }
24
+ case "plan-milestone": {
25
+ const dir = resolveMilestonePath(base, mid);
26
+ return dir ? join(dir, buildMilestoneFileName(mid, "ROADMAP")) : null;
27
+ }
28
+ case "research-slice": {
29
+ const dir = resolveSlicePath(base, mid, sid);
30
+ return dir ? join(dir, buildSliceFileName(sid, "RESEARCH")) : null;
31
+ }
32
+ case "plan-slice": {
33
+ const dir = resolveSlicePath(base, mid, sid);
34
+ return dir ? join(dir, buildSliceFileName(sid, "PLAN")) : null;
35
+ }
36
+ case "reassess-roadmap": {
37
+ const dir = resolveSlicePath(base, mid, sid);
38
+ return dir ? join(dir, buildSliceFileName(sid, "ASSESSMENT")) : null;
39
+ }
40
+ case "run-uat": {
41
+ const dir = resolveSlicePath(base, mid, sid);
42
+ return dir ? join(dir, buildSliceFileName(sid, "UAT-RESULT")) : null;
43
+ }
44
+ case "execute-task": {
45
+ const tid = parts[2];
46
+ const dir = resolveSlicePath(base, mid, sid);
47
+ return dir && tid
48
+ ? join(dir, "tasks", buildTaskFileName(tid, "SUMMARY"))
49
+ : null;
50
+ }
51
+ case "complete-slice": {
52
+ const dir = resolveSlicePath(base, mid, sid);
53
+ return dir ? join(dir, buildSliceFileName(sid, "SUMMARY")) : null;
54
+ }
55
+ case "validate-milestone": {
56
+ const dir = resolveMilestonePath(base, mid);
57
+ return dir ? join(dir, buildMilestoneFileName(mid, "VALIDATION")) : null;
58
+ }
59
+ case "complete-milestone": {
60
+ const dir = resolveMilestonePath(base, mid);
61
+ return dir ? join(dir, buildMilestoneFileName(mid, "SUMMARY")) : null;
62
+ }
63
+ case "replan-slice": {
64
+ const dir = resolveSlicePath(base, mid, sid);
65
+ return dir ? join(dir, buildSliceFileName(sid, "REPLAN")) : null;
66
+ }
67
+ case "rewrite-docs":
68
+ return null;
69
+ case "reactive-execute":
70
+ // Reactive execute produces multiple task summaries — verified separately
71
+ return null;
72
+ default:
73
+ return null;
74
+ }
75
+ }
76
+ export function diagnoseExpectedArtifact(unitType, unitId, base) {
77
+ const parts = unitId.split("/");
78
+ const mid = parts[0];
79
+ const sid = parts[1];
80
+ switch (unitType) {
81
+ case "discuss-milestone":
82
+ return `${relMilestoneFile(base, mid, "CONTEXT")} (milestone context from discussion)`;
83
+ case "research-milestone":
84
+ return `${relMilestoneFile(base, mid, "RESEARCH")} (milestone research)`;
85
+ case "plan-milestone":
86
+ return `${relMilestoneFile(base, mid, "ROADMAP")} (milestone roadmap)`;
87
+ case "research-slice":
88
+ return `${relSliceFile(base, mid, sid, "RESEARCH")} (slice research)`;
89
+ case "plan-slice":
90
+ return `${relSliceFile(base, mid, sid, "PLAN")} (slice plan)`;
91
+ case "execute-task": {
92
+ const tid = parts[2];
93
+ return `Task ${tid} marked [x] in ${relSliceFile(base, mid, sid, "PLAN")} + summary written`;
94
+ }
95
+ case "complete-slice":
96
+ return `Slice ${sid} marked [x] in ${relMilestoneFile(base, mid, "ROADMAP")} + summary + UAT written`;
97
+ case "replan-slice":
98
+ return `${relSliceFile(base, mid, sid, "REPLAN")} + updated ${relSliceFile(base, mid, sid, "PLAN")}`;
99
+ case "rewrite-docs":
100
+ return "Active overrides resolved in .gsd/OVERRIDES.md + plan documents updated";
101
+ case "reassess-roadmap":
102
+ return `${relSliceFile(base, mid, sid, "ASSESSMENT")} (roadmap reassessment)`;
103
+ case "run-uat":
104
+ return `${relSliceFile(base, mid, sid, "UAT-RESULT")} (UAT result)`;
105
+ case "validate-milestone":
106
+ return `${relMilestoneFile(base, mid, "VALIDATION")} (milestone validation report)`;
107
+ case "complete-milestone":
108
+ return `${relMilestoneFile(base, mid, "SUMMARY")} (milestone summary)`;
109
+ default:
110
+ return null;
111
+ }
112
+ }