gsd-pi 2.33.1-dev.ee47f1b → 2.34.0-dev.0150ae9

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 (356) hide show
  1. package/dist/bundled-resource-path.d.ts +8 -0
  2. package/dist/bundled-resource-path.js +14 -0
  3. package/dist/headless-query.js +6 -6
  4. package/dist/resources/extensions/gsd/auto/session.js +27 -32
  5. package/dist/resources/extensions/gsd/auto-dashboard.js +29 -109
  6. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +6 -1
  7. package/dist/resources/extensions/gsd/auto-dispatch.js +52 -81
  8. package/dist/resources/extensions/gsd/auto-loop.js +956 -0
  9. package/dist/resources/extensions/gsd/auto-observability.js +4 -2
  10. package/dist/resources/extensions/gsd/auto-post-unit.js +75 -185
  11. package/dist/resources/extensions/gsd/auto-prompts.js +133 -101
  12. package/dist/resources/extensions/gsd/auto-recovery.js +59 -97
  13. package/dist/resources/extensions/gsd/auto-start.js +330 -309
  14. package/dist/resources/extensions/gsd/auto-supervisor.js +5 -11
  15. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +7 -7
  16. package/dist/resources/extensions/gsd/auto-timers.js +3 -4
  17. package/dist/resources/extensions/gsd/auto-verification.js +35 -73
  18. package/dist/resources/extensions/gsd/auto-worktree-sync.js +167 -0
  19. package/dist/resources/extensions/gsd/auto-worktree.js +291 -126
  20. package/dist/resources/extensions/gsd/auto.js +283 -1013
  21. package/dist/resources/extensions/gsd/captures.js +10 -4
  22. package/dist/resources/extensions/gsd/dispatch-guard.js +7 -8
  23. package/dist/resources/extensions/gsd/docs/preferences-reference.md +25 -18
  24. package/dist/resources/extensions/gsd/doctor-checks.js +3 -4
  25. package/dist/resources/extensions/gsd/git-service.js +1 -1
  26. package/dist/resources/extensions/gsd/gsd-db.js +296 -151
  27. package/dist/resources/extensions/gsd/index.js +92 -228
  28. package/dist/resources/extensions/gsd/post-unit-hooks.js +13 -13
  29. package/dist/resources/extensions/gsd/progress-score.js +61 -156
  30. package/dist/resources/extensions/gsd/quick.js +98 -122
  31. package/dist/resources/extensions/gsd/session-lock.js +13 -0
  32. package/dist/resources/extensions/gsd/templates/preferences.md +1 -0
  33. package/dist/resources/extensions/gsd/undo.js +43 -48
  34. package/dist/resources/extensions/gsd/unit-runtime.js +16 -15
  35. package/dist/resources/extensions/gsd/verification-evidence.js +0 -1
  36. package/dist/resources/extensions/gsd/verification-gate.js +6 -35
  37. package/dist/resources/extensions/gsd/worktree-command.js +30 -24
  38. package/dist/resources/extensions/gsd/worktree-manager.js +2 -3
  39. package/dist/resources/extensions/gsd/worktree-resolver.js +344 -0
  40. package/dist/resources/extensions/gsd/worktree.js +7 -44
  41. package/dist/resources/extensions/mcp-client/index.js +2 -1
  42. package/dist/tool-bootstrap.js +59 -11
  43. package/dist/worktree-cli.js +7 -7
  44. package/package.json +1 -1
  45. package/packages/native/dist/native.d.ts +0 -2
  46. package/packages/native/dist/native.js +0 -2
  47. package/packages/native/src/native.ts +0 -3
  48. package/packages/pi-agent-core/dist/proxy.d.ts +1 -25
  49. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  50. package/packages/pi-agent-core/dist/proxy.js +1 -1
  51. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  52. package/packages/pi-agent-core/src/proxy.ts +1 -1
  53. package/packages/pi-ai/dist/api-registry.d.ts +0 -2
  54. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  55. package/packages/pi-ai/dist/api-registry.js +0 -10
  56. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  57. package/packages/pi-ai/dist/models.generated.d.ts +3630 -5483
  58. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  59. package/packages/pi-ai/dist/models.generated.js +735 -2588
  60. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  61. package/packages/pi-ai/dist/providers/anthropic.d.ts +0 -8
  62. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  63. package/packages/pi-ai/dist/providers/anthropic.js +1 -1
  64. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  65. package/packages/pi-ai/dist/providers/github-copilot-headers.d.ts +0 -1
  66. package/packages/pi-ai/dist/providers/github-copilot-headers.d.ts.map +1 -1
  67. package/packages/pi-ai/dist/providers/github-copilot-headers.js +1 -1
  68. package/packages/pi-ai/dist/providers/github-copilot-headers.js.map +1 -1
  69. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts +1 -43
  70. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  71. package/packages/pi-ai/dist/providers/google-gemini-cli.js +2 -2
  72. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  73. package/packages/pi-ai/dist/providers/google-shared.d.ts +0 -4
  74. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  75. package/packages/pi-ai/dist/providers/google-shared.js +1 -1
  76. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  77. package/packages/pi-ai/dist/providers/register-builtins.d.ts +0 -1
  78. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  79. package/packages/pi-ai/dist/providers/register-builtins.js +1 -1
  80. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  81. package/packages/pi-ai/dist/utils/event-stream.d.ts +0 -2
  82. package/packages/pi-ai/dist/utils/event-stream.d.ts.map +1 -1
  83. package/packages/pi-ai/dist/utils/event-stream.js +0 -4
  84. package/packages/pi-ai/dist/utils/event-stream.js.map +1 -1
  85. package/packages/pi-ai/dist/utils/overflow.d.ts +0 -4
  86. package/packages/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  87. package/packages/pi-ai/dist/utils/overflow.js +0 -6
  88. package/packages/pi-ai/dist/utils/overflow.js.map +1 -1
  89. package/packages/pi-ai/dist/utils/validation.d.ts +0 -8
  90. package/packages/pi-ai/dist/utils/validation.d.ts.map +1 -1
  91. package/packages/pi-ai/dist/utils/validation.js +0 -14
  92. package/packages/pi-ai/dist/utils/validation.js.map +1 -1
  93. package/packages/pi-ai/src/api-registry.ts +0 -12
  94. package/packages/pi-ai/src/models.generated.ts +1039 -2892
  95. package/packages/pi-ai/src/providers/anthropic.ts +1 -1
  96. package/packages/pi-ai/src/providers/github-copilot-headers.ts +1 -1
  97. package/packages/pi-ai/src/providers/google-gemini-cli.ts +2 -2
  98. package/packages/pi-ai/src/providers/google-shared.ts +1 -1
  99. package/packages/pi-ai/src/providers/register-builtins.ts +1 -1
  100. package/packages/pi-ai/src/utils/event-stream.ts +0 -5
  101. package/packages/pi-ai/src/utils/overflow.ts +1 -8
  102. package/packages/pi-ai/src/utils/validation.ts +0 -15
  103. package/packages/pi-coding-agent/dist/config.d.ts +0 -9
  104. package/packages/pi-coding-agent/dist/config.d.ts.map +1 -1
  105. package/packages/pi-coding-agent/dist/config.js +4 -8
  106. package/packages/pi-coding-agent/dist/config.js.map +1 -1
  107. package/packages/pi-coding-agent/dist/core/export-html/ansi-to-html.d.ts +0 -4
  108. package/packages/pi-coding-agent/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  109. package/packages/pi-coding-agent/dist/core/export-html/ansi-to-html.js +1 -1
  110. package/packages/pi-coding-agent/dist/core/export-html/ansi-to-html.js.map +1 -1
  111. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +0 -5
  112. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  113. package/packages/pi-coding-agent/dist/core/extensions/runner.js +0 -13
  114. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  115. package/packages/pi-coding-agent/dist/core/keybindings.d.ts +0 -8
  116. package/packages/pi-coding-agent/dist/core/keybindings.d.ts.map +1 -1
  117. package/packages/pi-coding-agent/dist/core/keybindings.js +2 -2
  118. package/packages/pi-coding-agent/dist/core/keybindings.js.map +1 -1
  119. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts +0 -17
  120. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  121. package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -62
  122. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  123. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts +0 -2
  124. package/packages/pi-coding-agent/dist/core/lsp/config.d.ts.map +1 -1
  125. package/packages/pi-coding-agent/dist/core/lsp/config.js +0 -7
  126. package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
  127. package/packages/pi-coding-agent/dist/core/lsp/edits.d.ts +0 -5
  128. package/packages/pi-coding-agent/dist/core/lsp/edits.d.ts.map +1 -1
  129. package/packages/pi-coding-agent/dist/core/lsp/edits.js +1 -1
  130. package/packages/pi-coding-agent/dist/core/lsp/edits.js.map +1 -1
  131. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts +0 -1
  132. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  133. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +1 -1
  134. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  135. package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts +1 -6
  136. package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts.map +1 -1
  137. package/packages/pi-coding-agent/dist/core/lsp/utils.js +1 -28
  138. package/packages/pi-coding-agent/dist/core/lsp/utils.js.map +1 -1
  139. package/packages/pi-coding-agent/dist/core/messages.d.ts +0 -8
  140. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  141. package/packages/pi-coding-agent/dist/core/messages.js +5 -5
  142. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  143. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +0 -3
  144. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  145. package/packages/pi-coding-agent/dist/core/model-registry.js +1 -3
  146. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  147. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts +1 -26
  148. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  149. package/packages/pi-coding-agent/dist/core/model-resolver.js +3 -59
  150. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  151. package/packages/pi-coding-agent/dist/core/prompt-templates.d.ts +0 -17
  152. package/packages/pi-coding-agent/dist/core/prompt-templates.d.ts.map +1 -1
  153. package/packages/pi-coding-agent/dist/core/prompt-templates.js +2 -2
  154. package/packages/pi-coding-agent/dist/core/prompt-templates.js.map +1 -1
  155. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +0 -4
  156. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  157. package/packages/pi-coding-agent/dist/core/session-manager.js +2 -4
  158. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  159. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +0 -12
  160. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  161. package/packages/pi-coding-agent/dist/core/settings-manager.js +2 -2
  162. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/migrations.d.ts +0 -16
  164. package/packages/pi-coding-agent/dist/migrations.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/migrations.js +2 -2
  166. package/packages/pi-coding-agent/dist/migrations.js.map +1 -1
  167. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector-search.d.ts +0 -2
  168. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  169. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector-search.js +2 -2
  170. package/packages/pi-coding-agent/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  171. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +1 -24
  172. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  173. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +50 -512
  174. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  175. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts +71 -0
  176. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -0
  177. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +514 -0
  178. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -0
  179. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +65 -4
  180. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  181. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +6 -23
  182. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts +12 -0
  184. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -0
  185. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +175 -0
  186. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -0
  187. package/packages/pi-coding-agent/dist/utils/changelog.d.ts +0 -4
  188. package/packages/pi-coding-agent/dist/utils/changelog.d.ts.map +1 -1
  189. package/packages/pi-coding-agent/dist/utils/changelog.js +1 -1
  190. package/packages/pi-coding-agent/dist/utils/changelog.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/utils/clipboard-image.d.ts +0 -1
  192. package/packages/pi-coding-agent/dist/utils/clipboard-image.d.ts.map +1 -1
  193. package/packages/pi-coding-agent/dist/utils/clipboard-image.js +1 -1
  194. package/packages/pi-coding-agent/dist/utils/clipboard-image.js.map +1 -1
  195. package/packages/pi-coding-agent/dist/utils/photon.d.ts +0 -19
  196. package/packages/pi-coding-agent/dist/utils/photon.d.ts.map +1 -1
  197. package/packages/pi-coding-agent/dist/utils/photon.js +1 -120
  198. package/packages/pi-coding-agent/dist/utils/photon.js.map +1 -1
  199. package/packages/pi-coding-agent/dist/utils/tools-manager.d.ts +0 -1
  200. package/packages/pi-coding-agent/dist/utils/tools-manager.d.ts.map +1 -1
  201. package/packages/pi-coding-agent/dist/utils/tools-manager.js +1 -1
  202. package/packages/pi-coding-agent/dist/utils/tools-manager.js.map +1 -1
  203. package/packages/pi-coding-agent/package.json +1 -1
  204. package/packages/pi-coding-agent/src/config.ts +5 -10
  205. package/packages/pi-coding-agent/src/core/export-html/ansi-to-html.ts +1 -1
  206. package/packages/pi-coding-agent/src/core/extensions/runner.ts +0 -13
  207. package/packages/pi-coding-agent/src/core/keybindings.ts +2 -2
  208. package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -73
  209. package/packages/pi-coding-agent/src/core/lsp/config.ts +0 -11
  210. package/packages/pi-coding-agent/src/core/lsp/edits.ts +1 -1
  211. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +1 -1
  212. package/packages/pi-coding-agent/src/core/lsp/utils.ts +1 -33
  213. package/packages/pi-coding-agent/src/core/messages.ts +5 -5
  214. package/packages/pi-coding-agent/src/core/model-registry.ts +0 -2
  215. package/packages/pi-coding-agent/src/core/model-resolver.ts +3 -77
  216. package/packages/pi-coding-agent/src/core/prompt-templates.ts +2 -2
  217. package/packages/pi-coding-agent/src/core/session-manager.ts +2 -4
  218. package/packages/pi-coding-agent/src/core/settings-manager.ts +2 -2
  219. package/packages/pi-coding-agent/src/migrations.ts +2 -2
  220. package/packages/pi-coding-agent/src/modes/interactive/components/session-selector-search.ts +2 -2
  221. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +50 -561
  222. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +653 -0
  223. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +7 -26
  224. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +196 -0
  225. package/packages/pi-coding-agent/src/utils/changelog.ts +1 -1
  226. package/packages/pi-coding-agent/src/utils/clipboard-image.ts +1 -1
  227. package/packages/pi-coding-agent/src/utils/photon.ts +0 -137
  228. package/packages/pi-coding-agent/src/utils/tools-manager.ts +1 -1
  229. package/packages/pi-tui/dist/components/editor.d.ts +0 -10
  230. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  231. package/packages/pi-tui/dist/components/editor.js +1 -1
  232. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  233. package/packages/pi-tui/dist/overlay-layout.d.ts +55 -0
  234. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -0
  235. package/packages/pi-tui/dist/overlay-layout.js +288 -0
  236. package/packages/pi-tui/dist/overlay-layout.js.map +1 -0
  237. package/packages/pi-tui/dist/tui.d.ts +0 -22
  238. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  239. package/packages/pi-tui/dist/tui.js +6 -272
  240. package/packages/pi-tui/dist/tui.js.map +1 -1
  241. package/packages/pi-tui/dist/utils.d.ts +0 -7
  242. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  243. package/packages/pi-tui/dist/utils.js +0 -44
  244. package/packages/pi-tui/dist/utils.js.map +1 -1
  245. package/packages/pi-tui/src/components/editor.ts +1 -1
  246. package/packages/pi-tui/src/overlay-layout.ts +372 -0
  247. package/packages/pi-tui/src/tui.ts +11 -312
  248. package/packages/pi-tui/src/utils.ts +0 -43
  249. package/pkg/dist/core/export-html/ansi-to-html.d.ts +0 -4
  250. package/pkg/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  251. package/pkg/dist/core/export-html/ansi-to-html.js +1 -1
  252. package/pkg/dist/core/export-html/ansi-to-html.js.map +1 -1
  253. package/pkg/dist/modes/interactive/theme/theme.d.ts +65 -4
  254. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  255. package/pkg/dist/modes/interactive/theme/theme.js +6 -23
  256. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  257. package/pkg/dist/modes/interactive/theme/themes.d.ts +12 -0
  258. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -0
  259. package/pkg/dist/modes/interactive/theme/themes.js +175 -0
  260. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -0
  261. package/pkg/package.json +1 -1
  262. package/src/resources/extensions/gsd/auto/session.ts +47 -30
  263. package/src/resources/extensions/gsd/auto-dashboard.ts +28 -131
  264. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +6 -1
  265. package/src/resources/extensions/gsd/auto-dispatch.ts +135 -91
  266. package/src/resources/extensions/gsd/auto-loop.ts +1665 -0
  267. package/src/resources/extensions/gsd/auto-observability.ts +4 -2
  268. package/src/resources/extensions/gsd/auto-post-unit.ts +85 -228
  269. package/src/resources/extensions/gsd/auto-prompts.ts +138 -109
  270. package/src/resources/extensions/gsd/auto-recovery.ts +124 -118
  271. package/src/resources/extensions/gsd/auto-start.ts +440 -354
  272. package/src/resources/extensions/gsd/auto-supervisor.ts +5 -12
  273. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +8 -8
  274. package/src/resources/extensions/gsd/auto-timers.ts +3 -4
  275. package/src/resources/extensions/gsd/auto-verification.ts +76 -90
  276. package/src/resources/extensions/gsd/auto-worktree-sync.ts +204 -0
  277. package/src/resources/extensions/gsd/auto-worktree.ts +389 -141
  278. package/src/resources/extensions/gsd/auto.ts +515 -1199
  279. package/src/resources/extensions/gsd/captures.ts +10 -4
  280. package/src/resources/extensions/gsd/dispatch-guard.ts +13 -9
  281. package/src/resources/extensions/gsd/docs/preferences-reference.md +25 -18
  282. package/src/resources/extensions/gsd/doctor-checks.ts +3 -4
  283. package/src/resources/extensions/gsd/git-service.ts +8 -1
  284. package/src/resources/extensions/gsd/gitignore.ts +4 -2
  285. package/src/resources/extensions/gsd/gsd-db.ts +375 -180
  286. package/src/resources/extensions/gsd/index.ts +104 -263
  287. package/src/resources/extensions/gsd/post-unit-hooks.ts +13 -13
  288. package/src/resources/extensions/gsd/progress-score.ts +65 -200
  289. package/src/resources/extensions/gsd/quick.ts +121 -125
  290. package/src/resources/extensions/gsd/session-lock.ts +11 -0
  291. package/src/resources/extensions/gsd/templates/preferences.md +1 -0
  292. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +32 -59
  293. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +75 -27
  294. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  295. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +37 -0
  296. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1458 -0
  297. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +8 -162
  298. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -108
  299. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +1 -3
  300. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +0 -3
  301. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +58 -0
  302. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -55
  303. package/src/resources/extensions/gsd/tests/headless-query.test.ts +22 -0
  304. package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +8 -11
  305. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +4 -6
  306. package/src/resources/extensions/gsd/tests/run-uat.test.ts +3 -3
  307. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +64 -0
  308. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +181 -0
  309. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +0 -3
  310. package/src/resources/extensions/gsd/tests/token-profile.test.ts +6 -6
  311. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -6
  312. package/src/resources/extensions/gsd/tests/undo.test.ts +6 -0
  313. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +24 -26
  314. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +7 -201
  315. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
  316. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
  317. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +0 -3
  318. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +705 -0
  319. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +57 -106
  320. package/src/resources/extensions/gsd/tests/worktree.test.ts +5 -1
  321. package/src/resources/extensions/gsd/tests/write-gate.test.ts +43 -132
  322. package/src/resources/extensions/gsd/types.ts +90 -81
  323. package/src/resources/extensions/gsd/undo.ts +42 -46
  324. package/src/resources/extensions/gsd/unit-runtime.ts +14 -18
  325. package/src/resources/extensions/gsd/verification-evidence.ts +1 -3
  326. package/src/resources/extensions/gsd/verification-gate.ts +6 -39
  327. package/src/resources/extensions/gsd/worktree-command.ts +36 -24
  328. package/src/resources/extensions/gsd/worktree-manager.ts +2 -3
  329. package/src/resources/extensions/gsd/worktree-resolver.ts +485 -0
  330. package/src/resources/extensions/gsd/worktree.ts +7 -44
  331. package/src/resources/extensions/mcp-client/index.ts +2 -1
  332. package/dist/resources/extensions/gsd/auto-constants.js +0 -5
  333. package/dist/resources/extensions/gsd/auto-idempotency.js +0 -106
  334. package/dist/resources/extensions/gsd/auto-stuck-detection.js +0 -165
  335. package/dist/resources/extensions/gsd/mechanical-completion.js +0 -351
  336. package/packages/pi-coding-agent/dist/modes/interactive/theme/dark.json +0 -85
  337. package/packages/pi-coding-agent/dist/modes/interactive/theme/light.json +0 -84
  338. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.json +0 -335
  339. package/packages/pi-coding-agent/src/modes/interactive/theme/dark.json +0 -85
  340. package/packages/pi-coding-agent/src/modes/interactive/theme/light.json +0 -84
  341. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.json +0 -335
  342. package/pkg/dist/modes/interactive/theme/dark.json +0 -85
  343. package/pkg/dist/modes/interactive/theme/light.json +0 -84
  344. package/pkg/dist/modes/interactive/theme/theme-schema.json +0 -335
  345. package/src/resources/extensions/gsd/auto-constants.ts +0 -6
  346. package/src/resources/extensions/gsd/auto-idempotency.ts +0 -151
  347. package/src/resources/extensions/gsd/auto-stuck-detection.ts +0 -221
  348. package/src/resources/extensions/gsd/mechanical-completion.ts +0 -430
  349. package/src/resources/extensions/gsd/tests/auto-dispatch-loop.test.ts +0 -691
  350. package/src/resources/extensions/gsd/tests/auto-reentrancy-guard.test.ts +0 -127
  351. package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +0 -123
  352. package/src/resources/extensions/gsd/tests/dispatch-stall-guard.test.ts +0 -126
  353. package/src/resources/extensions/gsd/tests/loop-regression.test.ts +0 -874
  354. package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +0 -356
  355. package/src/resources/extensions/gsd/tests/progress-score.test.ts +0 -206
  356. package/src/resources/extensions/gsd/tests/session-lock.test.ts +0 -434
