gsd-pi 2.45.0 → 2.46.0-dev.5c2b8ed

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 (350) hide show
  1. package/dist/help-text.js +1 -1
  2. package/dist/loader.js +34 -0
  3. package/dist/resources/extensions/gsd/auto/phases.js +27 -42
  4. package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
  5. package/dist/resources/extensions/gsd/auto/session.js +0 -11
  6. package/dist/resources/extensions/gsd/auto-artifact-paths.js +112 -0
  7. package/dist/resources/extensions/gsd/auto-post-unit.js +25 -96
  8. package/dist/resources/extensions/gsd/auto-start.js +2 -3
  9. package/dist/resources/extensions/gsd/auto-worktree.js +5 -4
  10. package/dist/resources/extensions/gsd/auto.js +12 -57
  11. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +15 -12
  12. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +18 -0
  13. package/dist/resources/extensions/gsd/commands/context.js +0 -4
  14. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +1 -1
  15. package/dist/resources/extensions/gsd/crash-recovery.js +2 -4
  16. package/dist/resources/extensions/gsd/dashboard-overlay.js +0 -44
  17. package/dist/resources/extensions/gsd/db-writer.js +9 -9
  18. package/dist/resources/extensions/gsd/doctor-checks.js +167 -2
  19. package/dist/resources/extensions/gsd/doctor.js +5 -3
  20. package/dist/resources/extensions/gsd/gsd-db.js +16 -3
  21. package/dist/resources/extensions/gsd/guided-flow.js +1 -2
  22. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  23. package/dist/resources/extensions/gsd/parallel-orchestrator.js +5 -18
  24. package/dist/resources/extensions/gsd/preferences-types.js +2 -2
  25. package/dist/resources/extensions/gsd/preferences.js +8 -4
  26. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -8
  27. package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  28. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
  29. package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -15
  30. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  31. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  32. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  33. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  34. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  35. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  36. package/dist/resources/extensions/gsd/prompts/queue.md +2 -2
  37. package/dist/resources/extensions/gsd/prompts/quick-task.md +2 -0
  38. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  39. package/dist/resources/extensions/gsd/prompts/research-slice.md +3 -3
  40. package/dist/resources/extensions/gsd/prompts/rethink.md +7 -2
  41. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  42. package/dist/resources/extensions/gsd/session-lock.js +1 -3
  43. package/dist/resources/extensions/gsd/state.js +7 -0
  44. package/dist/resources/extensions/gsd/sync-lock.js +89 -0
  45. package/dist/resources/extensions/gsd/tools/complete-milestone.js +61 -11
  46. package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -11
  47. package/dist/resources/extensions/gsd/tools/complete-task.js +50 -2
  48. package/dist/resources/extensions/gsd/tools/plan-milestone.js +37 -1
  49. package/dist/resources/extensions/gsd/tools/plan-slice.js +30 -1
  50. package/dist/resources/extensions/gsd/tools/plan-task.js +27 -1
  51. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +32 -2
  52. package/dist/resources/extensions/gsd/tools/reopen-slice.js +86 -0
  53. package/dist/resources/extensions/gsd/tools/reopen-task.js +90 -0
  54. package/dist/resources/extensions/gsd/tools/replan-slice.js +32 -2
  55. package/dist/resources/extensions/gsd/unit-ownership.js +85 -0
  56. package/dist/resources/extensions/gsd/workflow-events.js +102 -0
  57. package/dist/resources/extensions/gsd/workflow-logger.js +193 -0
  58. package/dist/resources/extensions/gsd/workflow-manifest.js +244 -0
  59. package/dist/resources/extensions/gsd/workflow-migration.js +280 -0
  60. package/dist/resources/extensions/gsd/workflow-projections.js +373 -0
  61. package/dist/resources/extensions/gsd/workflow-reconcile.js +411 -0
  62. package/dist/resources/extensions/gsd/worktree-manager.js +4 -3
  63. package/dist/resources/extensions/gsd/worktree-resolver.js +37 -0
  64. package/dist/resources/extensions/gsd/write-intercept.js +84 -0
  65. package/dist/resources/extensions/remote-questions/config.js +42 -0
  66. package/dist/resources/extensions/voice/index.js +11 -16
  67. package/dist/resources/extensions/voice/linux-ready.js +67 -0
  68. package/dist/web/standalone/.next/BUILD_ID +1 -1
  69. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  70. package/dist/web/standalone/.next/build-manifest.json +3 -3
  71. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  72. package/dist/web/standalone/.next/required-server-files.json +3 -3
  73. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  74. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  76. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  84. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  87. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  88. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  90. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  100. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/knowledge/route.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.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  138. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  144. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  158. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  160. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  162. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  164. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/index.html +1 -1
  174. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  175. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  176. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  177. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  178. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  179. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  180. package/dist/web/standalone/.next/server/app/page.js +2 -2
  181. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  183. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  184. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  185. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/middleware.js +2 -2
  187. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  189. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  190. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  191. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  192. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  193. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  194. package/dist/web/standalone/.next/static/chunks/app/page-6654a8cca61a3d1c.js +1 -0
  195. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  196. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  197. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  198. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  199. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  200. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  201. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  202. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  203. package/dist/web/standalone/server.js +1 -1
  204. package/package.json +2 -1
  205. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  206. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
  207. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
  209. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  210. package/packages/pi-coding-agent/dist/core/extensions/types.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/model-registry-auth-mode.test.js +239 -10
  220. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +2 -1
  222. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  223. package/packages/pi-coding-agent/dist/core/model-registry.js +20 -2
  224. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  225. package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
  226. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -1
  227. package/packages/pi-coding-agent/package.json +1 -1
  228. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
  229. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
  230. package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
  231. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
  232. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
  233. package/packages/pi-coding-agent/src/core/model-registry.ts +30 -3
  234. package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
  235. package/pkg/package.json +1 -1
  236. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -19
  237. package/src/resources/extensions/gsd/auto/phases.ts +24 -44
  238. package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
  239. package/src/resources/extensions/gsd/auto/session.ts +0 -18
  240. package/src/resources/extensions/gsd/auto-artifact-paths.ts +131 -0
  241. package/src/resources/extensions/gsd/auto-dashboard.ts +0 -1
  242. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -106
  243. package/src/resources/extensions/gsd/auto-start.ts +1 -3
  244. package/src/resources/extensions/gsd/auto-worktree.ts +8 -5
  245. package/src/resources/extensions/gsd/auto.ts +7 -83
  246. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -12
  247. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
  248. package/src/resources/extensions/gsd/commands/context.ts +0 -5
  249. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +1 -1
  250. package/src/resources/extensions/gsd/crash-recovery.ts +1 -5
  251. package/src/resources/extensions/gsd/dashboard-overlay.ts +0 -50
  252. package/src/resources/extensions/gsd/db-writer.ts +9 -17
  253. package/src/resources/extensions/gsd/doctor-checks.ts +180 -2
  254. package/src/resources/extensions/gsd/doctor-types.ts +7 -1
  255. package/src/resources/extensions/gsd/doctor.ts +6 -3
  256. package/src/resources/extensions/gsd/gsd-db.ts +16 -3
  257. package/src/resources/extensions/gsd/guided-flow.ts +1 -2
  258. package/src/resources/extensions/gsd/journal.ts +6 -1
  259. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  260. package/src/resources/extensions/gsd/parallel-orchestrator.ts +5 -21
  261. package/src/resources/extensions/gsd/preferences-types.ts +2 -2
  262. package/src/resources/extensions/gsd/preferences.ts +7 -3
  263. package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -8
  264. package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -23
  265. package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
  266. package/src/resources/extensions/gsd/prompts/execute-task.md +5 -15
  267. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  268. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  269. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  270. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  271. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  272. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  273. package/src/resources/extensions/gsd/prompts/queue.md +2 -2
  274. package/src/resources/extensions/gsd/prompts/quick-task.md +2 -0
  275. package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  276. package/src/resources/extensions/gsd/prompts/research-slice.md +3 -3
  277. package/src/resources/extensions/gsd/prompts/rethink.md +7 -2
  278. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  279. package/src/resources/extensions/gsd/session-lock.ts +0 -4
  280. package/src/resources/extensions/gsd/state.ts +8 -0
  281. package/src/resources/extensions/gsd/sync-lock.ts +94 -0
  282. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +5 -13
  283. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +6 -10
  284. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +96 -0
  285. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +264 -228
  286. package/src/resources/extensions/gsd/tests/complete-task.test.ts +317 -250
  287. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +2 -8
  288. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -3
  289. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  290. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +1 -1
  291. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +15 -24
  292. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
  293. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  294. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  295. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -1
  296. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +8 -9
  297. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +42 -3
  298. package/src/resources/extensions/gsd/tests/parallel-budget-atomicity.test.ts +0 -1
  299. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +0 -7
  300. package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +7 -8
  301. package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +20 -24
  302. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +0 -2
  303. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +9 -6
  304. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +171 -0
  305. package/src/resources/extensions/gsd/tests/preferences.test.ts +7 -9
  306. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +174 -0
  307. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +15 -14
  308. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +84 -0
  309. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +155 -0
  310. package/src/resources/extensions/gsd/tests/reopen-task.test.ts +165 -0
  311. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +1 -4
  312. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +2 -3
  313. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +122 -0
  314. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +175 -0
  315. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +205 -0
  316. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
  317. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +186 -0
  318. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +171 -0
  319. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
  320. package/src/resources/extensions/gsd/tests/write-intercept.test.ts +76 -0
  321. package/src/resources/extensions/gsd/tools/complete-milestone.ts +74 -11
  322. package/src/resources/extensions/gsd/tools/complete-slice.ts +68 -11
  323. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -1
  324. package/src/resources/extensions/gsd/tools/plan-milestone.ts +45 -0
  325. package/src/resources/extensions/gsd/tools/plan-slice.ts +38 -0
  326. package/src/resources/extensions/gsd/tools/plan-task.ts +35 -1
  327. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +39 -1
  328. package/src/resources/extensions/gsd/tools/reopen-slice.ts +125 -0
  329. package/src/resources/extensions/gsd/tools/reopen-task.ts +129 -0
  330. package/src/resources/extensions/gsd/tools/replan-slice.ts +38 -1
  331. package/src/resources/extensions/gsd/types.ts +8 -0
  332. package/src/resources/extensions/gsd/unit-ownership.ts +104 -0
  333. package/src/resources/extensions/gsd/workflow-events.ts +154 -0
  334. package/src/resources/extensions/gsd/workflow-logger.ts +243 -0
  335. package/src/resources/extensions/gsd/workflow-manifest.ts +334 -0
  336. package/src/resources/extensions/gsd/workflow-migration.ts +345 -0
  337. package/src/resources/extensions/gsd/workflow-projections.ts +425 -0
  338. package/src/resources/extensions/gsd/workflow-reconcile.ts +503 -0
  339. package/src/resources/extensions/gsd/worktree-manager.ts +4 -9
  340. package/src/resources/extensions/gsd/worktree-resolver.ts +37 -0
  341. package/src/resources/extensions/gsd/write-intercept.ts +90 -0
  342. package/src/resources/extensions/remote-questions/config.ts +45 -0
  343. package/src/resources/extensions/voice/index.ts +11 -21
  344. package/src/resources/extensions/voice/linux-ready.ts +87 -0
  345. package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
  346. package/dist/web/standalone/.next/static/chunks/app/page-12dd5ece0df4badc.js +0 -1
  347. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  348. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  349. /package/dist/web/standalone/.next/static/{wUzEX1U3CmFcMry2SUDJn → NtM_pwvGTaXTeqiByOv3A}/_buildManifest.js +0 -0
  350. /package/dist/web/standalone/.next/static/{wUzEX1U3CmFcMry2SUDJn → NtM_pwvGTaXTeqiByOv3A}/_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';
