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
@@ -5,22 +5,39 @@
5
5
  * manual `/worktree` which uses `worktree/<name>` branches). This module
6
6
  * manages create, enter, detect, and teardown for auto-mode worktrees.
7
7
  */
8
- import { existsSync, readFileSync, realpathSync, unlinkSync, statSync, rmSync, readdirSync, cpSync, mkdirSync, lstatSync as lstatSyncFn } from "node:fs";
8
+ import { existsSync, cpSync, readFileSync, readdirSync, mkdirSync, realpathSync, unlinkSync, lstatSync as lstatSyncFn, } from "node:fs";
9
9
  import { isAbsolute, join } from "node:path";
10
10
  import { GSDError, GSD_IO_ERROR, GSD_GIT_ERROR } from "./errors.js";
11
+ import { copyWorktreeDb, reconcileWorktreeDb, isDbAvailable, } from "./gsd-db.js";
12
+ import { atomicWriteSync } from "./atomic-write.js";
11
13
  import { execSync } from "node:child_process";
14
+ import { safeCopy, safeCopyRecursive } from "./safe-fs.js";
15
+ import { gsdRoot } from "./paths.js";
12
16
  import { createWorktree, removeWorktree, worktreePath, } from "./worktree-manager.js";
13
- import { detectWorktreeName, nudgeGitBranchCache } from "./worktree.js";
14
- import { ensureGsdSymlink } from "./repo-identity.js";
15
- import { MergeConflictError, readIntegrationBranch, } from "./git-service.js";
17
+ import { detectWorktreeName, nudgeGitBranchCache, } from "./worktree.js";
18
+ import { MergeConflictError, readIntegrationBranch } from "./git-service.js";
16
19
  import { parseRoadmap } from "./files.js";
17
20
  import { loadEffectiveGSDPreferences } from "./preferences.js";
18
- import { gsdRoot } from "./paths.js";
19
21
  import { nativeGetCurrentBranch, nativeWorkingTreeStatus, nativeAddAll, nativeCommit, nativeCheckoutBranch, nativeMergeSquash, nativeConflictFiles, nativeCheckoutTheirs, nativeAddPaths, nativeRmForce, nativeBranchDelete, nativeBranchExists, } from "./native-git-bridge.js";
20
- import { getErrorMessage } from "./error-utils.js";
21
22
  // ─── Module State ──────────────────────────────────────────────────────────
22
23
  /** Original project root before chdir into auto-worktree. */
23
24
  let originalBase = null;
25
+ function clearProjectRootStateFiles(basePath, milestoneId) {
26
+ const gsdDir = gsdRoot(basePath);
27
+ const transientFiles = [
28
+ join(gsdDir, "STATE.md"),
29
+ join(gsdDir, "auto.lock"),
30
+ join(gsdDir, "milestones", milestoneId, `${milestoneId}-META.json`),
31
+ ];
32
+ for (const file of transientFiles) {
33
+ try {
34
+ unlinkSync(file);
35
+ }
36
+ catch {
37
+ /* non-fatal — file may not exist */
38
+ }
39
+ }
40
+ }
24
41
  // ─── Worktree ↔ Main Repo Sync (#1311) ──────────────────────────────────────
25
42
  /**
26
43
  * Sync .gsd/ state from the main repo into the worktree.
@@ -53,7 +70,13 @@ export function syncGsdStateToWorktree(mainBasePath, worktreePath_) {
53
70
  if (!existsSync(mainGsd) || !existsSync(wtGsd))
54
71
  return { synced };
55
72
  // Sync root-level .gsd/ files (DECISIONS, REQUIREMENTS, PROJECT, KNOWLEDGE)
56
- const rootFiles = ["DECISIONS.md", "REQUIREMENTS.md", "PROJECT.md", "KNOWLEDGE.md", "OVERRIDES.md"];
73
+ const rootFiles = [
74
+ "DECISIONS.md",
75
+ "REQUIREMENTS.md",
76
+ "PROJECT.md",
77
+ "KNOWLEDGE.md",
78
+ "OVERRIDES.md",
79
+ ];
57
80
  for (const f of rootFiles) {
58
81
  const src = join(mainGsd, f);
59
82
  const dst = join(wtGsd, f);
@@ -62,7 +85,9 @@ export function syncGsdStateToWorktree(mainBasePath, worktreePath_) {
62
85
  cpSync(src, dst);
63
86
  synced.push(f);
64
87
  }
65
- catch { /* non-fatal */ }
88
+ catch {
89
+ /* non-fatal */
90
+ }
66
91
  }