@@ -1,14 +1,13 @@
1
1
  /**
2
- * Auto-mode Supervisor — signal handling and working-tree activity detection.
2
+ * Auto-mode Supervisor — SIGTERM handling and working-tree activity detection.
3
3
  *
4
4
  * Pure functions — no module-level globals or AutoContext dependency.
5
5
  */
6
6
  import { clearLock } from "./crash-recovery.js";
7
- import { releaseSessionLock } from "./session-lock.js";
8
7
  import { nativeHasChanges } from "./native-git-bridge.js";
9
- // ─── Signal Handling ──────────────────────────────────────────────────────────
8
+ // ─── SIGTERM Handling ─────────────────────────────────────────────────────────
10
9
  /**
11
- * Register SIGTERM and SIGINT handlers that clear lock files and exit cleanly.
10
+ * Register a SIGTERM handler that clears the lock file and exits cleanly.
12
11
  * Captures the active base path at registration time so the handler
13
12
  * always references the correct path even if the module variable changes.
14
13
  * Removes any previously registered handler before installing the new one.
@@ -16,24 +15,19 @@ import { nativeHasChanges } from "./native-git-bridge.js";
16
15
  * Returns the new handler so the caller can store and deregister it later.
17
16
  */
18
17
  export function registerSigtermHandler(currentBasePath, previousHandler) {
19
- if (previousHandler) {
18
+ if (previousHandler)
20
19
  process.off("SIGTERM", previousHandler);
21
- process.off("SIGINT", previousHandler);
22
- }
23
20
  const handler = () => {
24
- releaseSessionLock(currentBasePath);
25
21
  clearLock(currentBasePath);
26
22
  process.exit(0);
27
23
  };
28
24
  process.on("SIGTERM", handler);
29
- process.on("SIGINT", handler);
30
25
  return handler;
31
26
  }
