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
@@ -261,71 +261,6 @@ test("verification-gate: each check has durationMs", () => {
261
261
  }
262
262
  });
263
263
 
264
- // ─── Infra Error Tagging Tests ───────────────────────────────────────────────
265
-
266
- test("verification-gate: spawnSync ETIMEDOUT → infraError: true on the check", () => {
267
- const tmp = makeTempDir("vg-etimedout");
268
- try {
269
- // Use a short timeout against a long sleep to guarantee ETIMEDOUT
270
- const result = runVerificationGate({
271
- basePath: tmp,
272
- unitId: "T01",
273
- cwd: tmp,
274
- preferenceCommands: ["sleep 60"],
275
- commandTimeoutMs: 200,
276
- });
277
- assert.equal(result.passed, false);
278
- assert.equal(result.checks.length, 1);
279
- assert.ok(result.checks[0].exitCode !== 0, "should have non-zero exit code");
280
- assert.equal(result.checks[0].infraError, true, "ETIMEDOUT should be tagged as infraError");
281
- } finally {
282
- rmSync(tmp, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
283
- }
284
- });
285
-
286
- test("verification-gate: real command failure does NOT have infraError", () => {
287
- const tmp = makeTempDir("vg-real-fail");
288
- try {
289
- const result = runVerificationGate({
290
- basePath: tmp,
291
- unitId: "T01",
292
- cwd: tmp,
293
- // Cross-platform: node with --eval flag and no shell-sensitive characters
294
- preferenceCommands: ["node --eval \"process.exitCode=1\""],
295
- });
296
- assert.equal(result.passed, false);
297
- assert.equal(result.checks.length, 1);
298
- assert.equal(result.checks[0].exitCode, 1);
299
- assert.equal(result.checks[0].infraError, undefined, "real failure should not be tagged as infraError");
300
- } finally {
301
- rmSync(tmp, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
302
- }
303
- });
304
-
305
- test("verification-gate: mixed infra + real failure — only infra check is tagged", () => {
306
- const tmp = makeTempDir("vg-mixed-infra");
307
- try {
308
- // Use a timeout that kills "sleep 60" but lets "node --eval" complete (~80ms).
309
- // The gate applies the same timeout to each command sequentially.
310
- const result = runVerificationGate({
311
- basePath: tmp,
312
- unitId: "T01",
313
- cwd: tmp,
314
- preferenceCommands: ["sleep 60", "node --eval \"process.exitCode=2\""],
315
- commandTimeoutMs: 500,
316
- });
317
- assert.equal(result.passed, false);
318
- assert.equal(result.checks.length, 2);
319
- // First check: ETIMEDOUT → infraError
320
- assert.equal(result.checks[0].infraError, true, "timed-out command should be infraError");
321
- // Second check: real exit 2 → no infraError
322
- assert.equal(result.checks[1].exitCode, 2);
323
- assert.equal(result.checks[1].infraError, undefined, "real failure should not be infraError");
324
- } finally {
325
- rmSync(tmp, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
326
- }
327
- });
328
-
329
264
  // ─── Preference Validation Tests ─────────────────────────────────────────────
330
265
 
331
266
  test("verification-gate: validatePreferences accepts valid verification keys", () => {
@@ -646,7 +581,7 @@ test("formatFailureContext: formats a single failure with command, exit code, st
646
581
  const result: import("../types.ts").VerificationResult = {
647
582
  passed: false,
648
583
  checks: [
649
- { command: "npm run lint", exitCode: 1, stdout: "", stderr: "error: unused var", durationMs: 500, blocking: true },
584
+ { command: "npm run lint", exitCode: 1, stdout: "", stderr: "error: unused var", durationMs: 500 },
650
585
  ],
651
586
  discoverySource: "preference",
652
587
  timestamp: Date.now(),
@@ -663,9 +598,9 @@ test("formatFailureContext: formats multiple failures", () => {
663
598
  const result: import("../types.ts").VerificationResult = {
664
599
  passed: false,
665
600
  checks: [
666
- { command: "npm run lint", exitCode: 1, stdout: "", stderr: "lint error", durationMs: 100, blocking: true },
667
- { command: "npm run test", exitCode: 2, stdout: "", stderr: "test failure", durationMs: 200, blocking: true },
668
- { command: "npm run typecheck", exitCode: 0, stdout: "ok", stderr: "", durationMs: 50, blocking: true },
601
+ { command: "npm run lint", exitCode: 1, stdout: "", stderr: "lint error", durationMs: 100 },
602
+ { command: "npm run test", exitCode: 2, stdout: "", stderr: "test failure", durationMs: 200 },
603
+ { command: "npm run typecheck", exitCode: 0, stdout: "ok", stderr: "", durationMs: 50 },
669
604
  ],
670
605
  discoverySource: "preference",
671
606
  timestamp: Date.now(),
@@ -684,7 +619,7 @@ test("formatFailureContext: truncates stderr longer than 2000 chars", () => {
684
619
  const result: import("../types.ts").VerificationResult = {
685
620
  passed: false,
686
621
  checks: [
687
- { command: "big-err", exitCode: 1, stdout: "", stderr: longStderr, durationMs: 100, blocking: true },
622
+ { command: "big-err", exitCode: 1, stdout: "", stderr: longStderr, durationMs: 100 },
688
623
  ],
689
624
  discoverySource: "preference",
690
625
  timestamp: Date.now(),
@@ -699,8 +634,8 @@ test("formatFailureContext: returns empty string when all checks pass", () => {
699
634
  const result: import("../types.ts").VerificationResult = {
700
635
  passed: true,
701
636
  checks: [
702
- { command: "npm run lint", exitCode: 0, stdout: "ok", stderr: "", durationMs: 100, blocking: true },
703
- { command: "npm run test", exitCode: 0, stdout: "ok", stderr: "", durationMs: 200, blocking: true },
637
+ { command: "npm run lint", exitCode: 0, stdout: "ok", stderr: "", durationMs: 100 },
638
+ { command: "npm run test", exitCode: 0, stdout: "ok", stderr: "", durationMs: 200 },
704
639
  ],
705
640
  discoverySource: "preference",
706
641
  timestamp: Date.now(),
@@ -728,7 +663,6 @@ test("formatFailureContext: caps total output at 10,000 chars", () => {
728
663
  stdout: "",
729
664
  stderr: "e".repeat(1000), // 1000 chars each, 20 * ~1050 (with formatting) > 10,000
730
665
  durationMs: 100,
731
- blocking: true,
732
666
  });
733
667
  }
734
668
  const result: import("../types.ts").VerificationResult = {
@@ -1143,131 +1077,3 @@ test("dependency-audit: subdirectory package.json does not trigger audit", () =>
1143
1077
  assert.equal(npmAuditCalled, false, "subdirectory dependency files should not trigger audit");
1144
1078
  assert.deepStrictEqual(result, []);
1145
1079
  });
1146
-
1147
- // ─── Non-Blocking Discovery Tests ────────────────────────────────────────────
1148
-
1149
- test("non-blocking: package-json discovered commands failing → result.passed is still true", () => {
1150
- const tmp = makeTempDir("vg-nb-pkg-fail");
1151
- try {
1152
- writeFileSync(
1153
- join(tmp, "package.json"),
1154
- JSON.stringify({ scripts: { lint: "eslint .", test: "vitest" } }),
1155
- );
1156
- // These commands will fail because eslint/vitest don't exist in the temp dir
1157
- const result = runVerificationGate({
1158
- basePath: tmp,
1159
- unitId: "T01",
1160
- cwd: tmp,
1161
- // No preference commands — discovery falls through to package.json
1162
- });
1163
- assert.equal(result.discoverySource, "package-json");
1164
- assert.ok(result.checks.length > 0, "should have discovered package.json checks");
1165
- assert.equal(result.passed, true, "package-json failures should not block the gate");
1166
- for (const check of result.checks) {
1167
- assert.equal(check.blocking, false, "package-json checks should be non-blocking");
1168
- }
1169
- } finally {
1170
- rmSync(tmp, { recursive: true, force: true });
1171
- }
1172
- });
1173
-
1174
- test("non-blocking: preference commands failing → result.passed is false", () => {
1175
- const tmp = makeTempDir("vg-nb-pref-fail");
1176
- try {
1177
- const result = runVerificationGate({
1178
- basePath: tmp,
1179
- unitId: "T01",
1180
- cwd: tmp,
1181
- preferenceCommands: ["sh -c 'exit 1'"],
1182
- });
1183
- assert.equal(result.discoverySource, "preference");
1184
- assert.equal(result.passed, false, "preference failures should block the gate");
1185
- assert.equal(result.checks[0].blocking, true, "preference checks should be blocking");
1186
- } finally {
1187
- rmSync(tmp, { recursive: true, force: true });
1188
- }
1189
- });
1190
-
1191
- test("non-blocking: task-plan commands failing → result.passed is false", () => {
1192
- const tmp = makeTempDir("vg-nb-tp-fail");
1193
- try {
1194
- const result = runVerificationGate({
1195
- basePath: tmp,
1196
- unitId: "T01",
1197
- cwd: tmp,
1198
- taskPlanVerify: "sh -c 'exit 1'",
1199
- });
1200
- assert.equal(result.discoverySource, "task-plan");
1201
- assert.equal(result.passed, false, "task-plan failures should block the gate");
1202
- assert.equal(result.checks[0].blocking, true, "task-plan checks should be blocking");
1203
- } finally {
1204
- rmSync(tmp, { recursive: true, force: true });
1205
- }
1206
- });
1207
-
1208
- test("non-blocking: blocking field is set correctly based on discovery source", () => {
1209
- const tmp = makeTempDir("vg-nb-field");
1210
- try {
1211
- // preference → blocking
1212
- const prefResult = runVerificationGate({
1213
- basePath: tmp,
1214
- unitId: "T01",
1215
- cwd: tmp,
1216
- preferenceCommands: ["echo ok"],
1217
- });
1218
- assert.equal(prefResult.checks[0].blocking, true);
1219
-
1220
- // task-plan → blocking
1221
- const tpResult = runVerificationGate({
1222
- basePath: tmp,
1223
- unitId: "T01",
1224
- cwd: tmp,
1225
- taskPlanVerify: "echo ok",
1226
- });
1227
- assert.equal(tpResult.checks[0].blocking, true);
1228
-
1229
- // package-json → non-blocking
1230
- writeFileSync(
1231
- join(tmp, "package.json"),
1232
- JSON.stringify({ scripts: { test: "echo ok" } }),
1233
- );
1234
- const pkgResult = runVerificationGate({
1235
- basePath: tmp,
1236
- unitId: "T01",
1237
- cwd: tmp,
1238
- });
1239
- assert.equal(pkgResult.checks[0].blocking, false);
1240
- } finally {
1241
- rmSync(tmp, { recursive: true, force: true });
1242
- }
1243
- });
1244
-
1245
- test("non-blocking: formatFailureContext only includes blocking failures", () => {
1246
- const result: import("../types.ts").VerificationResult = {
1247
- passed: true,
1248
- checks: [
1249
- { command: "npm run lint", exitCode: 1, stdout: "", stderr: "lint warning", durationMs: 100, blocking: false },
1250
- { command: "npm run test", exitCode: 1, stdout: "", stderr: "test error", durationMs: 200, blocking: true },
1251
- { command: "npm run typecheck", exitCode: 1, stdout: "", stderr: "type error", durationMs: 50, blocking: false },
1252
- ],
1253
- discoverySource: "preference",
1254
- timestamp: Date.now(),
1255
- };
1256
- const output = formatFailureContext(result);
1257
- assert.ok(output.includes("`npm run test`"), "should include blocking failure");
1258
- assert.ok(!output.includes("npm run lint"), "should not include non-blocking failure");
1259
- assert.ok(!output.includes("npm run typecheck"), "should not include non-blocking failure");
1260
- });
1261
-
1262
- test("non-blocking: formatFailureContext returns empty when only non-blocking failures exist", () => {
1263
- const result: import("../types.ts").VerificationResult = {
1264
- passed: true,
1265
- checks: [
1266
- { command: "npm run lint", exitCode: 1, stdout: "", stderr: "lint warning", durationMs: 100, blocking: false },
1267
- { command: "npm run test", exitCode: 1, stdout: "", stderr: "test warning", durationMs: 200, blocking: false },
1268
- ],
1269
- discoverySource: "package-json",
1270
- timestamp: Date.now(),
1271
- };
1272
- assert.equal(formatFailureContext(result), "", "should return empty when only non-blocking failures");
1273
- });
@@ -0,0 +1,205 @@
1
+ /**
2
+ * worktree-db-integration.test.ts
3
+ *
4
+ * Integration tests for the worktree DB copy and reconcile hooks.
5
+ * Uses real temp git repos and real SQLite databases.
6
+ *
7
+ * Test cases:
8
+ * 1. Copy: createAutoWorktree seeds .gsd/gsd.db into the worktree when main has one
9
+ * 2. Copy-skip: createAutoWorktree silently skips when main has no gsd.db
10
+ * 3. Reconcile: reconcileWorktreeDb merges worktree rows into main DB
11
+ * 4. Reconcile-skip: reconcileWorktreeDb is non-fatal when both paths are nonexistent
12
+ * 5. Failure path: reconcileWorktreeDb emits to stderr on open failure (observable)
13
+ */
14
+
15
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, realpathSync } from "node:fs";
16
+ import { join } from "node:path";
17
+ import { tmpdir } from "node:os";
18
+ import { execSync } from "node:child_process";
19
+
20
+ import { createAutoWorktree } from "../auto-worktree.ts";
21
+ import { worktreePath } from "../worktree-manager.ts";
22
+ import {
23
+ copyWorktreeDb,
24
+ reconcileWorktreeDb,
25
+ openDatabase,
26
+ closeDatabase,
27
+ upsertDecision,
28
+ getActiveDecisions,
29
+ isDbAvailable,
30
+ } from "../gsd-db.ts";
31
+
32
+ import { createTestContext } from "./test-helpers.ts";
33
+
34
+ const { assertEq, assertTrue, report } = createTestContext();
35
+
36
+ function run(command: string, cwd: string): string {
37
+ return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
38
+ }
39
+
40
+ function createTempRepo(): string {
41
+ const dir = realpathSync(mkdtempSync(join(tmpdir(), "wt-db-int-test-")));
42
+ run("git init", dir);
43
+ run("git config user.email test@test.com", dir);
44
+ run("git config user.name Test", dir);
45
+ writeFileSync(join(dir, "README.md"), "# test\n");
46
+ run("git add .", dir);
47
+ run("git commit -m init", dir);
48
+ run("git branch -M main", dir);
49
+ return dir;
50
+ }
51
+
52
+ async function main(): Promise<void> {
53
+ const savedCwd = process.cwd();
54
+ const tempDirs: string[] = [];
55
+
56
+ function makeTempDir(): string {
57
+ const dir = realpathSync(mkdtempSync(join(tmpdir(), "wt-db-int-")));
58
+ tempDirs.push(dir);
59
+ return dir;
60
+ }
61
+
62
+ try {
63
+
64
+ // ─── Test 1: copy on worktree creation ───────────────────────────
65
+ console.log("\n=== Test 1: copy on worktree creation ===");
66
+ {
67
+ const tempDir = createTempRepo();
68
+ tempDirs.push(tempDir);
69
+
70
+ // Seed a gsd.db in the main repo
71
+ const gsdDir = join(tempDir, ".gsd");
72
+ mkdirSync(gsdDir, { recursive: true });
73
+ const mainDbPath = join(gsdDir, "gsd.db");
74
+ openDatabase(mainDbPath);
75
+ closeDatabase();
76
+
77
+ // Commit so createAutoWorktree can copy planning artifacts
78
+ run("git add .", tempDir);
79
+ run('git commit -m "add gsd dir"', tempDir);
80
+
81
+ // createAutoWorktree should copy the DB into the worktree
82
+ const wtPath = createAutoWorktree(tempDir, "M004");
83
+
84
+ const worktreeDbPath = join(worktreePath(tempDir, "M004"), ".gsd", "gsd.db");
85
+ assertTrue(
86
+ existsSync(worktreeDbPath),
87
+ "gsd.db exists in worktree .gsd after createAutoWorktree",
88
+ );
89
+
90
+ // Restore cwd for next test
91
+ process.chdir(savedCwd);
92
+ }
93
+
94
+ // ─── Test 2: copy skip when no source DB ─────────────────────────
95
+ console.log("\n=== Test 2: copy skip when no source DB ===");
96
+ {
97
+ const tempDir = createTempRepo();
98
+ tempDirs.push(tempDir);
99
+
100
+ // No gsd.db — just a bare repo
101
+ let threw = false;
102
+ let wtPath: string | null = null;
103
+ try {
104
+ wtPath = createAutoWorktree(tempDir, "M004");
105
+ } catch (err) {
106
+ threw = true;
107
+ console.error(" Unexpected throw:", err);
108
+ }
109
+
110
+ assertTrue(!threw, "createAutoWorktree does not throw when no source DB");
111
+
112
+ const worktreeDbPath = join(worktreePath(tempDir, "M004"), ".gsd", "gsd.db");
113
+ assertTrue(
114
+ !existsSync(worktreeDbPath),
115
+ "gsd.db is absent in worktree when source had none",
116
+ );
117
+
118
+ process.chdir(savedCwd);
119
+ }
120
+
121
+ // ─── Test 3: reconcile inserts worktree rows into main ───────────
122
+ console.log("\n=== Test 3: reconcile merges worktree rows into main ===");
123
+ {
124
+ const mainDbPath = join(makeTempDir(), "main.db");
125
+ const worktreeDbPath = join(makeTempDir(), "wt.db");
126
+
127
+ // Seed main DB (empty schema)
128
+ openDatabase(mainDbPath);
129
+ closeDatabase();
130
+
131
+ // Seed worktree DB with one decision
132
+ openDatabase(worktreeDbPath);
133
+ upsertDecision({
134
+ id: "D-WT-001",
135
+ when_context: "integration test",
136
+ scope: "test",
137
+ decision: "use reconcile",
138
+ choice: "reconcile on merge",
139
+ rationale: "test coverage",
140
+ revisable: "no",
141
+ superseded_by: null,
142
+ });
143
+ closeDatabase();
144
+
145
+ // Reconcile worktree → main
146
+ const result = reconcileWorktreeDb(mainDbPath, worktreeDbPath);
147
+ assertTrue(result.decisions >= 1, "reconcile reports at least 1 decision merged");
148
+
149
+ // Open main DB and verify the row is present
150
+ openDatabase(mainDbPath);
151
+ const decisions = getActiveDecisions();
152
+ closeDatabase();
153
+
154
+ const found = decisions.some((d) => d.id === "D-WT-001");
155
+ assertTrue(found, "worktree decision D-WT-001 present in main DB after reconcile");
156
+ }
157
+
158
+ // ─── Test 4: reconcile non-fatal when both paths nonexistent ─────
159
+ console.log("\n=== Test 4: reconcile non-fatal on nonexistent paths ===");
160
+ {
161
+ let threw = false;
162
+ try {
163
+ reconcileWorktreeDb("/nonexistent/path/gsd.db", "/also/nonexistent/gsd.db");
164
+ } catch {
165
+ threw = true;
166
+ }
167
+ assertTrue(!threw, "reconcileWorktreeDb does not throw when worktree DB is absent");
168
+ }
169
+
170
+ // ─── Test 5: failure path observable via stderr (diagnostic) ─────
171
+ // reconcileWorktreeDb emits to stderr on reconciliation failures.
172
+ // We can't easily intercept stderr in this test harness, but we verify
173
+ // that the function returns the zero-result shape (not undefined/throws)
174
+ // when the worktree DB is missing — confirming the failure path is non-fatal
175
+ // and returns a structured result.
176
+ console.log("\n=== Test 5: reconcile returns zero-shape when worktree DB absent ===");
177
+ {
178
+ const mainDbPath = join(makeTempDir(), "main2.db");
179
+ openDatabase(mainDbPath);
180
+ closeDatabase();
181
+
182
+ const result = reconcileWorktreeDb(mainDbPath, "/definitely/does/not/exist.db");
183
+ assertEq(result.decisions, 0, "decisions is 0 when worktree DB absent");
184
+ assertEq(result.requirements, 0, "requirements is 0 when worktree DB absent");
185
+ assertEq(result.artifacts, 0, "artifacts is 0 when worktree DB absent");
186
+ assertEq(result.conflicts.length, 0, "conflicts is empty when worktree DB absent");
187
+ }
188
+
189
+ } finally {
190
+ // Always restore cwd
191
+ process.chdir(savedCwd);
192
+ // Ensure DB is closed
193
+ if (isDbAvailable()) closeDatabase();
194
+ // Remove all temp dirs
195
+ for (const dir of tempDirs) {
196
+ if (existsSync(dir)) {
197
+ rmSync(dir, { recursive: true, force: true });
198
+ }
199
+ }
200
+ }
201
+
202
+ report();
203
+ }
204
+
205
+ main();