67
92
  }
68
93
  // Sync milestones: copy entire milestone directories that are missing
@@ -71,9 +96,11 @@ export function syncGsdStateToWorktree(mainBasePath, worktreePath_) {
71
96
  if (existsSync(mainMilestonesDir)) {
72
97
  try {
73
98
  mkdirSync(wtMilestonesDir, { recursive: true });
74
- const mainMilestones = readdirSync(mainMilestonesDir, { withFileTypes: true })
75
- .filter(d => d.isDirectory() && /^M\d{3}/.test(d.name))
76
- .map(d => d.name);
99
+ const mainMilestones = readdirSync(mainMilestonesDir, {
100
+ withFileTypes: true,
101
+ })
102
+ .filter((d) => d.isDirectory() && /^M\d{3}/.test(d.name))
103
+ .map((d) => d.name);
77
104
  for (const mid of mainMilestones) {
78
105
  const srcDir = join(mainMilestonesDir, mid);
79
106
  const dstDir = join(wtMilestonesDir, mid);
@@ -83,13 +110,15 @@ export function syncGsdStateToWorktree(mainBasePath, worktreePath_) {
83
110
  cpSync(srcDir, dstDir, { recursive: true });
84
111
  synced.push(`milestones/${mid}/`);
85
112
  }
86
- catch { /* non-fatal */ }
113
+ catch {
114
+ /* non-fatal */
115
+ }
87
116
  }
88
117
  else {
89
118
  // Milestone directory exists but may be missing files (stale snapshot).
90
119
  // Sync individual top-level milestone files (CONTEXT, ROADMAP, RESEARCH, etc.)
91
120
  try {
92
- const srcFiles = readdirSync(srcDir).filter(f => f.endsWith(".md") || f.endsWith(".json"));
121
+ const srcFiles = readdirSync(srcDir).filter((f) => f.endsWith(".md") || f.endsWith(".json"));
93
122
  for (const f of srcFiles) {
94
123
  const srcFile = join(srcDir, f);
95
124
  const dstFile = join(dstDir, f);
@@ -101,7 +130,9 @@ export function syncGsdStateToWorktree(mainBasePath, worktreePath_) {
101
130
  synced.push(`milestones/${mid}/${f}`);
102
131
  }
103
132
  }
104
- catch { /* non-fatal */ }
133
+ catch {
134
+ /* non-fatal */
135
+ }
105
136
  }
106
137
  }
107
138
  // Sync slices directory if it exists in main but not in worktree
@@ -112,13 +143,17 @@ export function syncGsdStateToWorktree(mainBasePath, worktreePath_) {
112
143
  cpSync(srcSlicesDir, dstSlicesDir, { recursive: true });
113
144
  synced.push(`milestones/${mid}/slices/`);
114
145
  }
115
- catch { /* non-fatal */ }
146
+ catch {
147
+ /* non-fatal */
148
+ }
116
149
  }
117
150
  else if (existsSync(srcSlicesDir) && existsSync(dstSlicesDir)) {
118
151
  // Both exist — sync missing slice directories
119
- const srcSlices = readdirSync(srcSlicesDir, { withFileTypes: true })
120
- .filter(d => d.isDirectory())
121
- .map(d => d.name);
152
+ const srcSlices = readdirSync(srcSlicesDir, {
153
+ withFileTypes: true,
154
+ })
155
+ .filter((d) => d.isDirectory())
156
+ .map((d) => d.name);
122
157
  for (const sid of srcSlices) {
123
158
  const srcSlice = join(srcSlicesDir, sid);
124
159
  const dstSlice = join(dstSlicesDir, sid);
@@ -127,16 +162,22 @@ export function syncGsdStateToWorktree(mainBasePath, worktreePath_) {
127
162
  cpSync(srcSlice, dstSlice, { recursive: true });
128
163
  synced.push(`milestones/${mid}/slices/${sid}/`);
129
164
  }
130
- catch { /* non-fatal */ }
165
+ catch {
166
+ /* non-fatal */
167
+ }
131
168
  }
132
169
  }
133
170
  }
134
171
  }