32
- /** Deregister signal handlers (called on stop/pause). */
27
+ /** Deregister the SIGTERM handler (called on stop/pause). */
33
28
  export function deregisterSigtermHandler(handler) {
34
29
  if (handler) {
35
30
  process.off("SIGTERM", handler);
36
- process.off("SIGINT", handler);
37
31
  }
38
32
  }
39
33
  // ─── Working Tree Activity Detection ──────────────────────────────────────────
@@ -6,9 +6,9 @@
6
6
  import { readUnitRuntimeRecord, writeUnitRuntimeRecord, formatExecuteTaskRecoveryStatus, inspectExecuteTaskDurability, } from "./unit-runtime.js";
7
7
  import { resolveExpectedArtifactPath, diagnoseExpectedArtifact, skipExecuteTask, writeBlockerPlaceholder, } from "./auto-recovery.js";
8
8
  import { existsSync } from "node:fs";
9
- import { parseUnitId } from "./unit-id.js";
9
+ import { resolveAgentEnd } from "./auto-loop.js";
10
10
  export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rctx) {
11
- const { basePath, verbose, currentUnitStartedAt, unitRecoveryCount, dispatchNextUnit } = rctx;
11
+ const { basePath, verbose, currentUnitStartedAt, unitRecoveryCount } = rctx;
12
12
  const runtime = readUnitRuntimeRecord(basePath, unitType, unitId);
13
13
  const recoveryAttempts = runtime?.recoveryAttempts ?? 0;
14
14
  const maxRecoveryAttempts = reason === "idle" ? 2 : 1;
@@ -36,7 +36,7 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
36
36
  });