@@ -11,12 +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";
17
15
  import { MergeConflictError } from "../git-service.js";
18
16
  import { join } from "node:path";
19
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";
20
23
  // ─── generateMilestoneReport ──────────────────────────────────────────────────
21
24
  /**
22
25
  * Generate and write an HTML milestone report snapshot.
@@ -102,8 +105,8 @@ export async function runPreDispatch(ic, loopState) {
102
105
  return { action: "break", reason: "health-gate-failed" };
103
106
  }
104
107
  }
105
- catch {
106
- // Non-fatal
108
+ catch (e) {
109
+ logWarning("engine", "Pre-dispatch health gate threw unexpectedly", { error: String(e) });
107
110
  }
108
111
  // Sync project root artifacts into worktree
109
112
  if (s.originalBasePath &&
@@ -157,7 +160,8 @@ export async function runPreDispatch(ic, loopState) {
157
160
  await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
158
161
  return { action: "break", reason: "merge-conflict" };
159
162
  }
160
- // Non-conflict errors — log and continue
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
  }
162
166
  // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
163
167
  deps.invalidateAllCaches();
@@ -177,11 +181,7 @@ export async function runPreDispatch(ic, loopState) {
177
181
  .filter((m) => m.status !== "complete" && m.status !== "parked")
178
182
  .map((m) => m.id);
179
183
  deps.pruneQueueOrder(s.basePath, pendingIds);
180
- // Reset completed-units tracking for the new milestone — stale entries
181
- // from the previous milestone cause the dispatch loop to skip units
182
- // that haven't actually been completed in the new milestone's context.
183
184
  // Archive the old completed-units.json instead of wiping it (#2313).
184
- s.completedUnits = [];
185
185
  try {
186
186
  const completedKeysPath = join(gsdRoot(s.basePath), "completed-units.json");
187
187
  if (existsSync(completedKeysPath) && s.currentMilestoneId) {
@@ -190,7 +190,9 @@ export async function runPreDispatch(ic, loopState) {
190
190
  }
191
191
  atomicWriteSync(completedKeysPath, JSON.stringify([], null, 2));
192
192
  }
193
- catch { /* non-fatal */ }
193
+ catch (e) {
194
+ logWarning("engine", "Failed to archive completed-units on milestone transition", { error: String(e) });
195
+ }
194
196
  // Rebuild STATE.md immediately so it reflects the new active milestone.