135
- catch { /* non-fatal */ }
172
+ catch {
173
+ /* non-fatal */
174
+ }
136
175
  }
137
176
  }
138
177
  }
139
- catch { /* non-fatal */ }
178
+ catch {
179
+ /* non-fatal */
180
+ }
140
181
  }
141
182
  return { synced };
142
183
  }
@@ -177,24 +218,32 @@ export function syncWorktreeStateBack(mainBasePath, worktreePath, milestoneId) {
177
218
  cpSync(src, dst, { force: true });
178
219
  synced.push(`milestones/${milestoneId}/${entry.name}`);
179
220
  }
180
- catch { /* non-fatal */ }
221
+ catch {
222
+ /* non-fatal */
223
+ }
181
224
  }
182
225
  }
183
226
  }
184
- catch { /* non-fatal */ }
227
+ catch {
228
+ /* non-fatal */
229
+ }
185
230
  // Sync slice-level files (summaries, UATs)
186
231
  const wtSlicesDir = join(wtMilestoneDir, "slices");
187
232
  const mainSlicesDir = join(mainMilestoneDir, "slices");
188
233
  if (existsSync(wtSlicesDir)) {
189
234
  try {
190
- for (const sliceEntry of readdirSync(wtSlicesDir, { withFileTypes: true })) {
235
+ for (const sliceEntry of readdirSync(wtSlicesDir, {
236
+ withFileTypes: true,
237
+ })) {
191
238
  if (!sliceEntry.isDirectory())
192
239
  continue;
193
240
  const sid = sliceEntry.name;
194
241
  const wtSliceDir = join(wtSlicesDir, sid);
195
242
  const mainSliceDir = join(mainSlicesDir, sid);
196
243
  mkdirSync(mainSliceDir, { recursive: true });
197
- for (const fileEntry of readdirSync(wtSliceDir, { withFileTypes: true })) {
244
+ for (const fileEntry of readdirSync(wtSliceDir, {
245
+ withFileTypes: true,
246
+ })) {
198
247
  if (fileEntry.isFile() && fileEntry.name.endsWith(".md")) {
199
248
  const src = join(wtSliceDir, fileEntry.name);
200
249
  const dst = join(mainSliceDir, fileEntry.name);
@@ -202,12 +251,16 @@ export function syncWorktreeStateBack(mainBasePath, worktreePath, milestoneId) {
202
251
  cpSync(src, dst, { force: true });
203
252
  synced.push(`milestones/${milestoneId}/slices/${sid}/${fileEntry.name}`);
204
253
  }
205
- catch { /* non-fatal */ }
254
+ catch {
255
+ /* non-fatal */
256
+ }
206
257
  }
207
258
  }
208
259
  }
209
260
  }
210
- catch { /* non-fatal */ }
261
+ catch {
262
+ /* non-fatal */
263
+ }
211
264
  }
212
265
  return { synced };
213
266
  }
@@ -247,7 +300,7 @@ export function runWorktreePostCreateHook(sourceDir, worktreeDir, hookPath) {
247
300
  return null;
248
301
  }
249
302
  catch (err) {
250
- const msg = getErrorMessage(err);
303
+ const msg = err instanceof Error ? err.message : String(err);
251
304
  return `Worktree post-create hook failed: ${msg}`;
252
305
  }
253
306
  }