37
37
  ctx.ui.notify(`${reason === "idle" ? "Idle" : "Timeout"} recovery: ${unitType} ${unitId} already completed on disk. Continuing auto-mode. (attempt ${attemptNumber})`, "info");
38
38
  unitRecoveryCount.delete(recoveryKey);
39
- await dispatchNextUnit(ctx, pi);
39
+ resolveAgentEnd({ messages: [], _synthetic: "timeout-recovery" });
40
40
  return "recovered";
41
41
  }
42
42
  if (recoveryAttempts < maxRecoveryAttempts) {
@@ -80,7 +80,7 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
80
80
  }
81
81
  // Retries exhausted — write missing durable artifacts and advance.
82
82
  const diagnostic = formatExecuteTaskRecoveryStatus(status);
83
- const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
83
+ const [mid, sid, tid] = unitId.split("/");
84
84
  const skipped = mid && sid && tid
85
85
  ? skipExecuteTask(basePath, mid, sid, tid, status, reason, maxRecoveryAttempts)
86
86
  : false;
@@ -93,7 +93,7 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
93
93
  });
94
94
  ctx.ui.notify(`${unitType} ${unitId} skipped after ${maxRecoveryAttempts} recovery attempts (${diagnostic}). Blocker artifacts written. Advancing pipeline. (attempt ${attemptNumber})`, "warning");