195
197
  // This bypasses the 30-second throttle in the normal rebuild path —
196
198
  // milestone transitions are rare and important enough to warrant an
@@ -198,8 +200,8 @@ export async function runPreDispatch(ic, loopState) {
198
200
  try {
199
201
  await deps.rebuildState(s.basePath);
200
202
  }
201
- catch {
202
- // 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) });
203
205
  }
204
206
  }
205
207
  if (mid) {
@@ -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,7 +586,7 @@ 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,
@@ -644,8 +646,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
644
646
  (requirementsContent?.length ?? 0) +
645
647
  (projectContent?.length ?? 0);
646
648
  }
647
- catch {
648
- // Non-fatal
649
+ catch (e) {
650
+ logWarning("engine", "Baseline char count measurement failed", { error: String(e) });
649
651
  }
650
652
  }
651
653
  // Cache-optimize prompt section ordering
@@ -654,7 +656,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
654
656
  }
655
657
  catch (reorderErr) {
656
658
  const msg = reorderErr instanceof Error ? reorderErr.message : String(reorderErr);
657
- process.stderr.write(`[gsd] prompt reorder failed (non-fatal): ${msg}\n`);
659
+ logWarning("engine", "Prompt reorder failed", { error: msg });
658
660
  }
659
661
  // Select and apply model (with tier escalation on retry — normal units only)
