@opengsd/gsd-pi 1.4.0-dev.c18009cd → 1.5.0-dev.4fb2d460

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 (334) hide show
  1. package/README.md +10 -10
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/ask-user-questions.js +1 -1
  4. package/dist/resources/extensions/gsd/auto/closeout.js +97 -5
  5. package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -3
  6. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +6 -3
  7. package/dist/resources/extensions/gsd/auto/unit-phase.js +5 -9
  8. package/dist/resources/extensions/gsd/auto-artifact-paths.js +12 -3
  9. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -7
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +16 -2
  11. package/dist/resources/extensions/gsd/auto-recovery.js +50 -6
  12. package/dist/resources/extensions/gsd/auto-start.js +4 -3
  13. package/dist/resources/extensions/gsd/auto-worktree-branch-lifecycle.js +189 -0
  14. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +133 -0
  15. package/dist/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.js +35 -0
  16. package/dist/resources/extensions/gsd/auto-worktree-creation.js +130 -0
  17. package/dist/resources/extensions/gsd/auto-worktree-entry.js +118 -0
  18. package/dist/resources/extensions/gsd/auto-worktree-merge-already-merged.js +98 -0
  19. package/dist/resources/extensions/gsd/auto-worktree-merge-branch-head.js +52 -0
  20. package/dist/resources/extensions/gsd/auto-worktree-merge-cleanup.js +87 -0
  21. package/dist/resources/extensions/gsd/auto-worktree-merge-code-changes.js +46 -0
  22. package/dist/resources/extensions/gsd/auto-worktree-merge-db-ready.js +68 -0
  23. package/dist/resources/extensions/gsd/auto-worktree-merge-integration-branch.js +51 -0
  24. package/dist/resources/extensions/gsd/auto-worktree-merge-message.js +106 -0
  25. package/dist/resources/extensions/gsd/auto-worktree-merge-pre-teardown.js +64 -0
  26. package/dist/resources/extensions/gsd/auto-worktree-merge-stash.js +168 -0
  27. package/dist/resources/extensions/gsd/auto-worktree-merge.js +302 -0
  28. package/dist/resources/extensions/gsd/auto-worktree-milestone-shelter.js +119 -0
  29. package/dist/resources/extensions/gsd/auto-worktree-path-resolution.js +5 -0
  30. package/dist/resources/extensions/gsd/auto-worktree-path-utils.js +5 -0
  31. package/dist/resources/extensions/gsd/auto-worktree-resource-version.js +41 -0
  32. package/dist/resources/extensions/gsd/auto-worktree-runtime-cleanup.js +99 -0
  33. package/dist/resources/extensions/gsd/auto-worktree-session-registry.js +57 -0
  34. package/dist/resources/extensions/gsd/auto-worktree-sync.js +249 -0
  35. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +120 -0
  36. package/dist/resources/extensions/gsd/auto-worktree.js +20 -2073
  37. package/dist/resources/extensions/gsd/auto.js +9 -3
  38. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -1
  39. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +20 -2
  40. package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
  41. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +185 -27
  42. package/dist/resources/extensions/gsd/codebase-generator.js +7 -1
  43. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  44. package/dist/resources/extensions/gsd/commands-workflow-templates.js +3 -3
  45. package/dist/resources/extensions/gsd/db/queries.js +9 -9
  46. package/dist/resources/extensions/gsd/db/writers/cascades.js +20 -2
  47. package/dist/resources/extensions/gsd/doctor-engine-checks.js +93 -11
  48. package/dist/resources/extensions/gsd/flat-phase-migration.js +32 -3
  49. package/dist/resources/extensions/gsd/forensics.js +1 -1
  50. package/dist/resources/extensions/gsd/git-conflict-resolve.js +2 -2
  51. package/dist/resources/extensions/gsd/git-service.js +45 -0
  52. package/dist/resources/extensions/gsd/gsd-db.js +23 -11
  53. package/dist/resources/extensions/gsd/guided-flow.js +22 -17
  54. package/dist/resources/extensions/gsd/markdown-renderer.js +15 -3
  55. package/dist/resources/extensions/gsd/md-importer.js +89 -23
  56. package/dist/resources/extensions/gsd/migration-auto-check.js +30 -3
  57. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +11 -0
  58. package/dist/resources/extensions/gsd/milestone-settlement.js +1 -1
  59. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  60. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -1
  61. package/dist/resources/extensions/gsd/paths.js +17 -3
  62. package/dist/resources/extensions/gsd/preferences-skills.js +10 -16
  63. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  64. package/dist/resources/extensions/gsd/preferences-validation.js +82 -0
  65. package/dist/resources/extensions/gsd/preferences.js +20 -0
  66. package/dist/resources/extensions/gsd/prompts/system.md +6 -6
  67. package/dist/resources/extensions/gsd/quick.js +12 -3
  68. package/dist/resources/extensions/gsd/skill-discovery.js +36 -23
  69. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +2 -1
  70. package/dist/resources/extensions/gsd/state/derive/from-db.js +88 -153
  71. package/dist/resources/extensions/gsd/tool-contract.js +14 -0
  72. package/dist/resources/extensions/gsd/tools/reopen-slice.js +5 -0
  73. package/dist/resources/extensions/gsd/tools/reopen-task.js +13 -5
  74. package/dist/resources/extensions/gsd/unit-registry.js +12 -2
  75. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +1 -1
  76. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -1
  77. package/dist/resources/extensions/gsd/workspace-git-preflight.js +2 -2
  78. package/dist/resources/extensions/gsd/worktree-command.js +1 -1
  79. package/dist/resources/extensions/gsd/worktree-lifecycle.js +14 -9
  80. package/dist/resources/extensions/gsd/worktree-reentry.js +2 -1
  81. package/dist/resources/extensions/shared/interview-ui.js +62 -9
  82. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  85. package/dist/web/standalone/.next/build-manifest.json +2 -2
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  88. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  96. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/index.html +1 -1
  104. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  111. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  113. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  114. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  115. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  116. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  117. package/integrations/hermes/open_gsd_hermes/gsd_client.py +24 -35
  118. package/integrations/hermes/tests/test_gsd_client_timeout.py +4 -4
  119. package/package.json +6 -6
  120. package/packages/cloud-mcp-gateway/package.json +2 -2
  121. package/packages/contracts/package.json +1 -1
  122. package/packages/daemon/package.json +4 -4
  123. package/packages/gsd-agent-core/dist/export-html/template.js +53 -4
  124. package/packages/gsd-agent-core/package.json +5 -5
  125. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  126. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +3 -2
  127. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  128. package/packages/gsd-agent-modes/package.json +7 -7
  129. package/packages/mcp-server/package.json +4 -4
  130. package/packages/native/package.json +1 -1
  131. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  132. package/packages/pi-agent-core/dist/agent-loop.js +14 -9
  133. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  134. package/packages/pi-agent-core/package.json +1 -1
  135. package/packages/pi-ai/dist/index.d.ts +1 -0
  136. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  137. package/packages/pi-ai/dist/index.js +1 -0
  138. package/packages/pi-ai/dist/index.js.map +1 -1
  139. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  140. package/packages/pi-ai/dist/providers/transform-messages.js +7 -3
  141. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  142. package/packages/pi-ai/dist/tool-result-content.d.ts +3 -0
  143. package/packages/pi-ai/dist/tool-result-content.d.ts.map +1 -0
  144. package/packages/pi-ai/dist/tool-result-content.js +62 -0
  145. package/packages/pi-ai/dist/tool-result-content.js.map +1 -0
  146. package/packages/pi-ai/dist/types.d.ts +8 -20
  147. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  148. package/packages/pi-ai/dist/types.js.map +1 -1
  149. package/packages/pi-ai/package.json +1 -1
  150. package/packages/pi-coding-agent/dist/core/package-manager.d.ts +9 -0
  151. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  152. package/packages/pi-coding-agent/dist/core/package-manager.js +74 -53
  153. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  154. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +6 -0
  155. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/resource-loader.js +30 -2
  157. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/skill-directories.d.ts +66 -0
  159. package/packages/pi-coding-agent/dist/core/skill-directories.d.ts.map +1 -0
  160. package/packages/pi-coding-agent/dist/core/skill-directories.js +138 -0
  161. package/packages/pi-coding-agent/dist/core/skill-directories.js.map +1 -0
  162. package/packages/pi-coding-agent/dist/core/skills.d.ts +4 -1
  163. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  164. package/packages/pi-coding-agent/dist/core/skills.js +4 -1
  165. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  167. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  168. package/packages/pi-coding-agent/dist/index.js +1 -0
  169. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  170. package/packages/pi-coding-agent/package.json +7 -7
  171. package/packages/pi-tui/package.json +2 -2
  172. package/packages/rpc-client/package.json +2 -2
  173. package/pkg/dist/core/export-html/template.js +53 -4
  174. package/pkg/package.json +1 -1
  175. package/src/resources/extensions/ask-user-questions.ts +1 -1
  176. package/src/resources/extensions/gsd/auto/closeout.ts +114 -7
  177. package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -3
  178. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +6 -3
  179. package/src/resources/extensions/gsd/auto/unit-phase.ts +5 -9
  180. package/src/resources/extensions/gsd/auto-artifact-paths.ts +12 -3
  181. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +13 -7
  182. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
  183. package/src/resources/extensions/gsd/auto-recovery.ts +50 -6
  184. package/src/resources/extensions/gsd/auto-start.ts +5 -3
  185. package/src/resources/extensions/gsd/auto-worktree-branch-lifecycle.ts +237 -0
  186. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +166 -0
  187. package/src/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.ts +37 -0
  188. package/src/resources/extensions/gsd/auto-worktree-creation.ts +171 -0
  189. package/src/resources/extensions/gsd/auto-worktree-entry.ts +154 -0
  190. package/src/resources/extensions/gsd/auto-worktree-merge-already-merged.ts +161 -0
  191. package/src/resources/extensions/gsd/auto-worktree-merge-branch-head.ts +83 -0
  192. package/src/resources/extensions/gsd/auto-worktree-merge-cleanup.ts +132 -0
  193. package/src/resources/extensions/gsd/auto-worktree-merge-code-changes.ts +71 -0
  194. package/src/resources/extensions/gsd/auto-worktree-merge-db-ready.ts +112 -0
  195. package/src/resources/extensions/gsd/auto-worktree-merge-integration-branch.ts +99 -0
  196. package/src/resources/extensions/gsd/auto-worktree-merge-message.ts +166 -0
  197. package/src/resources/extensions/gsd/auto-worktree-merge-pre-teardown.ts +93 -0
  198. package/src/resources/extensions/gsd/auto-worktree-merge-stash.ts +213 -0
  199. package/src/resources/extensions/gsd/auto-worktree-merge.ts +391 -0
  200. package/src/resources/extensions/gsd/auto-worktree-milestone-shelter.ts +159 -0
  201. package/src/resources/extensions/gsd/auto-worktree-path-resolution.ts +6 -0
  202. package/src/resources/extensions/gsd/auto-worktree-path-utils.ts +10 -0
  203. package/src/resources/extensions/gsd/auto-worktree-resource-version.ts +44 -0
  204. package/src/resources/extensions/gsd/auto-worktree-runtime-cleanup.ts +119 -0
  205. package/src/resources/extensions/gsd/auto-worktree-session-registry.ts +71 -0
  206. package/src/resources/extensions/gsd/auto-worktree-sync.ts +370 -0
  207. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +161 -0
  208. package/src/resources/extensions/gsd/auto-worktree.ts +69 -2429
  209. package/src/resources/extensions/gsd/auto.ts +11 -17
  210. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -1
  211. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +20 -2
  212. package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
  213. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +218 -27
  214. package/src/resources/extensions/gsd/codebase-generator.ts +7 -1
  215. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  216. package/src/resources/extensions/gsd/commands-workflow-templates.ts +3 -3
  217. package/src/resources/extensions/gsd/db/queries.ts +9 -9
  218. package/src/resources/extensions/gsd/db/writers/cascades.ts +23 -1
  219. package/src/resources/extensions/gsd/doctor-engine-checks.ts +109 -10
  220. package/src/resources/extensions/gsd/flat-phase-migration.ts +34 -3
  221. package/src/resources/extensions/gsd/forensics.ts +1 -1
  222. package/src/resources/extensions/gsd/git-conflict-resolve.ts +2 -2
  223. package/src/resources/extensions/gsd/git-service.ts +53 -0
  224. package/src/resources/extensions/gsd/gsd-db.ts +33 -11
  225. package/src/resources/extensions/gsd/guided-flow.ts +26 -18
  226. package/src/resources/extensions/gsd/markdown-renderer.ts +15 -3
  227. package/src/resources/extensions/gsd/md-importer.ts +93 -22
  228. package/src/resources/extensions/gsd/migration-auto-check.ts +32 -3
  229. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +15 -0
  230. package/src/resources/extensions/gsd/milestone-settlement.ts +1 -1
  231. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  232. package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -1
  233. package/src/resources/extensions/gsd/paths.ts +21 -3
  234. package/src/resources/extensions/gsd/preferences-skills.ts +10 -16
  235. package/src/resources/extensions/gsd/preferences-types.ts +30 -0
  236. package/src/resources/extensions/gsd/preferences-validation.ts +69 -0
  237. package/src/resources/extensions/gsd/preferences.ts +20 -0
  238. package/src/resources/extensions/gsd/prompts/system.md +6 -6
  239. package/src/resources/extensions/gsd/quick.ts +11 -3
  240. package/src/resources/extensions/gsd/skill-discovery.ts +47 -23
  241. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -1
  242. package/src/resources/extensions/gsd/state/derive/from-db.ts +201 -157
  243. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +169 -1
  244. package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +2 -1
  245. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +57 -0
  246. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +1 -1
  247. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +2 -1
  248. package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +1 -1
  249. package/src/resources/extensions/gsd/tests/auto-worktree-merge-already-merged.test.ts +177 -0
  250. package/src/resources/extensions/gsd/tests/auto-worktree-merge-branch-head.test.ts +118 -0
  251. package/src/resources/extensions/gsd/tests/auto-worktree-merge-cleanup.test.ts +115 -0
  252. package/src/resources/extensions/gsd/tests/auto-worktree-merge-code-changes.test.ts +76 -0
  253. package/src/resources/extensions/gsd/tests/auto-worktree-merge-db-ready.test.ts +140 -0
  254. package/src/resources/extensions/gsd/tests/auto-worktree-merge-integration-branch.test.ts +123 -0
  255. package/src/resources/extensions/gsd/tests/auto-worktree-merge-message.test.ts +114 -0
  256. package/src/resources/extensions/gsd/tests/auto-worktree-merge-pre-teardown.test.ts +84 -0
  257. package/src/resources/extensions/gsd/tests/auto-worktree-merge-stash.test.ts +70 -0
  258. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-shelter.test.ts +52 -0
  259. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +6 -6
  260. package/src/resources/extensions/gsd/tests/auto-worktree-resource-version.test.ts +59 -0
  261. package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +3 -1
  262. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  263. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +1 -1
  264. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -0
  265. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +174 -0
  266. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +1 -1
  267. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +71 -1
  268. package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +25 -1
  269. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +40 -0
  270. package/src/resources/extensions/gsd/tests/import-completion-lost-update.test.ts +196 -0
  271. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +4 -6
  272. package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +2 -1
  273. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +3 -3
  274. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +7 -8
  275. package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +2 -5
  276. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +76 -0
  277. package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +1 -1
  278. package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +1 -1
  279. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +2 -1
  280. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +5 -7
  281. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +2 -4
  282. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -15
  283. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +1 -1
  284. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +1 -1
  285. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +1 -1
  286. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +91 -0
  287. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +439 -0
  288. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +24 -0
  289. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +1 -1
  290. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -3
  291. package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +1 -1
  292. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +1 -4
  293. package/src/resources/extensions/gsd/tests/preferences.test.ts +19 -0
  294. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +5 -0
  295. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +52 -0
  296. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
  297. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +46 -0
  298. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -5
  299. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +2 -1
  300. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +2 -1
  301. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +1 -1
  302. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +1 -1
  303. package/src/resources/extensions/gsd/tests/system-flat-phase-layout.test.ts +33 -0
  304. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +4 -4
  305. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +2 -1
  306. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +4 -4
  307. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +196 -0
  308. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +1 -1
  309. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +26 -1
  310. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -1
  311. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +1 -1
  312. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +1 -3
  313. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +1 -1
  314. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +1 -1
  315. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +1 -1
  316. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +1 -1
  317. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +2 -1
  318. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +5 -2
  319. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +1 -1
  320. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +1 -1
  321. package/src/resources/extensions/gsd/tool-contract.ts +29 -0
  322. package/src/resources/extensions/gsd/tools/reopen-slice.ts +5 -0
  323. package/src/resources/extensions/gsd/tools/reopen-task.ts +13 -5
  324. package/src/resources/extensions/gsd/unit-registry.ts +16 -2
  325. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +1 -1
  326. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -1
  327. package/src/resources/extensions/gsd/workspace-git-preflight.ts +2 -2
  328. package/src/resources/extensions/gsd/worktree-command.ts +1 -1
  329. package/src/resources/extensions/gsd/worktree-lifecycle.ts +19 -15
  330. package/src/resources/extensions/gsd/worktree-reentry.ts +2 -1
  331. package/src/resources/extensions/shared/interview-ui.ts +58 -11
  332. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +32 -0
  333. /package/dist/web/standalone/.next/static/{L2UMqXELiDH3oz-7yguXp → gXoWec4UNqcR0tkuHwYCr}/_buildManifest.js +0 -0
  334. /package/dist/web/standalone/.next/static/{L2UMqXELiDH3oz-7yguXp → gXoWec4UNqcR0tkuHwYCr}/_ssgManifest.js +0 -0