@@ -263,6 +316,96 @@ export function autoWorktreeBranch(milestoneId) {
263
316
  * Atomic: chdir + originalBase update happen in the same try block
264
317
  * to prevent split-brain.
265
318
  */
319
+ /**
320
+ * Forward-merge plan checkbox state from the project root into a freshly
321
+ * re-attached worktree (#778).
322
+ *
323
+ * When auto-mode stops via crash (not graceful stop), the milestone branch
324
+ * HEAD may be behind the filesystem state at the project root because
325
+ * syncStateToProjectRoot() runs after every task completion but the final
326
+ * git commit may not have happened before the crash. On restart the worktree
327
+ * is re-attached to the branch HEAD, which has [ ] for the crashed task,
328
+ * causing verifyExpectedArtifact() to fail and triggering an infinite
329
+ * dispatch/skip loop.
330
+ *
331
+ * Fix: after re-attaching, read every *.md plan file in the milestone
332
+ * directory at the project root and apply any [x] checkbox states that are
333
+ * ahead of the worktree version (forward-only: never downgrade [x] → [ ]).
334
+ *
335
+ * This is safe because syncStateToProjectRoot() is the authoritative source
336
+ * of post-task state at the project root — it writes the same [x] the LLM
337
+ * produced, then the auto-commit follows. If the commit never happened, the
338
+ * filesystem copy is still valid and correct.
339
+ */
340
+ function reconcilePlanCheckboxes(projectRoot, wtPath, milestoneId) {
341
+ const srcMilestone = join(projectRoot, ".gsd", "milestones", milestoneId);
342
+ const dstMilestone = join(wtPath, ".gsd", "milestones", milestoneId);
343
+ if (!existsSync(srcMilestone) || !existsSync(dstMilestone))
344
+ return;
345
+ // Walk all markdown files in the milestone directory (plans, summaries, etc.)
346
+ function walkMd(dir) {
347
+ const results = [];
348
+ try {
349
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
350
+ const full = join(dir, entry.name);
351
+ if (entry.isDirectory()) {
352
+ results.push(...walkMd(full));
353
+ }
354
+ else if (entry.isFile() && entry.name.endsWith(".md")) {
355
+ results.push(full);
356
+ }
357
+ }
358
+ }
359
+ catch {
360
+ /* non-fatal */
361
+ }
362
+ return results;
363
+ }
364
+ for (const srcFile of walkMd(srcMilestone)) {
365
+ const rel = srcFile.slice(srcMilestone.length);
366
+ const dstFile = dstMilestone + rel;
367
+ if (!existsSync(dstFile))
368
+ continue; // only reconcile existing files
369
+ let srcContent;
370
+ let dstContent;
371
+ try {
372
+ srcContent = readFileSync(srcFile, "utf-8");
373
+ dstContent = readFileSync(dstFile, "utf-8");
374
+ }
375
+ catch {
376
+ continue;
377
+ }
378
+ if (srcContent === dstContent)
379
+ continue;
380
+ // Extract all checked task IDs from the source (project root)
381
+ // Pattern: - [x] **T<id>: or - [x] **S<id>: (case-insensitive x)
382
+ const checkedRe = /^- \[[xX]\] \*\*([TS]\d+):/gm;
383
+ const srcChecked = new Set();
384
+ for (const m of srcContent.matchAll(checkedRe))
385
+ srcChecked.add(m[1]);
386
+ if (srcChecked.size === 0)
387
+ continue;
388
+ // Forward-apply: replace [ ] → [x] for any IDs that are checked in src
389
+ let updated = dstContent;
390
+ let changed = false;
391
+ for (const id of srcChecked) {
392
+ const escapedId = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
393
+ const uncheckedRe = new RegExp(`^(- )\\[ \\]( \\*\\*${escapedId}:)`, "gm");
394
+ if (uncheckedRe.test(updated)) {
395
+ updated = updated.replace(new RegExp(`^(- )\\[ \\]( \\*\\*${escapedId}:)`, "gm"), "$1[x]$2");
396
+ changed = true;
397
+ }
398
+ }
399
+ if (changed) {
400
+ try {
401
+ atomicWriteSync(dstFile, updated, "utf-8");
402
+ }
403
+ catch {
404
+ /* non-fatal */
405
+ }
406
+ }
407
+ }
408
+ }
266
409
  export function createAutoWorktree(basePath, milestoneId) {
267
410
  const branch = autoWorktreeBranch(milestoneId);
268
411
  // Check if the milestone branch already exists — it survives auto-mode
@@ -273,20 +416,46 @@ export function createAutoWorktree(basePath, milestoneId) {
273
416
  let info;
274
417
  if (branchExists) {
275
418
  // Re-attach worktree to the existing milestone branch (preserving commits)
276
- info = createWorktree(basePath, milestoneId, { branch, reuseExistingBranch: true });
419
+ info = createWorktree(basePath, milestoneId, {
420
+ branch,
421
+ reuseExistingBranch: true,
422
+ });
277
423
  }
278
424
  else {
279
425
  // Fresh start — create branch from integration branch
280
426
  const integrationBranch = readIntegrationBranch(basePath, milestoneId) ?? undefined;
281
- info = createWorktree(basePath, milestoneId, { branch, startPoint: integrationBranch });
282
- }
283
- // Ensure worktree shares external state via symlink
284
- ensureGsdSymlink(info.path);
285
- // Sync .gsd/ state from main repo into the worktree (#1311).
286
- // Even with the symlink, the worktree may have stale git-tracked files
287
- // if .gsd/ is not gitignored. And on fresh create, the milestone files
288
- // created on main since the branch point won't be in the worktree.
289
- syncGsdStateToWorktree(basePath, info.path);
427
+ info = createWorktree(basePath, milestoneId, {
428
+ branch,
429
+ startPoint: integrationBranch,
430
+ });
431
+ }
432
+ // Copy .gsd/ planning artifacts from the source repo into the new worktree.
433
+ // Worktrees are fresh git checkouts untracked files don't carry over.
434
+ // Planning artifacts may be untracked if the project's .gitignore had a
435
+ // blanket .gsd/ rule (pre-v2.14.0). Without this copy, auto-mode loops
436
+ // on plan-slice because the plan file doesn't exist in the worktree.
437
+ //
438
+ // IMPORTANT: Skip when re-attaching to an existing branch (#759).
439
+ // The branch checkout already has committed artifacts with correct state
440
+ // (e.g. [x] for completed slices). Copying from the project root would
441
+ // overwrite them with stale data ([ ] checkboxes) because the root is
442
+ // not always fully synced.
443
+ if (!branchExists) {
444
+ copyPlanningArtifacts(basePath, info.path);
445
+ }
446
+ else {
447
+ // Re-attaching to an existing branch: forward-merge any plan checkpoint
448
+ // state from the project root into the worktree (#778).
449
+ //
450
+ // If auto-mode stopped via crash, the milestone branch HEAD may lag behind
451
+ // the project root filesystem because syncStateToProjectRoot() ran after
452
+ // task completion but the auto-commit never fired. On restart the worktree
453
+ // is re-created from the branch HEAD (which has [ ] for the crashed task),
454
+ // causing verifyExpectedArtifact() to return false → stale-key eviction →
455
+ // infinite dispatch/skip loop. Reconciling here ensures the worktree sees
456
+ // the same [x] state that syncStateToProjectRoot() wrote to the root.
457
+ reconcilePlanCheckboxes(basePath, info.path, milestoneId);
458
+ }
290
459
  // Run user-configured post-create hook (#597) — e.g. copy .env, symlink assets
291
460
  const hookError = runWorktreePostCreateHook(basePath, info.path);
292
461
  if (hookError) {
@@ -301,11 +470,52 @@ export function createAutoWorktree(basePath, milestoneId) {
301
470
  catch (err) {
302
471
  // If chdir fails, the worktree was created but we couldn't enter it.
303
472
  // Don't store originalBase -- caller can retry or clean up.
304
- throw new GSDError(GSD_IO_ERROR, `Auto-worktree created at ${info.path} but chdir failed: ${getErrorMessage(err)}`);
473
+ throw new GSDError(GSD_IO_ERROR, `Auto-worktree created at ${info.path} but chdir failed: ${err instanceof Error ? err.message : String(err)}`);
305
474
  }
306
475
  nudgeGitBranchCache(previousCwd);
307
476
  return info.path;
308
477
  }
478
+ /**
479
+ * Copy .gsd/ planning artifacts from source repo to a new worktree.
480
+ * Copies milestones/, DECISIONS.md, REQUIREMENTS.md, PROJECT.md, QUEUE.md,
481
+ * STATE.md, KNOWLEDGE.md, and OVERRIDES.md.
482
+ * Skips runtime files (auto.lock, metrics.json, etc.) and the worktrees/ dir.
483
+ * Best-effort — failures are non-fatal since auto-mode can recreate artifacts.
484
+ */
485
+ function copyPlanningArtifacts(srcBase, wtPath) {
486
+ const srcGsd = join(srcBase, ".gsd");
487
+ const dstGsd = join(wtPath, ".gsd");
488
+ if (!existsSync(srcGsd))
489
+ return;
490
+ // Copy milestones/ directory (planning files, roadmaps, plans, research)
491
+ safeCopyRecursive(join(srcGsd, "milestones"), join(dstGsd, "milestones"), {
492
+ force: true,
493
+ filter: (src) => !src.endsWith("-META.json"),
494
+ });
495
+ // Copy top-level planning files
496
+ for (const file of [
497
+ "DECISIONS.md",
498
+ "REQUIREMENTS.md",
499
+ "PROJECT.md",
500
+ "QUEUE.md",
501
+ "STATE.md",
502
+ "KNOWLEDGE.md",
503
+ "OVERRIDES.md",
504
+ ]) {
505
+ safeCopy(join(srcGsd, file), join(dstGsd, file), { force: true });
506
+ }
507
+ // Copy gsd.db if present in source
508
+ const srcDb = join(srcGsd, "gsd.db");
509
+ const destDb = join(dstGsd, "gsd.db");
510
+ if (existsSync(srcDb)) {
511
+ try {
512
+ copyWorktreeDb(srcDb, destDb);
513
+ }
514
+ catch {
515
+ /* non-fatal */
516
+ }
517
+ }
518
+ }
309
519
  /**
310
520
  * Teardown an auto-worktree: chdir back to original base, then remove
311
521
  * the worktree and its branch.
@@ -319,50 +529,28 @@ export function teardownAutoWorktree(originalBasePath, milestoneId, opts = {}) {
319
529
  originalBase = null;
320
530
  }
321
531
  catch (err) {
322
- throw new GSDError(GSD_IO_ERROR, `Failed to chdir back to ${originalBasePath} during teardown: ${getErrorMessage(err)}`);
532
+ throw new GSDError(GSD_IO_ERROR, `Failed to chdir back to ${originalBasePath} during teardown: ${err instanceof Error ? err.message : String(err)}`);
323
533
  }
324
534
  nudgeGitBranchCache(previousCwd);
325
- removeWorktree(originalBasePath, milestoneId, { branch, deleteBranch: !preserveBranch });
535
+ removeWorktree(originalBasePath, milestoneId, {
536
+ branch,
537
+ deleteBranch: !preserveBranch,
538
+ });
326
539
  }
327
540
  /**
328
541
  * Detect if the process is currently inside an auto-worktree.
329
542
  * Checks both module state and git branch prefix.
330
543
  */
331
544
  export function isInAutoWorktree(basePath) {
332
- const cwd = process.cwd();
333
- // Primary check: use originalBase if available (fast path)
334
- if (originalBase) {
335
- const resolvedBase = existsSync(basePath) ? realpathSync(basePath) : basePath;
336
- const wtDir = join(gsdRoot(resolvedBase), "worktrees");
337
- if (!cwd.startsWith(wtDir))
338
- return false;
339
- const branch = nativeGetCurrentBranch(cwd);
340
- return branch.startsWith("milestone/");
341
- }
342
- // Fallback: infer worktree status structurally when originalBase is null
343
- // (happens after session restart where module-level state is lost, #1120).
344
- // Check if cwd is inside a .gsd/worktrees/ directory and has a .git file
345
- // (worktree marker) pointing to the main repo.
346
- const worktreeMarker = join(cwd, ".git");
347
- if (!existsSync(worktreeMarker))
545
+ if (!originalBase)
348
546
  return false;
349
- try {
350
- const stat = statSync(worktreeMarker);
351
- if (stat.isDirectory())
352
- return false; // Main repo has .git dir, not file
353
- // Worktrees have a .git file with "gitdir: ..." pointing to the main repo
354
- const gitContent = readFileSync(worktreeMarker, "utf-8").trim();
355
- if (!gitContent.startsWith("gitdir:"))
356
- return false;
357
- // Verify we're inside a GSD-managed worktree
358
- if (!detectWorktreeName(cwd))
359
- return false;
360
- const branch = nativeGetCurrentBranch(cwd);
361
- return branch.startsWith("milestone/");
362
- }
363
- catch {
547
+ const cwd = process.cwd();
548
+ const resolvedBase = existsSync(basePath) ? realpathSync(basePath) : basePath;
549
+ const wtDir = join(resolvedBase, ".gsd", "worktrees");
550
+ if (!cwd.startsWith(wtDir))
364
551
  return false;
365
- }
552
+ const branch = nativeGetCurrentBranch(cwd);
553
+ return branch.startsWith("milestone/");
366
554
  }
367
555
  /**
368
556
  * Get the filesystem path for an auto-worktree, or null if it doesn't exist
@@ -418,23 +606,13 @@ export function enterAutoWorktree(basePath, milestoneId) {
418
606
  throw err;
419
607
  throw new GSDError(GSD_IO_ERROR, `Auto-worktree path ${p} exists but .git is unreadable`);
420
608
  }
421
- // Ensure worktree shares external state via symlink (#1311).
422
- // On resume (enterAutoWorktree), the symlink may be missing if it was
423
- // created before ensureGsdSymlink existed, or the .gsd/ directory may be
424
- // a stale git-tracked copy instead of a symlink. Refreshing here ensures
425
- // the worktree sees the same milestone state as the main repo.
426
- ensureGsdSymlink(p);
427
- // Sync .gsd/ state from main repo into worktree (#1311).
428
- // Covers the case where .gsd/ is a real directory (not symlinked) and
429
- // milestones were created on main after the worktree was last used.
430
- syncGsdStateToWorktree(basePath, p);
431
609
  const previousCwd = process.cwd();
432
610
  try {
433
611
  process.chdir(p);
434
612
  originalBase = basePath;
435
613
  }
436
614
  catch (err) {
437
- throw new GSDError(GSD_IO_ERROR, `Failed to enter auto-worktree at ${p}: ${getErrorMessage(err)}`);
615
+ throw new GSDError(GSD_IO_ERROR, `Failed to enter auto-worktree at ${p}: ${err instanceof Error ? err.message : String(err)}`);
438
616
  }
439
617
  nudgeGitBranchCache(previousCwd);
440
618
  return p;
@@ -450,8 +628,10 @@ export function getActiveAutoWorktreeContext() {
450
628
  if (!originalBase)
451
629
  return null;
452
630
  const cwd = process.cwd();
453
- const resolvedBase = existsSync(originalBase) ? realpathSync(originalBase) : originalBase;
454
- const wtDir = join(gsdRoot(resolvedBase), "worktrees");
631
+ const resolvedBase = existsSync(originalBase)
632
+ ? realpathSync(originalBase)
633
+ : originalBase;
634
+ const wtDir = join(resolvedBase, ".gsd", "worktrees");
455
635
  if (!cwd.startsWith(wtDir))
456
636
  return null;
457
637
  const worktreeName = detectWorktreeName(cwd);
@@ -507,54 +687,34 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
507
687
  const milestoneBranch = autoWorktreeBranch(milestoneId);
508
688
  // 1. Auto-commit dirty state in worktree before leaving
509
689
  autoCommitDirtyState(worktreeCwd);
690
+ // Reconcile worktree DB into main DB before leaving worktree context
691
+ if (isDbAvailable()) {
692
+ try {
693
+ const worktreeDbPath = join(worktreeCwd, ".gsd", "gsd.db");
694
+ const mainDbPath = join(originalBasePath_, ".gsd", "gsd.db");
695
+ reconcileWorktreeDb(mainDbPath, worktreeDbPath);
696
+ }
697
+ catch {
698
+ /* non-fatal */
699
+ }
700
+ }
510
701
  // 2. Parse roadmap for slice listing