660
662
  const modelResult = await deps.selectAndApplyModel(ctx, pi, unitType, unitId, s.basePath, prefs, s.verbose, s.autoModeStartModel, sidecarItem ? undefined : { isRetry, previousTier });
@@ -699,7 +701,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
699
701
  });
700
702
  // Write preliminary lock (no session path yet — runUnit creates a new session).
701
703
  // Crash recovery can still identify the in-flight unit from this lock.
702
- deps.writeLock(deps.lockBase(), unitType, unitId, s.completedUnits.length);
704
+ deps.writeLock(deps.lockBase(), unitType, unitId);
703
705
  debugLog("autoLoop", {
704
706
  phase: "runUnit-start",
705
707
  iteration: ic.iteration,
@@ -716,8 +718,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
716
718
  });
717
719
  // Now that runUnit has called newSession(), the session file path is correct.
718
720
  const sessionFile = deps.getSessionFile(ctx);
719
- deps.updateSessionLock(deps.lockBase(), unitType, unitId, s.completedUnits.length, sessionFile);
720
- 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);
721
723
  // Tag the most recent window entry with error info for stuck detection
722
724
  if (unitResult.status === "error" || unitResult.status === "cancelled") {
723
725
  const lastEntry = loopState.recentUnits[loopState.recentUnits.length - 1];
@@ -761,8 +763,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
761
763
  warning: "Task completed with 0 tool calls — likely hallucinated, marking as failed",
762
764
  });