@@ -0,0 +1,119 @@
1
+ // gsd-pi — Auto-worktree runtime cleanup module.
2
+ //
3
+ // Owns stale worktree cwd escape and runtime unit cleanup during auto startup.
4
+
5
+ import { existsSync, readdirSync, unlinkSync } from "node:fs";
6
+ import { join } from "node:path";
7
+
8
+ import { gsdHome } from "./gsd-home.js";
9
+ import { MILESTONE_ID_RE } from "./milestone-ids.js";
10
+ import {
11
+ normalizeWorktreePathForCompare,
12
+ projectRootFromWorktreePath,
13
+ } from "./worktree-root.js";
14
+ import { logWarning } from "./workflow-logger.js";
15
+
16
+ const LEGACY_DEEP_SETUP_RUNTIME_UNIT_FILES = new Set([
17
+ "workflow-preferences-WORKFLOW-PREFS.json",
18
+ "discuss-project-PROJECT.json",
19
+ "discuss-requirements-REQUIREMENTS.json",
20
+ "research-decision-RESEARCH-DECISION.json",
21
+ "research-project-RESEARCH-PROJECT.json",
22
+ ]);
23
+
24
+ /**
25
+ * Detect and escape a stale worktree cwd (#608).
26
+ *
27
+ * After milestone completion + merge, the worktree directory is removed but
28
+ * the process cwd may still point inside `.gsd/worktrees/<MID>/`.
29
+ * When a new session starts, `process.cwd()` is passed as `base` to startAuto
30
+ * and all subsequent writes land in the wrong directory. This function detects
31
+ * that scenario and chdir back to the project root.
32
+ *
33
+ * Returns the corrected base path.
34
+ */
35
+ export function escapeStaleWorktree(base: string): string {
36
+ const projectRoot = projectRootFromWorktreePath(base);
37
+ if (projectRoot === null) return base;
38
+
39
+ // Guard: If the candidate project root's .gsd IS the user-level ~/.gsd,
40
+ // the string-slice heuristic matched the wrong /.gsd/ boundary. This happens
41
+ // when .gsd is a symlink into ~/.gsd/projects/<hash> and process.cwd()
42
+ // resolved through the symlink. Returning ~ would be catastrophic (#1676).
43
+ const candidateGsd = normalizeWorktreePathForCompare(join(projectRoot, ".gsd"));
44
+ const gsdHomeNorm = normalizeWorktreePathForCompare(gsdHome());
45
+ if (candidateGsd === gsdHomeNorm || candidateGsd.startsWith(gsdHomeNorm + "/")) {
46
+ // Don't chdir to home — return base unchanged.
47
+ // resolveProjectRoot() in worktree.ts has the full git-file-based recovery
48
+ // and will be called by the caller (startAuto → projectRoot()).
49
+ return base;
50
+ }
51
+
52
+ try {
53
+ process.chdir(projectRoot);
54
+ } catch (e) {
55
+ // If chdir fails, return the original — caller will handle errors downstream
56
+ logWarning("worktree", `escapeStaleWorktree chdir failed: ${(e as Error).message}`);
57
+ return base;
58
+ }
59
+ return projectRoot;
60
+ }
61
+
62
+ /**
63
+ * Clean stale runtime unit files for completed milestones.
64
+ *
65
+ * After restart, stale runtime/units/*.json from prior milestones can
66
+ * cause deriveState to resume the wrong milestone (#887). Removes files
67
+ * for milestones that have a SUMMARY (fully complete).
68
+ */
69
+ export function cleanStaleRuntimeUnits(
70
+ gsdRootPath: string,
71
+ hasMilestoneSummary: (mid: string) => boolean,
72
+ ): number {
73
+ const runtimeUnitsDir = join(gsdRootPath, "runtime", "units");
74
+ if (!existsSync(runtimeUnitsDir)) return 0;
75
+
76
+ let cleaned = 0;
77
+ try {
78
+ for (const file of readdirSync(runtimeUnitsDir)) {
79
+ if (!file.endsWith(".json")) continue;
80
+ if (shouldRemoveRuntimeUnit(file, hasMilestoneSummary)) {
81
+ cleaned += unlinkRuntimeUnit(runtimeUnitsDir, file);
82
+ }
83
+ }
84
+ } catch (err) {
85
+ logWarning(
86
+ "worktree",
87
+ `stale runtime unit cleanup failed: ${err instanceof Error ? err.message : String(err)}`,
88
+ );
89
+ }
90
+ return cleaned;
91
+ }
92
+
93
+ function shouldRemoveRuntimeUnit(
94
+ file: string,
95
+ hasMilestoneSummary: (mid: string) => boolean,
96
+ ): boolean {
97
+ if (LEGACY_DEEP_SETUP_RUNTIME_UNIT_FILES.has(file)) return true;
98
+
99
+ const staleDiscussMatch = file.match(/^discuss-milestone-(.+)\.json$/);
100
+ if (staleDiscussMatch && !MILESTONE_ID_RE.test(staleDiscussMatch[1])) {
101
+ return true;
102
+ }
103
+
104
+ const midMatch = file.match(/(M\d+(?:-[a-z0-9]{6})?)/);
105
+ return Boolean(midMatch && hasMilestoneSummary(midMatch[1]));
106
+ }
107
+
108
+ function unlinkRuntimeUnit(runtimeUnitsDir: string, file: string): number {
109
+ try {
110
+ unlinkSync(join(runtimeUnitsDir, file));
111
+ return 1;
112
+ } catch (err) {
113
+ logWarning(
114
+ "worktree",
115
+ `stale runtime unit unlink failed (${file}): ${err instanceof Error ? err.message : String(err)}`,
116
+ );
117
+ return 0;
118
+ }
119
+ }
@@ -0,0 +1,71 @@
1
+ // gsd-pi — Auto-worktree active session registry.
2
+ //
3
+ // Owns the process-local active workspace state used by auto-worktree create,
4
+ // enter, teardown, and merge paths. Keeping this state behind a focused module
5
+ // gives registry tests the same interface production uses instead of reaching
6
+ // through the legacy auto-worktree compatibility barrel.
7
+
8
+ import { nativeGetCurrentBranch } from "./native-git-bridge.js";
9
+ import {
10
+ isGsdWorktreePath,
11
+ normalizeWorktreePathForCompare,
12
+ resolveWorktreeProjectRoot,
13
+ } from "./worktree-root.js";
14
+ import { detectWorktreeName } from "./worktree.js";
15
+ import type { GsdWorkspace } from "./workspace.js";
16
+
17
+ /** Active workspace registry — replaces the legacy `originalBase` singleton. */
18
+ let activeWorkspace: GsdWorkspace | null = null;
19
+
20
+ export function setActiveWorkspace(ws: GsdWorkspace | null): void {
21
+ activeWorkspace = ws;
22
+ }
23
+
24
+ export function getActiveWorkspace(): GsdWorkspace | null {
25
+ return activeWorkspace;
26
+ }
27
+
28
+ /**
29
+ * Get the original project root stored when entering an auto-worktree.
30
+ * Returns null if not currently in an auto-worktree.
31
+ */
32
+ export function getAutoWorktreeOriginalBase(): string | null {
33
+ return getActiveWorkspace()?.projectRoot ?? null;
34
+ }
35
+
36
+ /**
37
+ * Test-only — resets the module-level `activeWorkspace` registry between
38
+ * runs. Production code never clears the registry directly; tests call this
39
+ * in `beforeEach`/`afterEach` to isolate registry-mutating cases.
40
+ */
41
+ export function _resetAutoWorktreeOriginalBaseForTests(): void {
42
+ setActiveWorkspace(null);
43
+ }
44
+
45
+ export function getActiveAutoWorktreeContext(): {
46
+ originalBase: string;
47
+ worktreeName: string;
48
+ branch: string;
49
+ } | null {
50
+ const ws = getActiveWorkspace();
51
+ if (!ws) return null;
52
+ const originalBase = ws.projectRoot;
53
+ const cwd = process.cwd();
54
+ if (!isGsdWorktreePath(cwd)) return null;
55
+ const cwdProjectRoot = resolveWorktreeProjectRoot(cwd, originalBase);
56
+ if (
57
+ normalizeWorktreePathForCompare(cwdProjectRoot) !==
58
+ normalizeWorktreePathForCompare(originalBase)
59
+ ) {
60
+ return null;
61
+ }
62
+ const worktreeName = detectWorktreeName(cwd);
63
+ if (!worktreeName) return null;
64
+ const branch = nativeGetCurrentBranch(cwd);
65
+ if (!branch.startsWith("milestone/")) return null;
66
+ return {
67
+ originalBase,
68
+ worktreeName,
69
+ branch,
70
+ };
71
+ }
@@ -0,0 +1,370 @@
1
+ // gsd-pi — Auto-worktree state sync module.
2
+ //
3
+ // Owns project-root/worktree projection compatibility seams while the project DB
4
+ // remains authoritative for workflow state.
5
+
6
+ import {
7
+ cpSync,
8
+ existsSync,
9
+ lstatSync as lstatSyncFn,
10
+ mkdirSync,
11
+ readdirSync,
12
+ } from "node:fs";
13
+ import { join } from "node:path";
14
+
15
+ import {
16
+ _isSamePath as isSamePath,
17
+ _shouldReconcileWorktreeDb,
18
+ } from "./auto-worktree-cleanup.js";
19
+ import { resolveGsdPathContract } from "./paths.js";
20
+ import type { MilestoneScope } from "./workspace.js";
21
+ import { WorktreeStateProjection } from "./worktree-state-projection.js";
22
+ import { logWarning } from "./workflow-logger.js";
23
+
24
+ const PROJECT_PREFERENCES_FILE = "PREFERENCES.md";
25
+ const LEGACY_PROJECT_PREFERENCES_FILE = "preferences.md";
26
+
27
+ /**
28
+ * Root-level .gsd/ projections copied from project root into worktrees for
29
+ * compatibility. Project root remains the canonical state/projection root.
30
+ */
31
+ const ROOT_STATE_FILES = [
32
+ "DECISIONS.md",
33
+ "REQUIREMENTS.md",
34
+ "PROJECT.md",
35
+ "KNOWLEDGE.md",
36
+ "OVERRIDES.md",
37
+ "QUEUE.md",
38
+ "completed-units.json",
39
+ "metrics.json",
40
+ "mcp.json",
41
+ // NOTE: project preferences are intentionally NOT in ROOT_STATE_FILES.
42
+ // Forward-sync (main → worktree) is handled explicitly in syncGsdStateToWorktree().
43
+ // Back-sync (worktree → main) must NEVER overwrite the project root's copy
44
+ // because the project root is authoritative for preferences (#2684).
45
+ ] as const;
46
+
47
+ /**
48
+ * Path-string entry point to WorktreeStateProjection.projectRootToWorktree.
49
+ * Production code goes through the Module class; this delegator survives so
50
+ * the projection-invariant tests (#1886, #2184, #2478, #2821) can exercise
51
+ * the bodies with raw paths.
52
+ */
53
+ export function syncProjectRootToWorktree(
54
+ projectRoot: string,
55
+ worktreePath_: string,
56
+ milestoneId: string | null,
57
+ ): void {
58
+ new WorktreeStateProjection().projectRootToWorktreePaths(
59
+ projectRoot,
60
+ worktreePath_,
61
+ milestoneId,
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Path-string entry point to WorktreeStateProjection.projectWorktreeToRoot.
67
+ * Production code goes through the Module class; this delegator survives so
68
+ * the projection-invariant tests can exercise the body with raw paths.
69
+ */
70
+ export function syncStateToProjectRoot(
71
+ worktreePath_: string,
72
+ projectRoot: string,
73
+ milestoneId: string | null,
74
+ ): void {
75
+ new WorktreeStateProjection().projectWorktreeToRootPaths(
76
+ worktreePath_,
77
+ projectRoot,
78
+ milestoneId,
79
+ );
80
+ }
81
+
82
+ /**
83
+ * Scope-typed variant of syncGsdStateToWorktree.
84
+ *
85
+ * Takes an explicit (rootScope, worktreeScope) pair. Note: milestoneId is not
86
+ * used by syncGsdStateToWorktree — this variant only requires workspace
87
+ * identity. Asserts both scopes belong to the same workspace identity to
88
+ * prevent silent mismatch bugs.
89
+ */
90
+ export function syncGsdStateToWorktreeByScope(
91
+ rootScope: MilestoneScope,
92
+ worktreeScope: MilestoneScope,
93
+ ): { synced: string[] } {
94
+ if (rootScope.workspace.identityKey !== worktreeScope.workspace.identityKey) {
95
+ throw new Error(
96
+ `syncGsdStateToWorktreeByScope: scope identity mismatch — ` +
97
+ `rootScope.identityKey="${rootScope.workspace.identityKey}" ` +
98
+ `worktreeScope.identityKey="${worktreeScope.workspace.identityKey}"`,
99
+ );
100
+ }
101
+ const mainBasePath = rootScope.workspace.projectRoot;
102
+ const worktreePath = worktreeScope.workspace.worktreeRoot
103
+ ?? worktreeScope.workspace.projectRoot;
104
+ return syncGsdStateToWorktree(mainBasePath, worktreePath);
105
+ }
106
+
107
+ /**
108
+ * Sync .gsd/ state from the main repo into the worktree.
109
+ *
110
+ * When .gsd/ is a symlink to the external state directory, both the main
111
+ * repo and worktree share the same directory — no sync needed.
112
+ *
113
+ * When .gsd/ is a real directory (e.g., git-tracked or manage_gitignore:false),
114
+ * the worktree has its own copy that may be stale. This function copies
115
+ * missing milestones, CONTEXT, ROADMAP, DECISIONS, REQUIREMENTS, and
116
+ * PROJECT files from the main repo's .gsd/ into the worktree's .gsd/.
117
+ *
118
+ * Only adds missing content — never overwrites existing files in the worktree.
119
+ * Worktree files are compatibility projections; DB/project root remains
120
+ * authoritative for runtime state.
121
+ * @deprecated Use syncGsdStateToWorktreeByScope instead.
122
+ * TODO(C-future): remove once all callers migrated.
123
+ */
124
+ export function syncGsdStateToWorktree(
125
+ mainBasePath: string,
126
+ worktreePath_: string,
127
+ ): { synced: string[] } {
128
+ const contract = resolveGsdPathContract(worktreePath_, mainBasePath);
129
+ const mainGsd = contract.projectGsd;
130
+ const wtGsd = contract.worktreeGsd ?? join(worktreePath_, ".gsd");
131
+ const synced: string[] = [];
132
+
133
+ if (isSamePath(mainGsd, wtGsd)) return { synced };
134
+ if (!existsSync(mainGsd)) return { synced };
135
+
136
+ mkdirSync(wtGsd, { recursive: true });
137
+ syncRootStateFiles(mainGsd, wtGsd, synced);
138
+ syncProjectPreferences(mainGsd, wtGsd, synced);
139
+ syncMilestoneLayouts(mainGsd, wtGsd, synced);
140
+
141
+ return { synced };
142
+ }
143
+
144
+ function syncRootStateFiles(
145
+ mainGsd: string,
146
+ wtGsd: string,
147
+ synced: string[],
148
+ ): void {
149
+ for (const file of ROOT_STATE_FILES) {
150
+ const src = join(mainGsd, file);
151
+ const dst = join(wtGsd, file);
152
+ if (!existsSync(src) || existsSync(dst)) continue;
153
+
154
+ try {
155
+ cpSync(src, dst);
156
+ synced.push(file);
157
+ } catch (err) {
158
+ logWarning(
159
+ "worktree",
160
+ `file copy failed (${file}): ${err instanceof Error ? err.message : String(err)}`,
161
+ );
162
+ }
163
+ }
164
+ }
165
+
166
+ function syncProjectPreferences(
167
+ mainGsd: string,
168
+ wtGsd: string,
169
+ synced: string[],
170
+ ): void {
171
+ const worktreeHasPreferences = existsSync(join(wtGsd, PROJECT_PREFERENCES_FILE))
172
+ || existsSync(join(wtGsd, LEGACY_PROJECT_PREFERENCES_FILE));
173
+ if (worktreeHasPreferences) return;
174
+
175
+ for (const file of [PROJECT_PREFERENCES_FILE, LEGACY_PROJECT_PREFERENCES_FILE] as const) {
176
+ const src = join(mainGsd, file);
177
+ const dst = join(wtGsd, file);
178
+ if (!existsSync(src)) continue;
179
+
180
+ try {
181
+ cpSync(src, dst);
182
+ synced.push(file);
183
+ } catch (err) {
184
+ logWarning(
185
+ "worktree",
186
+ `preferences copy failed (${file}): ${err instanceof Error ? err.message : String(err)}`,
187
+ );
188
+ }
189
+ return;
190
+ }
191
+ }
192
+
193
+ function syncMilestoneLayouts(
194
+ mainGsd: string,
195
+ wtGsd: string,
196
+ synced: string[],
197
+ ): void {
198
+ for (const layoutSegment of ["phases", "milestones"] as const) {
199
+ syncMilestoneLayout(mainGsd, wtGsd, layoutSegment, synced);
200
+ }
201
+ }
202
+
203
+ function syncMilestoneLayout(
204
+ mainGsd: string,
205
+ wtGsd: string,
206
+ layoutSegment: "phases" | "milestones",
207
+ synced: string[],
208
+ ): void {
209
+ const mainMilestonesDir = join(mainGsd, layoutSegment);
210
+ const wtMilestonesDir = join(wtGsd, layoutSegment);
211
+ if (!existsSync(mainMilestonesDir)) return;
212
+
213
+ try {
214
+ mkdirSync(wtMilestonesDir, { recursive: true });
215
+ const mainMilestones = readdirSync(mainMilestonesDir, { withFileTypes: true })
216
+ .filter((entry) => entry.isDirectory())
217
+ .map((entry) => entry.name);
218
+
219
+ for (const milestoneId of mainMilestones) {
220
+ syncMilestoneDirectory(
221
+ mainMilestonesDir,
222
+ wtMilestonesDir,
223
+ milestoneId,
224
+ synced,
225
+ );
226
+ }
227
+ } catch (err) {
228
+ logWarning(
229
+ "worktree",
230
+ `milestone directory sync failed: ${err instanceof Error ? err.message : String(err)}`,
231
+ );
232
+ }
233
+ }
234
+
235
+ function syncMilestoneDirectory(
236
+ mainMilestonesDir: string,
237
+ wtMilestonesDir: string,
238
+ milestoneId: string,
239
+ synced: string[],
240
+ ): void {
241
+ const srcDir = join(mainMilestonesDir, milestoneId);
242
+ const dstDir = join(wtMilestonesDir, milestoneId);
243
+
244
+ if (!existsSync(dstDir)) {
245
+ try {
246
+ cpSync(srcDir, dstDir, { recursive: true });
247
+ // Preserve the legacy telemetry string used before this extraction. The
248
+ // actual layout may be `phases/`; callers only consumed this as a coarse
249
+ // "milestone projection copied" marker.
250
+ synced.push(`milestones/${milestoneId}/`);
251
+ } catch (err) {
252
+ logWarning(
253
+ "worktree",
254
+ `milestone copy failed (${milestoneId}): ${err instanceof Error ? err.message : String(err)}`,
255
+ );
256
+ }
257
+ return;
258
+ }
259
+
260
+ try {
261
+ syncMilestoneTopLevelFiles(srcDir, dstDir, milestoneId, synced);
262
+ syncSlicesDirectory(srcDir, dstDir, milestoneId, synced);
263
+ } catch (err) {
264
+ logWarning(
265
+ "worktree",
266
+ `milestone file sync failed: ${err instanceof Error ? err.message : String(err)}`,
267
+ );
268
+ }
269
+ }
270
+
271
+ function syncMilestoneTopLevelFiles(
272
+ srcDir: string,
273
+ dstDir: string,
274
+ milestoneId: string,
275
+ synced: string[],
276
+ ): void {
277
+ const srcFiles = readdirSync(srcDir).filter(
278
+ (file) => file.endsWith(".md") || file.endsWith(".json"),
279
+ );
280
+
281
+ for (const file of srcFiles) {
282
+ const srcFile = join(srcDir, file);
283
+ const dstFile = join(dstDir, file);
284
+ if (existsSync(dstFile)) continue;
285
+
286
+ try {
287
+ const srcStat = lstatSyncFn(srcFile);
288
+ if (!srcStat.isFile()) continue;
289
+
290
+ cpSync(srcFile, dstFile);
291
+ synced.push(`milestones/${milestoneId}/${file}`);
292
+ } catch (err) {
293
+ logWarning(
294
+ "worktree",
295
+ `milestone file copy failed (${milestoneId}/${file}): ${err instanceof Error ? err.message : String(err)}`,
296
+ );
297
+ }
298
+ }
299
+ }
300
+
301
+ function syncSlicesDirectory(
302
+ srcDir: string,
303
+ dstDir: string,
304
+ milestoneId: string,
305
+ synced: string[],
306
+ ): void {
307
+ const srcSlicesDir = join(srcDir, "slices");
308
+ const dstSlicesDir = join(dstDir, "slices");
309
+ if (!existsSync(srcSlicesDir)) return;
310
+
311
+ if (!existsSync(dstSlicesDir)) {
312
+ try {
313
+ cpSync(srcSlicesDir, dstSlicesDir, { recursive: true });
314
+ synced.push(`milestones/${milestoneId}/slices/`);
315
+ } catch (err) {
316
+ logWarning(
317
+ "worktree",
318
+ `slices copy failed (${milestoneId}): ${err instanceof Error ? err.message : String(err)}`,
319
+ );
320
+ }
321
+ return;
322
+ }
323
+
324
+ const srcSlices = readdirSync(srcSlicesDir, { withFileTypes: true })
325
+ .filter((entry) => entry.isDirectory())
326
+ .map((entry) => entry.name);
327
+
328
+ for (const sliceId of srcSlices) {
329
+ const srcSlice = join(srcSlicesDir, sliceId);
330
+ const dstSlice = join(dstSlicesDir, sliceId);
331
+ if (existsSync(dstSlice)) continue;
332
+
333
+ try {
334
+ cpSync(srcSlice, dstSlice, { recursive: true });
335
+ synced.push(`milestones/${milestoneId}/slices/${sliceId}/`);
336
+ } catch (err) {
337
+ logWarning(
338
+ "worktree",
339
+ `slice copy failed (${milestoneId}/${sliceId}): ${err instanceof Error ? err.message : String(err)}`,
340
+ );
341
+ }
342
+ }
343
+ }
344
+
345
+ /**
346
+ * Sync compatibility artifacts from worktree back to the main external state
347
+ * directory. Canonical workflow state lives in the project DB; worktree .gsd
348
+ * content is legacy projection/diagnostic data only.
349
+ *
350
+ * Syncs:
351
+ * 1. Legacy worktree DBs are reconciled into the canonical project DB.
352
+ * 2. Runtime diagnostic files may be copied for operator visibility.
353
+ *
354
+ * Markdown milestone directories are projections and are not copied from
355
+ * worktrees into the project root. Current workflow state must arrive through
356
+ * the shared project DB or the pre-upgrade DB reconciliation path above.
357
+ */
358
+ export function syncWorktreeStateBack(
359
+ mainBasePath: string,
360
+ worktreePath: string,
361
+ milestoneId: string,
362
+ ): { synced: string[] } {
363
+ return new WorktreeStateProjection().finalizeProjectionForMergePaths(
364
+ mainBasePath,
365
+ worktreePath,
366
+ milestoneId,
367
+ );
368
+ }
369
+
370
+ export { _shouldReconcileWorktreeDb } from "./auto-worktree-cleanup.js";