@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,237 @@
1
+ // gsd-pi — Auto-worktree branch lifecycle module.
2
+ //
3
+ // Owns milestone branch naming, branch-mode entry, and safe fast-forward of
4
+ // reused milestone branches. Worktree creation/merge code imports this module
5
+ // instead of keeping branch policy inside the legacy auto-worktree barrel.
6
+
7
+ import { GSDError, GSD_GIT_ERROR } from "./errors.js";
8
+ import { readIntegrationBranch } from "./git-service.js";
9
+ import { loadEffectiveGSDPreferences } from "./preferences.js";
10
+ import { debugLog } from "./debug-logger.js";
11
+ import { checkoutBranchWithStashGuard } from "./worktree-git-recovery.js";
12
+ import {
13
+ nativeBranchExists,
14
+ nativeBranchForceReset,
15
+ nativeDetectMainBranch,
16
+ nativeIsAncestor,
17
+ nativeUpdateRef,
18
+ nativeWorktreeList,
19
+ } from "./native-git-bridge.js";
20
+
21
+ /** Returns the git branch name for a milestone worktree (`milestone/<MID>`). */
22
+ export function autoWorktreeBranch(milestoneId: string): string {
23
+ return `milestone/${milestoneId}`;
24
+ }
25
+
26
+ export function _resolveAutoWorktreeStartPoint(
27
+ integrationBranch: string | null | undefined,
28
+ gitMainBranch: string | null | undefined,
29
+ branchExists: (branch: string) => boolean,
30
+ ): string | undefined {
31
+ if (integrationBranch) return integrationBranch;
32
+ return gitMainBranch &&
33
+ typeof gitMainBranch === "string" &&
34
+ gitMainBranch.length > 0 &&
35
+ branchExists(gitMainBranch)
36
+ ? gitMainBranch
37
+ : undefined;
38
+ }
39
+
40
+ /**
41
+ * Enter branch isolation mode for a milestone.
42
+ *
43
+ * Creates `milestone/<MID>` from the integration branch (if it doesn't
44
+ * exist yet) and checks out to it. No worktree directory is created — the
45
+ * project root is the working copy; only HEAD changes.
46
+ *
47
+ * Uses the same 3-tier integration-branch fallback as createAutoWorktree:
48
+ * 1. META.json recorded integration branch
49
+ * 2. git.main_branch preference
50
+ * 3. nativeDetectMainBranch (origin/HEAD auto-detection)
51
+ */
52
+ export function enterBranchModeForMilestone(
53
+ basePath: string,
54
+ milestoneId: string,
55
+ ): void {
56
+ const branch = autoWorktreeBranch(milestoneId);
57
+ const branchExists = nativeBranchExists(basePath, branch);
58
+
59
+ if (!branchExists) {
60
+ // Create the milestone branch from the integration branch start-point.
61
+ const integrationBranch =
62
+ readIntegrationBranch(basePath, milestoneId) ?? undefined;
63
+ const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
64
+ const startPoint =
65
+ _resolveAutoWorktreeStartPoint(
66
+ integrationBranch,
67
+ gitPrefs?.main_branch,
68
+ (branchName) => nativeBranchExists(basePath, branchName),
69
+ ) ??
70
+ nativeDetectMainBranch(basePath);
71
+
72
+ // TOCTOU ancestry guard (Issue #4980 HIGH-3).
73
+ //
74
+ // The outer `branchExists` check is racy: a concurrent process
75
+ // (parallel-orchestrator worker, side-by-side `gsd` instance, or manual
76
+ // `git branch` invocation) may have created the branch with real commits
77
+ // between that check and this point. `nativeBranchForceReset` does
78
+ // `git branch -f`, which silently overwrites the branch ref — orphaning
79
+ // any commits not reachable from `startPoint`. Re-check immediately
80
+ // before the destructive call and refuse if the branch suddenly exists
81
+ // with non-ancestor commits.
82
+ const concurrentlyCreated = nativeBranchExists(basePath, branch);
83
+ if (
84
+ concurrentlyCreated &&
85
+ !nativeIsAncestor(basePath, branch, startPoint)
86
+ ) {
87
+ throw new GSDError(
88
+ GSD_GIT_ERROR,
89
+ `Branch "${branch}" was created concurrently with commits not reachable from "${startPoint}". ` +
90
+ `Refusing to force-reset — would orphan prior work. ` +
91
+ `Resume the existing milestone or run \`git branch -D ${branch}\` to discard.`,
92
+ );
93
+ }
94
+ // nativeBranchForceReset creates (or resets) branch at startPoint,
95
+ // then checkout switches HEAD to it.
96
+ nativeBranchForceReset(basePath, branch, startPoint);
97
+ debugLog("auto-worktree", {
98
+ action: "enterBranchMode",
99
+ milestoneId,
100
+ branch,
101
+ startPoint,
102
+ created: true,
103
+ });
104
+ } else {
105
+ debugLog("auto-worktree", {
106
+ action: "enterBranchMode",
107
+ milestoneId,
108
+ branch,
109
+ reused: true,
110
+ });
111
+ }
112
+
113
+ checkoutBranchWithStashGuard(
114
+ basePath,
115
+ branch,
116
+ `enter-branch-mode:${milestoneId}`,
117
+ );
118
+ }
119
+
120
+ /**
121
+ * True when `branch` is checked out in any worktree listed by
122
+ * `git worktree list --porcelain`. Used to gate ref updates that would
123
+ * otherwise leave a concurrent worktree's HEAD inconsistent with its
124
+ * index/working tree (Codex peer-review of #5538-followup).
125
+ *
126
+ * Best-effort: a `nativeWorktreeList` failure returns true so we err on
127
+ * the side of NOT moving the ref. Better to skip a fast-forward than to
128
+ * silently corrupt another worktree.
129
+ */
130
+ export function _isBranchCheckedOutElsewhere(
131
+ basePath: string,
132
+ branch: string,
133
+ ): boolean {
134
+ try {
135
+ const entries = nativeWorktreeList(basePath);
136
+ return entries.some((entry) => entry.branch === branch);
137
+ } catch {
138
+ return true;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Resolve the integration branch using the same 3-tier fallback as the
144
+ * fresh-create path: META.json → git.main_branch preference → detected
145
+ * main branch. Returns null when no usable target exists.
146
+ */
147
+ function resolveIntegrationBranchForReuse(
148
+ basePath: string,
149
+ milestoneId: string,
150
+ ): string | null {
151
+ const fromMeta = readIntegrationBranch(basePath, milestoneId);
152
+ if (fromMeta) return fromMeta;
153
+
154
+ const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
155
+ const fromPref = gitPrefs?.main_branch &&
156
+ typeof gitPrefs.main_branch === "string" &&
157
+ gitPrefs.main_branch.length > 0 &&
158
+ nativeBranchExists(basePath, gitPrefs.main_branch)
159
+ ? gitPrefs.main_branch
160
+ : null;
161
+ if (fromPref) return fromPref;
162
+
163
+ try {
164
+ return nativeDetectMainBranch(basePath);
165
+ } catch {
166
+ return null;
167
+ }
168
+ }
169
+
170
+ /**
171
+ * When reusing an existing milestone branch, fast-forward it onto the
172
+ * integration branch when that's safe (branch is a strict ancestor of
173
+ * integration — no commits would be lost). Skips when the branch has its
174
+ * own commits ahead of integration, when the integration branch can't be
175
+ * resolved, or when any git operation fails — the merge gate at milestone
176
+ * completion will surface real divergence as a conflict.
177
+ *
178
+ * The previous behavior re-attached the worktree to whatever stale tip
179
+ * the branch held, which caused new milestone work to fork from a base
180
+ * missing prior milestones' merges (#5538-followup).
181
+ */
182
+ export function fastForwardReusedMilestoneBranchIfSafe(
183
+ basePath: string,
184
+ milestoneId: string,
185
+ branch: string,
186
+ ): void {
187
+ try {
188
+ const integrationBranch = resolveIntegrationBranchForReuse(
189
+ basePath,
190
+ milestoneId,
191
+ );
192
+ if (!integrationBranch || integrationBranch === branch) return;
193
+ if (!nativeBranchExists(basePath, integrationBranch)) return;
194
+
195
+ // Pure fast-forward only: branch must be a strict ancestor of integration.
196
+ // If the branch has its own commits ahead, leave it alone.
197
+ if (!nativeIsAncestor(basePath, branch, integrationBranch)) {
198
+ debugLog("createAutoWorktree", {
199
+ phase: "skip-ff-branch-not-ancestor",
200
+ milestoneId,
201
+ branch,
202
+ integration: integrationBranch,
203
+ });
204
+ return;
205
+ }
206
+
207
+ // Codex peer-review: `nativeUpdateRef` succeeds even when the branch is
208
+ // currently checked out in another worktree, leaving that worktree's HEAD
209
+ // inconsistent with its index/work tree. Skip the fast-forward if any
210
+ // listed worktree has this branch checked out — the merge gate at
211
+ // milestone-completion will surface stale-base divergence as a conflict
212
+ // instead of silently corrupting the other worktree's state.
213
+ if (_isBranchCheckedOutElsewhere(basePath, branch)) {
214
+ debugLog("createAutoWorktree", {
215
+ phase: "skip-ff-branch-checked-out-elsewhere",
216
+ milestoneId,
217
+ branch,
218
+ });
219
+ return;
220
+ }
221
+
222
+ nativeUpdateRef(basePath, `refs/heads/${branch}`, integrationBranch);
223
+ debugLog("createAutoWorktree", {
224
+ phase: "fast-forward-reused-branch",
225
+ milestoneId,
226
+ branch,
227
+ integration: integrationBranch,
228
+ });
229
+ } catch (err) {
230
+ debugLog("createAutoWorktree", {
231
+ phase: "fast-forward-reused-branch-failed",
232
+ milestoneId,
233
+ branch,
234
+ error: err instanceof Error ? err.message : String(err),
235
+ });
236
+ }
237
+ }
@@ -0,0 +1,166 @@
1
+ // gsd-pi — Auto-worktree cleanup helpers.
2
+ //
3
+ // Owns shared cleanup primitives used by teardown and merge cleanup paths:
4
+ // same-file DB reconciliation checks, transient project-root state removal,
5
+ // git pathspec conversion for externally-rooted .gsd paths, and expected
6
+ // unlink error classification.
7
+
8
+ import { execFileSync } from "node:child_process";
9
+ import { existsSync, realpathSync, unlinkSync } from "node:fs";
10
+ import { isAbsolute, join, relative } from "node:path";
11
+
12
+ import { gsdRoot } from "./paths.js";
13
+ import { logWarning } from "./workflow-logger.js";
14
+
15
+ function isSamePath(a: string, b: string): boolean {
16
+ try {
17
+ return realpathSync(a) === realpathSync(b);
18
+ } catch (e) {
19
+ if ((e as NodeJS.ErrnoException).code === "ENOENT") return false;
20
+ logWarning("worktree", `isSamePath failed: ${(e as Error).message}`);
21
+ return false;
22
+ }
23
+ }
24
+
25
+ export function _isSamePath(a: string, b: string): boolean {
26
+ return isSamePath(a, b);
27
+ }
28
+
29
+ export function _shouldReconcileWorktreeDb(
30
+ worktreeDbPath: string,
31
+ mainDbPath: string,
32
+ pathExists: (path: string) => boolean = existsSync,
33
+ samePath: (a: string, b: string) => boolean = isSamePath,
34
+ ): boolean {
35
+ return pathExists(worktreeDbPath) && !samePath(worktreeDbPath, mainDbPath);
36
+ }
37
+
38
+ export function _isExpectedWorktreeUnlinkError(
39
+ code: string | undefined,
40
+ ): boolean {
41
+ return code === "ENOENT" || code === "EISDIR";
42
+ }
43
+
44
+ function gitPathspecForWorktreePath(
45
+ basePath: string,
46
+ targetPath: string,
47
+ ): string | null {
48
+ let base = basePath;
49
+ let target = targetPath;
50
+ try {
51
+ base = execFileSync("git", ["rev-parse", "--show-toplevel"], {
52
+ cwd: basePath,
53
+ stdio: ["ignore", "pipe", "ignore"],
54
+ encoding: "utf-8",
55
+ }).trim() || basePath;
56
+ } catch {
57
+ /* keep original */
58
+ void base;
59
+ }
60
+ try {
61
+ base = realpathSync.native(base);
62
+ } catch {
63
+ /* keep original */
64
+ void base;
65
+ }
66
+ try {
67
+ target = realpathSync.native(targetPath);
68
+ } catch {
69
+ /* keep original */
70
+ void target;
71
+ }
72
+
73
+ const rel = relative(base, target);
74
+ if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) return null;
75
+ return rel.replaceAll("\\", "/");
76
+ }
77
+
78
+ export function _gitPathspecForWorktreePath(
79
+ basePath: string,
80
+ targetPath: string,
81
+ ): string | null {
82
+ return gitPathspecForWorktreePath(basePath, targetPath);
83
+ }
84
+
85
+ export function clearProjectRootStateFiles(
86
+ basePath: string,
87
+ milestoneId: string,
88
+ ): void {
89
+ const gsdDir = gsdRoot(basePath);
90
+ // Phase C pt 2: auto.lock removed from this list — the file is gone
91
+ // (migrated to the workers + unit_dispatches + runtime_kv tables). The
92
+ // remaining transient files (STATE.md, {MID}-META.json) are still
93
+ // worth removing on teardown.
94
+ const transientFiles = [
95
+ join(gsdDir, "STATE.md"),
96
+ join(gsdDir, "milestones", milestoneId, `${milestoneId}-META.json`),
97
+ ];
98
+
99
+ for (const file of transientFiles) {
100
+ try {
101
+ unlinkSync(file);
102
+ } catch (err) {
103
+ // ENOENT is expected — file may not exist (#3597)
104
+ if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
105
+ logWarning(
106
+ "worktree",
107
+ `file unlink failed: ${err instanceof Error ? err.message : String(err)}`,
108
+ );
109
+ }
110
+ }
111
+ }
112
+
113
+ // Clean up legacy synced milestone directories and runtime/units.
114
+ // Older versions copied these into the project root during execution.
115
+ // If they remain as untracked files when we attempt
116
+ // `git merge --squash`, git rejects the merge with "local changes would
117
+ // be overwritten", causing silent data loss (#1738).
118
+ const syncedDirs = [
119
+ join(gsdDir, "milestones", milestoneId),
120
+ join(gsdDir, "runtime", "units"),
121
+ ];
122
+
123
+ for (const dir of syncedDirs) {
124
+ try {
125
+ if (!existsSync(dir)) continue;
126
+
127
+ const pathspec = gitPathspecForWorktreePath(basePath, dir);
128
+ if (!pathspec) continue;
129
+
130
+ // Only remove files that are untracked by git — tracked files are
131
+ // managed by the branch checkout and should not be deleted.
132
+ const untrackedOutput = execFileSync(
133
+ "git",
134
+ ["ls-files", "--others", "--exclude-standard", pathspec],
135
+ {
136
+ cwd: basePath,
137
+ stdio: ["ignore", "pipe", "pipe"],
138
+ encoding: "utf-8",
139
+ },
140
+ ).trim();
141
+ if (!untrackedOutput) continue;
142
+
143
+ for (const f of untrackedOutput.split("\n").filter(Boolean)) {
144
+ try {
145
+ unlinkSync(join(basePath, f));
146
+ } catch (err) {
147
+ // ENOENT/EISDIR are expected for already-removed or
148
+ // directory entries (#3597).
149
+ const code = (err as NodeJS.ErrnoException).code;
150
+ if (!_isExpectedWorktreeUnlinkError(code)) {
151
+ logWarning(
152
+ "worktree",
153
+ `untracked file unlink failed: ${err instanceof Error ? err.message : String(err)}`,
154
+ );
155
+ }
156
+ }
157
+ }
158
+ } catch (err) {
159
+ /* non-fatal — git command may fail if not in repo */
160
+ logWarning(
161
+ "worktree",
162
+ `untracked file cleanup failed: ${err instanceof Error ? err.message : String(err)}`,
163
+ );
164
+ }
165
+ }
166
+ }
@@ -0,0 +1,37 @@
1
+ // gsd-pi — Conflict auto-resolve policy for auto-worktree merges.
2
+ //
3
+ // Owns the pure path policy for conflict paths that are safe to resolve
4
+ // mechanically. Git mutation stays in git-conflict-resolve.ts.
5
+
6
+ /** Patterns for machine-generated build artifacts that can be safely
7
+ * auto-resolved by accepting --theirs during merge. These files are
8
+ * regenerable and never contain meaningful manual edits. */
9
+ export const SAFE_AUTO_RESOLVE_PATTERNS: RegExp[] = [
10
+ /\.tsbuildinfo$/,
11
+ /\.pyc$/,
12
+ /\/__pycache__\//,
13
+ /\.DS_Store$/,
14
+ /\.map$/,
15
+ // Regenerable dependency lockfiles. These are fully derivable from their
16
+ // manifests by the package manager, so accepting the merge side during
17
+ // auto-resolve clears the conflict markers without losing meaningful edits —
18
+ // and stops auto-mode from hard-pausing on a lockfile conflict (issue #828).
19
+ /(?:^|\/)pnpm-lock\.yaml$/,
20
+ /(?:^|\/)package-lock\.json$/,
21
+ /(?:^|\/)npm-shrinkwrap\.json$/,
22
+ /(?:^|\/)yarn\.lock$/,
23
+ /(?:^|\/)bun\.lockb?$/,
24
+ /(?:^|\/)Cargo\.lock$/,
25
+ /(?:^|\/)composer\.lock$/,
26
+ /(?:^|\/)Gemfile\.lock$/,
27
+ /(?:^|\/)Pipfile\.lock$/,
28
+ /(?:^|\/)poetry\.lock$/,
29
+ ];
30
+
31
+ /** Returns true if the file path is safe to auto-resolve during merge.
32
+ * Covers `.gsd/` state files, common build artifacts, and regenerable
33
+ * dependency lockfiles. */
34
+ export function isSafeToAutoResolve(filePath: string): boolean {
35
+ return filePath.startsWith(".gsd/")
36
+ || SAFE_AUTO_RESOLVE_PATTERNS.some((re) => re.test(filePath));
37
+ }
@@ -0,0 +1,171 @@
1
+ // gsd-pi — Auto-worktree creation module.
2
+ //
3
+ // Owns the creation path for milestone worktrees: repository readiness,
4
+ // branch reuse/start-point selection, initial untracked-content import,
5
+ // post-create hook, cwd transition, and session registry update.
6
+
7
+ import { execFileSync } from "node:child_process";
8
+ import { cpSync, existsSync, mkdirSync } from "node:fs";
9
+ import { dirname, join } from "node:path";
10
+
11
+ import { classifyProject } from "./detection.js";
12
+ import { GSDError, GSD_GIT_ERROR, GSD_IO_ERROR } from "./errors.js";
13
+ import { readIntegrationBranch } from "./git-service.js";
14
+ import { nativeBranchExists } from "./native-git-bridge.js";
15
+ import { loadEffectiveGSDPreferences } from "./preferences.js";
16
+ import {
17
+ autoWorktreeBranch,
18
+ fastForwardReusedMilestoneBranchIfSafe,
19
+ _resolveAutoWorktreeStartPoint,
20
+ } from "./auto-worktree-branch-lifecycle.js";
21
+ import { setActiveWorkspace } from "./auto-worktree-session-registry.js";
22
+ import { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
23
+ import { createWorktree } from "./worktree-manager.js";
24
+ import { nudgeGitBranchCache } from "./worktree.js";
25
+ import { resolveWorktreeProjectRoot } from "./worktree-root.js";
26
+ import { createWorkspace } from "./workspace.js";
27
+ import { debugLog } from "./debug-logger.js";
28
+ import { logWarning } from "./workflow-logger.js";
29
+
30
+ function importUntrackedProjectRootContentIntoEmptyWorktree(
31
+ projectRoot: string,
32
+ worktreeRoot: string,
33
+ milestoneId: string,
34
+ ): number {
35
+ const worktreeClassification = classifyProject(worktreeRoot);
36
+ if (worktreeClassification.kind !== "greenfield") return 0;
37
+
38
+ const projectRootClassification = classifyProject(projectRoot);
39
+ if (
40
+ projectRootClassification.kind === "greenfield" ||
41
+ projectRootClassification.kind === "invalid-repo" ||
42
+ projectRootClassification.untrackedFiles.length === 0
43
+ ) {
44
+ return 0;
45
+ }
46
+
47
+ let copied = 0;
48
+ for (const relPath of projectRootClassification.untrackedFiles) {
49
+ const src = join(projectRoot, relPath);
50
+ if (!existsSync(src)) continue;
51
+
52
+ const dst = join(worktreeRoot, relPath);
53
+ if (existsSync(dst)) continue;
54
+
55
+ mkdirSync(dirname(dst), { recursive: true });
56
+ cpSync(src, dst, { recursive: true, force: false });
57
+ copied++;
58
+ }
59
+
60
+ if (copied > 0) {
61
+ debugLog("createAutoWorktree", {
62
+ phase: "import-untracked-project-content",
63
+ milestoneId,
64
+ copied,
65
+ });
66
+ }
67
+
68
+ return copied;
69
+ }
70
+
71
+ export function createAutoWorktree(
72
+ basePath: string,
73
+ milestoneId: string,
74
+ ): string {
75
+ basePath = resolveWorktreeProjectRoot(basePath);
76
+
77
+ // Check if repo has commits — git worktree requires a valid HEAD.
78
+ try {
79
+ execFileSync("git", ["rev-parse", "--verify", "HEAD"], {
80
+ cwd: basePath,
81
+ stdio: "pipe",
82
+ });
83
+ } catch {
84
+ throw new GSDError(
85
+ GSD_GIT_ERROR,
86
+ "Cannot create worktree: repository has no commits yet. Worktree isolation requires at least one commit.",
87
+ );
88
+ }
89
+
90
+ const branch = autoWorktreeBranch(milestoneId);
91
+
92
+ // Check if the milestone branch already exists — it survives auto-mode
93
+ // stop/pause and contains committed work from prior sessions. If it exists,
94
+ // re-attach the worktree to it WITHOUT resetting. Only create a fresh branch
95
+ // from the integration branch when no prior work exists.
96
+ const branchExists = nativeBranchExists(basePath, branch);
97
+
98
+ let info: { name: string; path: string; branch: string; exists: boolean };
99
+ if (branchExists) {
100
+ // #5538-followup: fast-forward the reused branch onto the integration
101
+ // branch when safe so the next milestone forks from up-to-date code.
102
+ // Without this, a milestone that was created before another milestone
103
+ // merged into main would carry a stale base into its worktree.
104
+ fastForwardReusedMilestoneBranchIfSafe(basePath, milestoneId, branch);
105
+
106
+ // Re-attach worktree to the existing milestone branch (preserving commits).
107
+ info = createWorktree(basePath, milestoneId, {
108
+ branch,
109
+ reuseExistingBranch: true,
110
+ });
111
+ } else {
112
+ // Fresh start — create branch from integration branch.
113
+ // Use the same 3-tier fallback as mergeMilestoneToMain (#3461):
114
+ // 1. META.json integration branch (explicit per-milestone override)
115
+ // 2. git.main_branch preference (user's configured working branch)
116
+ // 3. nativeDetectMainBranch (origin/HEAD auto-detection)
117
+ // Without tier 2, projects with main_branch=dev but origin/HEAD→master
118
+ // would fork worktrees from the wrong (stale) branch.
119
+ const integrationBranch = readIntegrationBranch(basePath, milestoneId)
120
+ ?? undefined;
121
+ const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
122
+ const startPoint = _resolveAutoWorktreeStartPoint(
123
+ integrationBranch,
124
+ gitPrefs?.main_branch,
125
+ (branchName) => nativeBranchExists(basePath, branchName),
126
+ );
127
+ info = createWorktree(basePath, milestoneId, {
128
+ branch,
129
+ startPoint,
130
+ });
131
+ }
132
+
133
+ // Phase C: copyPlanningArtifacts and reconcilePlanCheckboxes were
134
+ // deleted. Both addressed the same problem (worktree-local .gsd/
135
+ // projection lagging behind project-root state) by maintaining a stale
136
+ // copy. Now that auto-mode writers in workflow-projections.ts,
137
+ // triage-resolution.ts, rule-registry.ts, and auto-post-unit.ts route
138
+ // through s.canonicalProjectRoot, the worktree never needs a local
139
+ // .gsd/ — both reads and writes converge on the project-root .gsd/.
140
+ // The original concerns (#759, #778) no longer apply because there is
141
+ // no second copy to drift.
142
+ importUntrackedProjectRootContentIntoEmptyWorktree(
143
+ basePath,
144
+ info.path,
145
+ milestoneId,
146
+ );
147
+
148
+ // Run user-configured post-create hook (#597) — e.g. copy .env, symlink assets.
149
+ const hookError = runWorktreePostCreateHook(basePath, info.path);
150
+ if (hookError) {
151
+ // Non-fatal — log but don't prevent worktree usage.
152
+ logWarning("reconcile", hookError, { worktree: info.name });
153
+ }
154
+
155
+ const previousCwd = process.cwd();
156
+
157
+ try {
158
+ process.chdir(info.path);
159
+ setActiveWorkspace(createWorkspace(basePath));
160
+ } catch (err) {
161
+ // If chdir fails, the worktree was created but we couldn't enter it.
162
+ // Don't set activeWorkspace -- caller can retry or clean up.
163
+ throw new GSDError(
164
+ GSD_IO_ERROR,
165
+ `Auto-worktree created at ${info.path} but chdir failed: ${err instanceof Error ? err.message : String(err)}`,
166
+ );
167
+ }
168
+
169
+ nudgeGitBranchCache(previousCwd);
170
+ return info.path;
171
+ }