763
765
  ctx.ui.notify(`${unitType} ${unitId} completed with 0 tool calls — hallucinated summary, will retry`, "warning");
764
- // Do NOT add to completedUnits fall through to next iteration
765
- // 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.
766
768
  return { action: "next", data: { unitStartedAt: s.currentUnit.startedAt } };
767
769
  }
768
770
  }
@@ -772,25 +774,8 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
772
774
  }
773
775
  const skipArtifactVerification = unitType.startsWith("hook/") || unitType === "custom-step";
774
776
  const artifactVerified = skipArtifactVerification ||
775
- deps.verifyExpectedArtifact(unitType, unitId, s.basePath);
777
+ verifyExpectedArtifact(unitType, unitId, s.basePath);
776
778
  if (artifactVerified) {
777
- s.completedUnits.push({
778
- type: unitType,
779
- id: unitId,
780
- startedAt: s.currentUnit.startedAt,
781
- finishedAt: Date.now(),
782
- });
783
- if (s.completedUnits.length > 200) {
784
- s.completedUnits = s.completedUnits.slice(-200);
785
- }
786
- // Flush completed-units to disk so the record survives crashes
787
- try {
788
- const completedKeysPath = join(gsdRoot(s.basePath), "completed-units.json");
789
- const keys = s.completedUnits.map((u) => `${u.type}/${u.id}`);
790
- atomicWriteSync(completedKeysPath, JSON.stringify(keys, null, 2));
791
- }
792
- catch { /* non-fatal: disk flush failure */ }
793
- deps.clearUnitRuntimeRecord(s.basePath, unitType, unitId);
794
779
  s.unitDispatchCount.delete(`${unitType}/${unitId}`);
795
780
  s.unitRecoveryCount.delete(`${unitType}/${unitId}`);
796
781
  }
@@ -823,8 +808,8 @@ export async function runFinalize(ic, iterData, sidecarItem) {
823
808
  // Sidecar items use lightweight pre-verification opts
824
809
  const preVerificationOpts = sidecarItem
825
810
  ? sidecarItem.kind === "hook"
826
- ? { skipSettleDelay: true, skipDoctor: true, skipStateRebuild: true, skipWorktreeSync: true }
827
- : { skipSettleDelay: true, skipStateRebuild: true }
811
+ ? { skipSettleDelay: true, skipWorktreeSync: true }
812
+ : { skipSettleDelay: true }
828
813
  : undefined;
829
814
  const preResult = await deps.postUnitPreVerification(postUnitCtx, preVerificationOpts);
830
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
+ }
@@ -13,14 +13,12 @@
13
13
  import { deriveState } from "./state.js";
14
14
  import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
15
15
  import { loadPrompt } from "./prompt-loader.js";
16
- import { resolveSliceFile, resolveTaskFile, resolveMilestoneFile, resolveTasksDir, buildTaskFileName, gsdRoot, } from "./paths.js";
16
+ import { resolveSliceFile, resolveTaskFile, resolveMilestoneFile, resolveTasksDir, buildTaskFileName, } from "./paths.js";
17
17
  import { invalidateAllCaches } from "./cache.js";
18
18
  import { closeoutUnit } from "./auto-unit-closeout.js";
19
19
  import { autoCommitCurrentBranch, } from "./worktree.js";
20
20
  import { verifyExpectedArtifact, resolveExpectedArtifactPath, } from "./auto-recovery.js";
21
- import { writeUnitRuntimeRecord, clearUnitRuntimeRecord } from "./unit-runtime.js";
22
- import { runGSDDoctor, rebuildState, summarizeDoctorIssues } from "./doctor.js";
23
- import { recordHealthSnapshot, checkHealEscalation } from "./doctor-proactive.js";
21
+ import { regenerateIfMissing } from "./workflow-projections.js";
24
22
  import { syncStateToProjectRoot } from "./auto-worktree-sync.js";