95
95
  unitRecoveryCount.delete(recoveryKey);
96
- await dispatchNextUnit(ctx, pi);
96
+ resolveAgentEnd({ messages: [], _synthetic: "timeout-recovery" });
97
97
  return "recovered";
98
98
  }
99
99
  // Fallback: couldn't write skip artifacts — pause as before.
@@ -118,7 +118,7 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
118
118
  });
119
119
  ctx.ui.notify(`${reason === "idle" ? "Idle" : "Timeout"} recovery: ${unitType} ${unitId} artifact already exists on disk. Advancing. (attempt ${attemptNumber})`, "info");
120
120
  unitRecoveryCount.delete(recoveryKey);
121
- await dispatchNextUnit(ctx, pi);
121
+ resolveAgentEnd({ messages: [], _synthetic: "timeout-recovery" });
122
122
  return "recovered";
123
123
  }
124
124
  if (recoveryAttempts < maxRecoveryAttempts) {
@@ -170,7 +170,7 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
170
170
  });
171
171
  ctx.ui.notify(`${unitType} ${unitId} skipped after ${maxRecoveryAttempts} recovery attempts. Blocker placeholder written to ${placeholder}. Advancing pipeline. (attempt ${attemptNumber})`, "warning");
172
172
  unitRecoveryCount.delete(recoveryKey);
173
- await dispatchNextUnit(ctx, pi);
173
+ resolveAgentEnd({ messages: [], _synthetic: "timeout-recovery" });
174
174
  return "recovered";
175
175
  }
176
176
  // Fallback: couldn't resolve artifact path — pause as before.
@@ -2,7 +2,7 @@
2
2
  * Unit supervision timers — soft timeout warning, idle watchdog,
3
3
  * hard timeout, and context-pressure monitor.
4
4
  *
5
- * Extracted from dispatchNextUnit() in auto.ts. All timers are set up
5
+ * Originally extracted from dispatchNextUnit() in auto.ts (now deleted replaced by autoLoop).
6
6
  * via startUnitSupervision() and torn down by the caller via clearUnitTimeout().
7
7
  */
8
8
  import { readUnitRuntimeRecord, writeUnitRuntimeRecord } from "./unit-runtime.js";
@@ -13,7 +13,6 @@ import { detectWorkingTreeActivity } from "./auto-supervisor.js";
13
13
  import { closeoutUnit } from "./auto-unit-closeout.js";
14
14
  import { saveActivityLog } from "./activity-log.js";
15
15
  import { recoverTimedOutUnit } from "./auto-timeout-recovery.js";
16
- import { getErrorMessage } from "./error-utils.js";
17
16
  /**
18
17
  * Set up all four supervision timers for the current unit:
19
18
  * 1. Soft timeout warning (wrapup)
@@ -98,7 +97,7 @@ export function startUnitSupervision(sctx) {
98
97
  await pauseAuto(ctx, pi);
99
98
  }
100
99
  catch (err) {
101
- const message = getErrorMessage(err);
100
+ const message = err instanceof Error ? err.message : String(err);
102
101
  console.error(`[idle-watchdog] Unhandled error: ${message}`);
103
102
  try {
104
103
  ctx.ui.notify(`Idle watchdog error: ${message}`, "warning");
@@ -129,7 +128,7 @@ export function startUnitSupervision(sctx) {
129
128
  await pauseAuto(ctx, pi);
130
129
  }
131
130
  catch (err) {
132
- const message = getErrorMessage(err);
131
+ const message = err instanceof Error ? err.message : String(err);
133
132
  console.error(`[hard-timeout] Unhandled error: ${message}`);
134
133
  try {
135
134
  ctx.ui.notify(`Hard timeout error: ${message}`, "warning");
@@ -14,18 +14,18 @@ import { resolveSliceFile, resolveSlicePath } from "./paths.js";
14
14
  import { loadEffectiveGSDPreferences } from "./preferences.js";
15
15
  import { runVerificationGate, formatFailureContext, captureRuntimeErrors, runDependencyAudit, } from "./verification-gate.js";
16
16
  import { writeVerificationJSON } from "./verification-evidence.js";
17
- import { removePersistedKey } from "./auto-recovery.js";
18
17
  import { join } from "node:path";
19
- import { getErrorMessage } from "./error-utils.js";
20
- import { parseUnitId } from "./unit-id.js";
18
+ function isInfraVerificationFailure(stderr) {
19
+ return /\b(ENOENT|ENOTFOUND|ETIMEDOUT|ECONNRESET|EAI_AGAIN|spawn\s+\S+\s+ENOENT|command not found)\b/i.test(stderr);
20
+ }
21
21
  /**
22
22
  * Run the verification gate for the current execute-task unit.
23
23
  * Returns:
24
24
  * - "continue" — gate passed (or no checks configured), proceed normally
25
- * - "retry" — gate failed with retries remaining, dispatchNextUnit already called
25
+ * - "retry" — gate failed with retries remaining, s.pendingVerificationRetry set for loop re-iteration
26
26
  * - "pause" — gate failed with retries exhausted, pauseAuto already called
27
27
  */