511
702
  const roadmap = parseRoadmap(roadmapContent);
512
- const completedSlices = roadmap.slices.filter(s => s.done);
703
+ const completedSlices = roadmap.slices.filter((s) => s.done);
513
704
  // 3. chdir to original base
514
705
  const previousCwd = process.cwd();
515
706
  process.chdir(originalBasePath_);
516
- // 3a. Auto-commit any dirty state in the project root. Without this, the
517
- // squash merge can fail with "Your local changes would be overwritten" (#1127).
518
- autoCommitDirtyState(originalBasePath_);
519
- // 3b. Remove untracked .gsd/ runtime files that syncStateToProjectRoot copied.
520
- // Only clean specific runtime files — NEVER touch milestones/, decisions, or
521
- // other planning artifacts that represent user work (#1250).
522
- const runtimeFilesToClean = ["STATE.md", "completed-units.json", "auto.lock", "gsd.db"];
523
- for (const f of runtimeFilesToClean) {
524
- const p = join(originalBasePath_, ".gsd", f);
525
- try {
526
- if (existsSync(p))
527
- unlinkSync(p);
528
- }
529
- catch { /* non-fatal */ }
530
- }
531
- try {
532
- const runtimeDir = join(originalBasePath_, ".gsd", "runtime");
533
- if (existsSync(runtimeDir))
534
- rmSync(runtimeDir, { recursive: true, force: true });
535
- }
536
- catch { /* non-fatal */ }
537
707
  // 4. Resolve integration branch — prefer milestone metadata, fall back to preferences / "main"