25
23
  import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getAdapter } from "./gsd-db.js";
26
24
  import { renderPlanCheckboxes } from "./markdown-renderer.js";
@@ -30,7 +28,6 @@ import { hasPendingCaptures, loadPendingCaptures } from "./captures.js";
30
28
  import { debugLog } from "./debug-logger.js";
31
29
  import { existsSync, unlinkSync } from "node:fs";
32
30
  import { join } from "node:path";
33
- import { atomicWriteSync } from "./atomic-write.js";
34
31
  import { _resetHasChangesCache } from "./native-git-bridge.js";
35
32
  /**
36
33
  * Detect summary files written directly to disk without the LLM calling
@@ -137,8 +134,6 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
137
134
  }
138
135
  return rogues;
139
136
  }
140
- /** Throttle STATE.md rebuilds — at most once per 30 seconds */
141
- const STATE_REBUILD_MIN_INTERVAL_MS = 30_000;
142
137
  /**
143
138
  * Pre-verification processing: parallel worker signal check, cache invalidation,
144
139
  * auto-commit, doctor run, state rebuild, worktree sync, artifact verification.
@@ -232,74 +227,6 @@ export async function postUnitPreVerification(pctx, opts) {
232
227
  catch (e) {
233
228
  debugLog("postUnit", { phase: "github-sync", error: String(e) });
234
229
  }
235
- // Doctor: fix mechanical bookkeeping (skipped for lightweight sidecars)
236
- if (!opts?.skipDoctor)
237
- try {
238
- const scopeParts = s.currentUnit.id.split("/").slice(0, 2);
239
- const doctorScope = scopeParts.join("/");
240
- const sliceTerminalUnits = new Set(["complete-slice", "run-uat"]);
241
- const effectiveFixLevel = sliceTerminalUnits.has(s.currentUnit.type) ? "all" : "task";
242
- const report = await runGSDDoctor(s.basePath, { fix: true, scope: doctorScope, fixLevel: effectiveFixLevel });
243
- // Human-readable fix notification with details
244
- if (report.fixesApplied.length > 0) {
245
- const fixSummary = report.fixesApplied.length <= 2
246
- ? report.fixesApplied.join("; ")
247
- : `${report.fixesApplied[0]}; +${report.fixesApplied.length - 1} more`;
248
- ctx.ui.notify(`Doctor: ${fixSummary}`, "info");
249
- }
250
- // Proactive health tracking — filter to current milestone to avoid
251
- // cross-milestone stale errors inflating the escalation counter
252
- const currentMilestoneId = s.currentUnit.id.split("/")[0];
253
- const milestoneIssues = currentMilestoneId
254
- ? report.issues.filter(i => i.unitId === currentMilestoneId ||
255
- i.unitId.startsWith(`${currentMilestoneId}/`))
256
- : report.issues;
257
- const summary = summarizeDoctorIssues(milestoneIssues);
258
- // Pass issue details + scope for real-time visibility in the progress widget
259
- const issueDetails = milestoneIssues
260
- .filter(i => i.severity === "error" || i.severity === "warning")
261
- .map(i => ({ code: i.code, message: i.message, severity: i.severity, unitId: i.unitId }));
262
- recordHealthSnapshot(summary.errors, summary.warnings, report.fixesApplied.length, issueDetails, report.fixesApplied, doctorScope);
263
- // Check if we should escalate to LLM-assisted heal
264
- if (summary.errors > 0) {
265
- const unresolvedErrors = milestoneIssues
266
- .filter(i => i.severity === "error" && !i.fixable)
267
- .map(i => ({ code: i.code, message: i.message, unitId: i.unitId }));
268
- const escalation = checkHealEscalation(summary.errors, unresolvedErrors);
269
- if (escalation.shouldEscalate) {
270
- ctx.ui.notify(`Doctor heal escalation: ${escalation.reason}. Dispatching LLM-assisted heal.`, "warning");
271
- try {
272
- const { formatDoctorIssuesForPrompt, formatDoctorReport } = await import("./doctor.js");
273
- const { dispatchDoctorHeal } = await import("./commands-handlers.js");
274
- const actionable = report.issues.filter(i => i.severity === "error");
275
- const reportText = formatDoctorReport(report, { scope: doctorScope, includeWarnings: true });
276
- const structuredIssues = formatDoctorIssuesForPrompt(actionable);
277
- dispatchDoctorHeal(pi, doctorScope, reportText, structuredIssues);
278
- return "dispatched";
279
- }
280
- catch (e) {
281
- debugLog("postUnit", { phase: "doctor-heal-dispatch", error: String(e) });
282
- }
283
- }
284
- }
285
- }
286
- catch (e) {
287
- debugLog("postUnit", { phase: "doctor", error: String(e) });
288
- }
289
- // Throttled STATE.md rebuild (skipped for lightweight sidecars)
290
- if (!opts?.skipStateRebuild) {
291
- const now = Date.now();
292
- if (now - s.lastStateRebuildAt >= STATE_REBUILD_MIN_INTERVAL_MS) {
293
- try {
294
- await rebuildState(s.basePath);
295
- s.lastStateRebuildAt = now;
296
- autoCommitCurrentBranch(s.basePath, "state-rebuild", s.currentUnit.id);
297
- }
298
- catch (e) {
299
- debugLog("postUnit", { phase: "state-rebuild", error: String(e) });
300
- }
301
- }
302
- }
303
230
  // Prune dead bg-shell processes
304
231
  try {
305
232
  const { pruneDeadProcesses } = await import("../bg-shell/process-manager.js");
@@ -411,6 +338,27 @@ export async function postUnitPreVerification(pctx, opts) {
411
338
  catch (e) {
412
339
  debugLog("postUnit", { phase: "artifact-verify", error: String(e) });
413
340
  }
341
+ // If verification failed, attempt to regenerate missing projection files
342
+ // from DB data before giving up (e.g. research-slice produces PLAN from engine).
343
+ if (!triggerArtifactVerified) {
344
+ try {
345
+ const parts = s.currentUnit.id.split("/");
346
+ const [mid, sid] = parts;
347
+ if (mid && sid) {
348
+ const regenerated = regenerateIfMissing(s.basePath, mid, sid, "PLAN");
349
+ if (regenerated) {
350
+ // Re-check after regeneration
351
+ triggerArtifactVerified = verifyExpectedArtifact(s.currentUnit.type, s.currentUnit.id, s.basePath);
352
+ if (triggerArtifactVerified) {
353
+ invalidateAllCaches();
354
+ }
355
+ }
356
+ }
357
+ }
358
+ catch (e) {
359
+ debugLog("postUnit", { phase: "regenerate-projection", error: String(e) });
360
+ }
361
+ }
414
362
  // When artifact verification fails for a unit type that has a known expected
415
363
  // artifact, return "retry" so the caller re-dispatches with failure context
416
364
  // instead of blindly re-dispatching the same unit (#1571).
@@ -432,18 +380,7 @@ export async function postUnitPreVerification(pctx, opts) {
432
380
  }
433
381
  }
434
382
  else {
435
- // Hook unit completed — finalize its runtime record
436
- try {
437
- writeUnitRuntimeRecord(s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, {
438
- phase: "finalized",
439
- progressCount: 1,
440
- lastProgressKind: "hook-completed",
441
- });
442
- clearUnitRuntimeRecord(s.basePath, s.currentUnit.type, s.currentUnit.id);
443
- }
444
- catch (e) {
445
- debugLog("postUnit", { phase: "hook-finalize", error: String(e) });
446
- }
383
+ // Hook unit completed — no additional processing needed
447
384
  }
448
385
  }
449
386
  return "continue";
@@ -517,15 +454,7 @@ export async function postUnitPostVerification(pctx) {
517
454
  }
518
455
  }
519
456
  }
520
- // 3. Remove from s.completedUnits and flush to completed-units.json
521
- s.completedUnits = s.completedUnits.filter(u => !(u.type === trigger.unitType && u.id === trigger.unitId));
522
- try {
523
- const completedKeysPath = join(gsdRoot(s.basePath), "completed-units.json");
524
- const keys = s.completedUnits.map(u => `${u.type}/${u.id}`);
525
- atomicWriteSync(completedKeysPath, JSON.stringify(keys, null, 2));
526
- }
527
- catch { /* non-fatal: disk flush failure */ }
528
- // 4. Delete the retry_on artifact (e.g. NEEDS-REWORK.md)
457
+ // 3. Delete the retry_on artifact (e.g. NEEDS-REWORK.md)
529
458
  if (trigger.retryArtifact) {
530
459
  const retryArtifactPath = resolveHookArtifactPath(s.basePath, trigger.unitId, trigger.retryArtifact);
531
460
  if (existsSync(retryArtifactPath)) {
@@ -352,7 +352,6 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
352
352
  });