28
- export async function runPostUnitVerification(vctx, dispatchNextUnit, startDispatchGapWatchdog, pauseAuto) {
28
+ export async function runPostUnitVerification(vctx, pauseAuto) {
29
29
  const { s, ctx, pi } = vctx;
30
30
  if (!s.currentUnit || s.currentUnit.type !== "execute-task") {
31
31
  return "continue";
@@ -34,15 +34,16 @@ export async function runPostUnitVerification(vctx, dispatchNextUnit, startDispa
34
34
  const effectivePrefs = loadEffectiveGSDPreferences();
35
35
  const prefs = effectivePrefs?.preferences;
36
36
  // Read task plan verify field
37
- const { milestone: mid, slice: sid, task: tid } = parseUnitId(s.currentUnit.id);
37
+ const parts = s.currentUnit.id.split("/");
38
38
  let taskPlanVerify;
39
- if (mid && sid && tid) {
39
+ if (parts.length >= 3) {
40
+ const [mid, sid, tid] = parts;
40
41
  const planFile = resolveSliceFile(s.basePath, mid, sid, "PLAN");
41
42
  if (planFile) {
42
43
  const planContent = await loadFile(planFile);
43
44
  if (planContent) {
44
45
  const slicePlan = parsePlan(planContent);
45
- const taskEntry = slicePlan?.tasks?.find(t => t.id === tid);
46
+ const taskEntry = slicePlan?.tasks?.find((t) => t.id === tid);
46
47
  taskPlanVerify = taskEntry?.verify;
47
48
  }
48
49
  }
@@ -58,7 +59,7 @@ export async function runPostUnitVerification(vctx, dispatchNextUnit, startDispa
58
59
  const runtimeErrors = await captureRuntimeErrors();
59
60
  if (runtimeErrors.length > 0) {
60
61
  result.runtimeErrors = runtimeErrors;
61
- if (runtimeErrors.some(e => e.blocking)) {
62
+ if (runtimeErrors.some((e) => e.blocking)) {
62
63
  result.passed = false;
63
64
  }
64
65
  }
@@ -73,48 +74,30 @@ export async function runPostUnitVerification(vctx, dispatchNextUnit, startDispa
73
74
  }
74
75
  // Auto-fix retry preferences
75
76
  const autoFixEnabled = prefs?.verification_auto_fix !== false;
76
- const maxRetries = typeof prefs?.verification_max_retries === "number" ? prefs.verification_max_retries : 2;
77
- const completionKey = `${s.currentUnit.type}/${s.currentUnit.id}`;
77
+ const maxRetries = typeof prefs?.verification_max_retries === "number"
78
+ ? prefs.verification_max_retries
79
+ : 2;
78
80
  if (result.checks.length > 0) {
79
- const blockingChecks = result.checks.filter(c => c.blocking);
80
- const advisoryChecks = result.checks.filter(c => !c.blocking);
81
- const blockingPassCount = blockingChecks.filter(c => c.exitCode === 0).length;
82
- const advisoryFailCount = advisoryChecks.filter(c => c.exitCode !== 0).length;
81
+ const passCount = result.checks.filter((c) => c.exitCode === 0).length;
82
+ const total = result.checks.length;
83
83
  if (result.passed) {
84
- let msg = blockingChecks.length > 0
85
- ? `Verification gate: ${blockingPassCount}/${blockingChecks.length} blocking checks passed`
86
- : `Verification gate: passed (no blocking checks)`;
87
- if (advisoryFailCount > 0) {
88
- msg += ` (${advisoryFailCount} advisory warning${advisoryFailCount > 1 ? "s" : ""})`;
89
- }
90
- ctx.ui.notify(msg);
91
- // Log advisory warnings to stderr for visibility
92
- if (advisoryFailCount > 0) {
93
- const advisoryFailures = advisoryChecks.filter(c => c.exitCode !== 0);
94
- process.stderr.write(`verification-gate: ${advisoryFailCount} advisory (non-blocking) failure(s)\n`);
95
- for (const f of advisoryFailures) {
96
- process.stderr.write(` [advisory] ${f.command} exited ${f.exitCode}\n`);
97
- }
98
- }
84
+ ctx.ui.notify(`Verification gate: ${passCount}/${total} checks passed`);
99
85
  }
100
86
  else {
101
- const blockingFailures = blockingChecks.filter(c => c.exitCode !== 0);
102
- const failNames = blockingFailures.map(f => f.command).join(", ");
87
+ const failures = result.checks.filter((c) => c.exitCode !== 0);
88
+ const failNames = failures.map((f) => f.command).join(", ");
103
89
  ctx.ui.notify(`Verification gate: FAILED — ${failNames}`);
104
- process.stderr.write(`verification-gate: ${blockingFailures.length}/${blockingChecks.length} blocking checks failed\n`);
105
- for (const f of blockingFailures) {
90
+ process.stderr.write(`verification-gate: ${total - passCount}/${total} checks failed\n`);
91
+ for (const f of failures) {
106
92
  process.stderr.write(` ${f.command} exited ${f.exitCode}\n`);
107
93
  if (f.stderr)
108
94
  process.stderr.write(` stderr: ${f.stderr.slice(0, 500)}\n`);
109
95
  }
110
- if (advisoryFailCount > 0) {
111
- process.stderr.write(`verification-gate: ${advisoryFailCount} additional advisory (non-blocking) failure(s)\n`);
112
- }
113
96
  }
114
97
  }
115
98
  // Log blocking runtime errors
116
- if (result.runtimeErrors?.some(e => e.blocking)) {
117
- const blockingErrors = result.runtimeErrors.filter(e => e.blocking);
99
+ if (result.runtimeErrors?.some((e) => e.blocking)) {
100
+ const blockingErrors = result.runtimeErrors.filter((e) => e.blocking);
118
101
  process.stderr.write(`verification-gate: ${blockingErrors.length} blocking runtime error(s) detected\n`);
119
102
  for (const err of blockingErrors) {
120
103
  process.stderr.write(` [${err.source}] ${err.severity}: ${err.message.slice(0, 200)}\n`);
@@ -122,8 +105,9 @@ export async function runPostUnitVerification(vctx, dispatchNextUnit, startDispa
122
105
  }
123
106
  // Write verification evidence JSON
124
107
  const attempt = s.verificationRetryCount.get(s.currentUnit.id) ?? 0;
125
- if (mid && sid && tid) {
108
+ if (parts.length >= 3) {
126
109
  try {
110
+ const [mid, sid, tid] = parts;
127
111
  const sDir = resolveSlicePath(s.basePath, mid, sid);
128
112
  if (sDir) {
129
113
  const tasksDir = join(sDir, "tasks");
@@ -140,36 +124,24 @@ export async function runPostUnitVerification(vctx, dispatchNextUnit, startDispa
140
124
  process.stderr.write(`verification-evidence: write error — ${evidenceErr.message}\n`);
141
125
  }
142
126
  }
143
- // ── Auto-fix retry logic ──
144
- if (result.passed) {
145
- s.verificationRetryCount.delete(s.currentUnit.id);
146
- s.pendingVerificationRetry = null;
147
- return "continue";
148
- }
149
- // Check if all failures are infra errors (ETIMEDOUT, ENOENT, etc.).
150
- // Infra errors are transient OS-level problems the agent cannot fix —
151
- // retrying the entire task is wasteful and creates phantom failures.
152
- const failedChecks = result.checks.filter(c => c.exitCode !== 0);
153
- const allInfraErrors = failedChecks.length > 0 && failedChecks.every(c => c.infraError === true);
154
- if (allInfraErrors) {
155
- const infraNames = failedChecks.map(f => f.command).join(", ");
156
- ctx.ui.notify(`Verification gate: infra error (${infraNames}) — skipping retry, not a code issue`, "warning");
157
- process.stderr.write(`verification-gate: all ${failedChecks.length} failure(s) are infra errors — treating as transient, no retry\n`);
127
+ const advisoryFailure = !result.passed &&
128
+ (result.discoverySource === "package-json" ||
129
+ result.checks.some((check) => isInfraVerificationFailure(check.stderr)));
130
+ if (advisoryFailure) {
158
131
  s.verificationRetryCount.delete(s.currentUnit.id);
159
132
  s.pendingVerificationRetry = null;
133
+ ctx.ui.notify(result.discoverySource === "package-json"
134
+ ? "Verification failed in auto-discovered package.json checks — treating as advisory."
135
+ : "Verification failed due to infrastructure/runtime environment issues — treating as advisory.", "warning");
160
136
  return "continue";
161
137
  }
162
- if (result.discoverySource === "package-json") {
163
- // Auto-discovered checks from package.json may fail on pre-existing errors
164
- // that the current task didn't introduce. Don't trigger the retry loop —
165
- // log a warning and let the task proceed (#1186).
166
- process.stderr.write(`verification-gate: auto-discovered checks failed (source: package-json) — treating as advisory, not blocking\n`);
167
- ctx.ui.notify(`Verification: auto-discovered checks failed (pre-existing errors likely). Continuing without retry.`, "warning");
138
+ // ── Auto-fix retry logic ──
139
+ if (result.passed) {
168
140
  s.verificationRetryCount.delete(s.currentUnit.id);
169
141
  s.pendingVerificationRetry = null;
170
142
  return "continue";
171
143
  }
172
- if (autoFixEnabled && attempt + 1 <= maxRetries) {
144
+ else if (autoFixEnabled && attempt + 1 <= maxRetries) {
173
145
  const nextAttempt = attempt + 1;
174
146
  s.verificationRetryCount.set(s.currentUnit.id, nextAttempt);
175
147
  s.pendingVerificationRetry = {
@@ -178,17 +150,7 @@ export async function runPostUnitVerification(vctx, dispatchNextUnit, startDispa
178
150
  attempt: nextAttempt,
179
151
  };
180
152
  ctx.ui.notify(`Verification failed — auto-fix attempt ${nextAttempt}/${maxRetries}`, "warning");
181
- s.completedKeySet.delete(completionKey);
182
- removePersistedKey(s.basePath, completionKey);
183
- // Dispatch retry immediately
184
- try {
185
- await dispatchNextUnit(ctx, pi);
186
- }
187
- catch (retryDispatchErr) {
188
- const msg = getErrorMessage(retryDispatchErr);
189
- ctx.ui.notify(`Verification retry dispatch error: ${msg}`, "error");
190
- startDispatchGapWatchdog(ctx, pi);
191
- }
153
+ // Return "retry" — the autoLoop while loop will re-iterate with the retry context
192
154
  return "retry";
193
155
  }
194
156
  else {
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Worktree ↔ project root state synchronization for auto-mode.
3
+ *
4
+ * When auto-mode runs inside a worktree, dispatch-critical state files
5
+ * (.gsd/ metadata) diverge between the worktree (where work happens)
6
+ * and the project root (where startAutoMode reads initial state on restart).
7
+ * Without syncing, restarting auto-mode reads stale state from the project
8
+ * root and re-dispatches already-completed units.
9
+ *
10
+ * Also contains resource staleness detection and stale worktree escape.
11
+ */
12
+ import { existsSync, readFileSync, unlinkSync, readdirSync, } from "node:fs";
13
+ import { join, sep as pathSep } from "node:path";
14
+ import { homedir } from "node:os";
15
+ import { safeCopy, safeCopyRecursive } from "./safe-fs.js";
16
+ // ─── Project Root → Worktree Sync ─────────────────────────────────────────
17
+ /**
18
+ * Sync milestone artifacts from project root INTO worktree before deriveState.
19
+ * Covers the case where the LLM wrote artifacts to the main repo filesystem
20
+ * (e.g. via absolute paths) but the worktree has stale data. Also deletes
21
+ * gsd.db in the worktree so it rebuilds from fresh disk state (#853).
22
+ * Non-fatal — sync failure should never block dispatch.
23
+ */
24
+ export function syncProjectRootToWorktree(projectRoot, worktreePath, milestoneId) {
25
+ if (!worktreePath || !projectRoot || worktreePath === projectRoot)
26
+ return;
27
+ if (!milestoneId)
28
+ return;
29
+ const prGsd = join(projectRoot, ".gsd");
30
+ const wtGsd = join(worktreePath, ".gsd");
31
+ // Copy milestone directory from project root to worktree if the project root
32
+ // has newer artifacts (e.g. slices that don't exist in the worktree yet)
33
+ safeCopyRecursive(join(prGsd, "milestones", milestoneId), join(wtGsd, "milestones", milestoneId));
34
+ // Delete worktree gsd.db so it rebuilds from the freshly synced files.
35
+ // Stale DB rows are the root cause of the infinite skip loop (#853).
36
+ try {
37
+ const wtDb = join(wtGsd, "gsd.db");
38
+ if (existsSync(wtDb)) {
39
+ unlinkSync(wtDb);
40
+ }
41
+ }
42
+ catch {
43
+ /* non-fatal */
44
+ }
45
+ }
46
+ // ─── Worktree → Project Root Sync ─────────────────────────────────────────
47
+ /**
48
+ * Sync dispatch-critical .gsd/ state files from worktree to project root.
49
+ * Only runs when inside an auto-worktree (worktreePath differs from projectRoot).
50
+ * Copies: STATE.md + active milestone directory (roadmap, slice plans, task summaries).
51
+ * Non-fatal — sync failure should never block dispatch.
52
+ */
53
+ export function syncStateToProjectRoot(worktreePath, projectRoot, milestoneId) {
54
+ if (!worktreePath || !projectRoot || worktreePath === projectRoot)
55
+ return;
56
+ if (!milestoneId)
57
+ return;
58
+ const wtGsd = join(worktreePath, ".gsd");
59
+ const prGsd = join(projectRoot, ".gsd");
60
+ // 1. STATE.md — the quick-glance status used by initial deriveState()
61
+ safeCopy(join(wtGsd, "STATE.md"), join(prGsd, "STATE.md"), { force: true });
62
+ // 2. Milestone directory — ROADMAP, slice PLANs, task summaries
63
+ // Copy the entire milestone .gsd subtree so deriveState reads current checkboxes
64
+ safeCopyRecursive(join(wtGsd, "milestones", milestoneId), join(prGsd, "milestones", milestoneId), { force: true });
65
+ // 4. Runtime records — unit dispatch state used by selfHealRuntimeRecords().
66
+ // Without this, a crash during a unit leaves the runtime record only in the
67
+ // worktree. If the next session resolves basePath before worktree re-entry,
68
+ // selfHeal can't find or clear the stale record (#769).
69
+ safeCopyRecursive(join(wtGsd, "runtime", "units"), join(prGsd, "runtime", "units"), { force: true });
70
+ }
71
+ // ─── Resource Staleness ───────────────────────────────────────────────────
72
+ /**
73
+ * Read the resource version (semver) from the managed-resources manifest.
74
+ * Uses gsdVersion instead of syncedAt so that launching a second session
75
+ * doesn't falsely trigger staleness (#804).
76
+ */
77
+ export function readResourceVersion() {
78
+ const agentDir = process.env.GSD_CODING_AGENT_DIR || join(homedir(), ".gsd", "agent");
79
+ const manifestPath = join(agentDir, "managed-resources.json");
80
+ try {
81
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
82
+ return typeof manifest?.gsdVersion === "string"
83
+ ? manifest.gsdVersion
84
+ : null;
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
90
+ /**
91
+ * Check if managed resources have been updated since session start.
92
+ * Returns a warning message if stale, null otherwise.
93
+ */
94
+ export function checkResourcesStale(versionOnStart) {
95
+ if (versionOnStart === null)
96
+ return null;
97
+ const current = readResourceVersion();
98
+ if (current === null)
99
+ return null;
100
+ if (current !== versionOnStart) {
101
+ return "GSD resources were updated since this session started. Restart gsd to load the new code.";
102
+ }
103
+ return null;
104
+ }
105
+ // ─── Stale Worktree Escape ────────────────────────────────────────────────
106
+ /**
107
+ * Detect and escape a stale worktree cwd (#608).
108
+ *
109
+ * After milestone completion + merge, the worktree directory is removed but
110
+ * the process cwd may still point inside `.gsd/worktrees/<MID>/`.
111
+ * When a new session starts, `process.cwd()` is passed as `base` to startAuto
112
+ * and all subsequent writes land in the wrong directory. This function detects
113
+ * that scenario and chdir back to the project root.
114
+ *
115
+ * Returns the corrected base path.
116
+ */
117
+ export function escapeStaleWorktree(base) {
118
+ const marker = `${pathSep}.gsd${pathSep}worktrees${pathSep}`;
119
+ const idx = base.indexOf(marker);
120
+ if (idx === -1)
121
+ return base;
122
+ // base is inside .gsd/worktrees/<something> — extract the project root
123
+ const projectRoot = base.slice(0, idx);
124
+ try {
125
+ process.chdir(projectRoot);
126
+ }
127
+ catch {
128
+ // If chdir fails, return the original — caller will handle errors downstream
129
+ return base;
130
+ }
131
+ return projectRoot;
132
+ }
133
+ /**
134
+ * Clean stale runtime unit files for completed milestones.
135
+ *
136
+ * After restart, stale runtime/units/*.json from prior milestones can
137
+ * cause deriveState to resume the wrong milestone (#887). Removes files
138
+ * for milestones that have a SUMMARY (fully complete).
139
+ */
140
+ export function cleanStaleRuntimeUnits(gsdRootPath, hasMilestoneSummary) {
141
+ const runtimeUnitsDir = join(gsdRootPath, "runtime", "units");
142
+ if (!existsSync(runtimeUnitsDir))
143
+ return 0;
144
+ let cleaned = 0;
145
+ try {
146
+ for (const file of readdirSync(runtimeUnitsDir)) {
147
+ if (!file.endsWith(".json"))
148
+ continue;
149
+ const midMatch = file.match(/(M\d+(?:-[a-z0-9]{6})?)/);
150
+ if (!midMatch)
151
+ continue;
152
+ if (hasMilestoneSummary(midMatch[1])) {
153
+ try {
154
+ unlinkSync(join(runtimeUnitsDir, file));
155
+ cleaned++;
156
+ }
157
+ catch {
158
+ /* non-fatal */
159
+ }
160
+ }
161
+ }
162
+ }
163
+ catch {
164
+ /* non-fatal */
165
+ }
166
+ return cleaned;
167
+ }