538
708
  const prefs = loadEffectiveGSDPreferences()?.preferences?.git ?? {};
539
709
  const integrationBranch = readIntegrationBranch(originalBasePath_, milestoneId);
540
710
  const mainBranch = integrationBranch ?? prefs.main_branch ?? "main";
711
+ // Remove transient project-root state files before any branch or merge
712
+ // operation. Untracked milestone metadata can otherwise block squash merges.
713
+ clearProjectRootStateFiles(originalBasePath_, milestoneId);
541
714
  // 5. Checkout integration branch (skip if already current — avoids git error
542
715
  // when main is already checked out in the project-root worktree, #757)
543
716
  const currentBranchAtBase = nativeGetCurrentBranch(originalBasePath_);
544
717
  if (currentBranchAtBase !== mainBranch) {
545
- // Remove untracked .gsd/ state files that may conflict with the branch
546
- // being checked out. These are regenerated by doctor/rebuildState and
547
- // are not meaningful in the main working tree — the worktree had the
548
- // real state. Without this, `git checkout main` fails with
549
- // "Your local changes would be overwritten" (#827).
550
- const gsdStateFiles = ["STATE.md", "completed-units.json", "auto.lock"];
551
- for (const f of gsdStateFiles) {
552
- const p = join(gsdRoot(originalBasePath_), f);
553
- try {
554
- unlinkSync(p);
555
- }
556
- catch { /* non-fatal — file may not exist */ }
557
- }
558
718
  nativeCheckoutBranch(originalBasePath_, mainBranch);
559
719
  }