353
353
  s.autoStartTime = Date.now();
354
354
  s.resourceVersionOnStart = readResourceVersion();
355
- s.completedUnits = [];
356
355
  s.pendingQuickTasks = [];
357
356
  s.currentUnit = null;
358
357
  s.currentMilestoneId = state.activeMilestone?.id ?? null;
@@ -455,8 +454,8 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
455
454
  ? `Will loop through ${pendingCount} milestones.`
456
455
  : "Will loop until milestone complete.";
457
456
  ctx.ui.notify(`${modeLabel} started. ${scopeMsg}`, "info");
458
- updateSessionLock(lockBase(), "starting", s.currentMilestoneId ?? "unknown", 0);
459
- writeLock(lockBase(), "starting", s.currentMilestoneId ?? "unknown", 0);
457
+ updateSessionLock(lockBase(), "starting", s.currentMilestoneId ?? "unknown");
458
+ writeLock(lockBase(), "starting", s.currentMilestoneId ?? "unknown");
460
459
  // Secrets collection gate
461
460
  const mid = state.activeMilestone.id;
462
461
  try {
@@ -17,6 +17,7 @@ import { createWorktree, removeWorktree, resolveGitDir, worktreePath, } from "./
17
17
  import { detectWorktreeName, nudgeGitBranchCache, } from "./worktree.js";
18
18
  import { MergeConflictError, readIntegrationBranch, RUNTIME_EXCLUSION_PATHS } from "./git-service.js";
19
19
  import { debugLog } from "./debug-logger.js";
20
+ import { logWarning } from "./workflow-logger.js";
20
21
  import { loadEffectiveGSDPreferences } from "./preferences.js";
21
22
  import { nativeGetCurrentBranch, nativeDetectMainBranch, nativeWorkingTreeStatus, nativeAddAllWithExclusions, nativeCommit, nativeCheckoutBranch, nativeMergeSquash, nativeConflictFiles, nativeCheckoutTheirs, nativeAddPaths, nativeRmForce, nativeBranchDelete, nativeBranchExists, nativeDiffNumstat, nativeUpdateRef, nativeIsAncestor, } from "./native-git-bridge.js";
22
23
  // ─── Module State ──────────────────────────────────────────────────────────
@@ -615,7 +616,7 @@ export function createAutoWorktree(basePath, milestoneId) {
615
616
  const hookError = runWorktreePostCreateHook(basePath, info.path);
616
617
  if (hookError) {
617
618
  // Non-fatal — log but don't prevent worktree usage
618
- console.error(`[GSD] ${hookError}`);
619
+ logWarning("reconcile", hookError, { worktree: info.name });
619
620
  }
620
621
  const previousCwd = process.cwd();
621
622
  try {
@@ -690,9 +691,9 @@ export function teardownAutoWorktree(originalBasePath, milestoneId, opts = {}) {
690
691
  // backslashes (#1436), leaving ~1 GB+ orphaned directories.
691
692
  const wtDir = worktreePath(originalBasePath, milestoneId);
692
693
  if (existsSync(wtDir)) {
693
- console.error(`[GSD] WARNING: Worktree directory still exists after teardown: ${wtDir}\n` +
694
- ` This is likely an orphaned directory consuming disk space.\n` +
695
- ` Remove it manually with: rm -rf "${wtDir.replaceAll("\\", "/")}"`);
694
+ logWarning("reconcile", `Worktree directory still exists after teardown: ${wtDir}. ` +
695
+ `This is likely an orphaned directory consuming disk space. ` +
696
+ `Remove it manually with: rm -rf "${wtDir.replaceAll("\\", "/")}"`, { worktree: milestoneId });
696
697
  // Attempt a direct filesystem removal as a fallback
697
698
  try {
698
699
  rmSync(wtDir, { recursive: true, force: true });