560
720
  // 6. Build rich commit message
@@ -562,7 +722,9 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
562
722
  const subject = `feat(${milestoneId}): ${milestoneTitle}`;
563
723
  let body = "";
564
724
  if (completedSlices.length > 0) {
565
- const sliceLines = completedSlices.map(s => `- ${s.id}: ${s.title}`).join("\n");
725
+ const sliceLines = completedSlices
726
+ .map((s) => `- ${s.id}: ${s.title}`)
727
+ .join("\n");
566
728
  body = `\n\nCompleted slices:\n${sliceLines}\n\nBranch: ${milestoneBranch}`;
567
729
  }
568
730
  const commitMessage = subject + body;
@@ -575,11 +737,11 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
575
737
  : nativeConflictFiles(originalBasePath_);
576
738
  if (conflictedFiles.length > 0) {
577
739
  // Separate .gsd/ state file conflicts from real code conflicts.
578
- // GSD state files (STATE.md, completed-units.json, auto.lock, etc.)
740
+ // GSD state files (STATE.md, auto.lock, etc.)
579
741
  // diverge between branches during normal operation — always prefer the
580
742
  // milestone branch version since it has the latest execution state.
581
- const gsdConflicts = conflictedFiles.filter(f => f.startsWith(".gsd/"));
582
- const codeConflicts = conflictedFiles.filter(f => !f.startsWith(".gsd/"));
743
+ const gsdConflicts = conflictedFiles.filter((f) => f.startsWith(".gsd/"));
744
+ const codeConflicts = conflictedFiles.filter((f) => !f.startsWith(".gsd/"));
583
745
  // Auto-resolve .gsd/ conflicts by accepting the milestone branch version
584
746
  if (gsdConflicts.length > 0) {
585
747
  for (const gsdFile of gsdConflicts) {
@@ -646,7 +808,10 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
646
808
  }
647
809
  // 10. Remove worktree directory first (must happen before branch deletion)
648
810
  try {
649
- removeWorktree(originalBasePath_, milestoneId, { branch: null, deleteBranch: false });
811
+ removeWorktree(originalBasePath_, milestoneId, {
812
+ branch: null,
813
+ deleteBranch: false,
814
+ });
650
815
  }
651
816
  catch {
652
817
  // Best-effort -- worktree dir may already be gone