@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
@@ -3,8 +3,10 @@
3
3
 
4
4
  import { importExtensionModule, type ExtensionAPI, type ExtensionContext } from "@gsd/pi-coding-agent";
5
5
 
6
+ import { execFileSync } from "node:child_process";
7
+ import { createHash } from "node:crypto";
6
8
  import { join, basename } from "node:path";
7
- import { existsSync, cpSync } from "node:fs";
9
+ import { existsSync, cpSync, readFileSync } from "node:fs";
8
10
  import type { AutoSession } from "./session.js";
9
11
  import type { LoopDeps } from "./loop-deps.js";
10
12
  import type { GSDState } from "../types.js";
@@ -16,7 +18,7 @@ import { getIsolationMode } from "../preferences.js";
16
18
  import { isDbAvailable, getMilestone } from "../gsd-db.js";
17
19
  import { refreshWorkflowDatabaseFromDisk } from "../db-workspace.js";
18
20
  import { isClosedStatus } from "../status-guards.js";
19
- import { gsdRoot } from "../paths.js";
21
+ import { gsdRoot, PLANNING_ARTIFACT_SUFFIXES } from "../paths.js";
20
22
  import { atomicWriteSync } from "../atomic-write.js";
21
23
  import { logWarning, logError } from "../workflow-logger.js";
22
24
  import { debugLog } from "../debug-logger.js";
@@ -98,7 +100,15 @@ export async function _runMilestoneMergeWithStashRestore(
98
100
  ): Promise<{ action: "break"; reason: string } | null> {
99
101
  const { ctx, pi, s, deps } = ic;
100
102
 
101
- const projectRoot = s.originalBasePath || s.basePath;
103
+ // Resolve the project root once, before the merge can flip session path
104
+ // pointers (worktree teardown mutates s.basePath / s.scope). The guarded
105
+ // merge's preflight/postflight stash restore, the pre-merge ignored-markdown
106
+ // snapshot, the dirty-projection check, and the rebuild must all target this
107
+ // same tree; otherwise `.gsd` markdown restored on one tree can be silently
108
+ // overwritten by a rebuild on another. canonicalProjectRoot is the
109
+ // authoritative `.gsd`/DB writer path (see AutoSession.canonicalProjectRoot).
110
+ const projectRoot = s.originalBasePath || s.canonicalProjectRoot || s.basePath;
111
+ const ignoredProjectionSnapshot = snapshotIgnoredGsdMarkdownProjections(projectRoot);
102
112
  const mergeResult = deps.lifecycle.exitMilestone(
103
113
  milestoneId,
104
114
  {
@@ -113,12 +123,12 @@ export async function _runMilestoneMergeWithStashRestore(
113
123
  );
114
124
 
115
125
  if (mergeResult.ok) {
116
- await markMilestoneMergedAndRebuild(s);
126
+ await markMilestoneMergedAndRebuild(s, projectRoot, ignoredProjectionSnapshot);
117
127
  return null;
118
128
  }
119
129
 
120
130
  if (mergeResult.reason === "postflight-stash-restore-failed") {
121
- await markMilestoneMergedAndRebuild(s);
131
+ await markMilestoneMergedAndRebuild(s, projectRoot, ignoredProjectionSnapshot);
122
132
  }
123
133
 
124
134
  if (mergeResult.reason === "preflight-dirty-overlap" || mergeResult.reason === "preflight-unmerged-conflicts") {
@@ -180,10 +190,23 @@ export async function _runMilestoneMergeWithStashRestore(
180
190
  return null;
181
191
  }
182
192
 
183
- async function markMilestoneMergedAndRebuild(s: AutoSession): Promise<void> {
193
+ type GsdMarkdownSnapshot = Map<string, string>;
194
+
195
+ async function markMilestoneMergedAndRebuild(
196
+ s: AutoSession,
197
+ rebuildBasePath: string,
198
+ ignoredProjectionSnapshot: GsdMarkdownSnapshot | null,
199
+ ): Promise<void> {
184
200
  s.milestoneMergedInPhases = true;
201
+ if (hasDirtyGsdMarkdownProjections(rebuildBasePath, ignoredProjectionSnapshot)) {
202
+ logWarning(
203
+ "engine",
204
+ "skipping markdown projection rebuild after milestone merge because restored .gsd edits are dirty",
205
+ );
206
+ return;
207
+ }
208
+
185
209
  try {
186
- const rebuildBasePath = s.originalBasePath || s.canonicalProjectRoot || s.basePath;
187
210
  const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.js");
188
211
  await rebuildMarkdownProjectionsFromDb(rebuildBasePath);
189
212
  } catch (err) {
@@ -194,6 +217,90 @@ async function markMilestoneMergedAndRebuild(s: AutoSession): Promise<void> {
194
217
  }
195
218
  }
196
219
 
220
+ function hasDirtyGsdMarkdownProjections(
221
+ basePath: string,
222
+ ignoredProjectionSnapshot: GsdMarkdownSnapshot | null,
223
+ ): boolean {
224
+ try {
225
+ const output = execFileSync(
226
+ "git",
227
+ ["status", "--porcelain", "-z", "--untracked-files=all", "--", ".gsd"],
228
+ { cwd: basePath, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
229
+ );
230
+ const entries = output.split("\0").filter(Boolean);
231
+ for (let i = 0; i < entries.length; i++) {
232
+ const entry = entries[i];
233
+ if (entry.length <= 3) continue;
234
+ const status = entry.slice(0, 2);
235
+ const path = entry.slice(3);
236
+ if (isGeneratedGsdMarkdownProjection(path)) return true;
237
+ if ((status === "R " || status === "C ") && i + 1 < entries.length) {
238
+ const dest = entries[++i];
239
+ if (isGeneratedGsdMarkdownProjection(dest)) return true;
240
+ }
241
+ }
242
+ } catch (err) {
243
+ void err;
244
+ // Fall through to ignored-file snapshot comparison below.
245
+ }
246
+ return ignoredGsdMarkdownProjectionSnapshotChanged(basePath, ignoredProjectionSnapshot);
247
+ }
248
+
249
+ function isGeneratedGsdMarkdownProjection(path: string): boolean {
250
+ const normalized = path.replace(/\\/g, "/");
251
+ if (normalized === ".gsd/DECISIONS.md") return true;
252
+ if (!normalized.startsWith(".gsd/milestones/") && !normalized.startsWith(".gsd/phases/")) {
253
+ return false;
254
+ }
255
+ return isGeneratedPlanningArtifactFileName(basename(normalized));
256
+ }
257
+
258
+ function isGeneratedPlanningArtifactFileName(fileName: string): boolean {
259
+ if (!fileName.endsWith(".md")) return false;
260
+ const stem = fileName.slice(0, -".md".length).toUpperCase();
261
+ for (const suffix of PLANNING_ARTIFACT_SUFFIXES) {
262
+ if (!stem.endsWith(`-${suffix}`)) continue;
263
+ const idPrefix = stem.slice(0, -suffix.length - 1);
264
+ return /^(?:[MST]\d+|\d{2,})(?:-[A-Z0-9]+)*$/.test(idPrefix);
265
+ }
266
+ return false;
267
+ }
268
+
269
+ function snapshotIgnoredGsdMarkdownProjections(basePath: string): GsdMarkdownSnapshot | null {
270
+ try {
271
+ const output = execFileSync(
272
+ "git",
273
+ ["ls-files", "--others", "--ignored", "--exclude-standard", "-z", "--", ".gsd"],
274
+ { cwd: basePath, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
275
+ );
276
+ const snapshot: GsdMarkdownSnapshot = new Map();
277
+ for (const path of output.split("\0")) {
278
+ if (!isGeneratedGsdMarkdownProjection(path)) continue;
279
+ snapshot.set(path, hashFile(join(basePath, path)));
280
+ }
281
+ return snapshot;
282
+ } catch {
283
+ return null;
284
+ }
285
+ }
286
+
287
+ function hashFile(path: string): string {
288
+ return createHash("sha256").update(readFileSync(path)).digest("hex");
289
+ }
290
+
291
+ function ignoredGsdMarkdownProjectionSnapshotChanged(
292
+ basePath: string,
293
+ before: GsdMarkdownSnapshot | null,
294
+ ): boolean {
295
+ if (!before) return true;
296
+ const after = snapshotIgnoredGsdMarkdownProjections(basePath);
297
+ if (!after || after.size !== before.size) return true;
298
+ for (const [path, hash] of before) {
299
+ if (after.get(path) !== hash) return true;
300
+ }
301
+ return false;
302
+ }
303
+
197
304
  export async function _runMilestoneMergeOnceWithStashRestore(
198
305
  ic: IterationContext,
199
306
  milestoneId: string,
@@ -34,7 +34,8 @@ import {
34
34
  preDispatchHealthGate,
35
35
  recordHealthSnapshot,
36
36
  } from "../doctor-proactive.js";
37
- import { checkResourcesStale, autoWorktreeBranch, mergeMilestoneToMain } from "../auto-worktree.js";
37
+ import { autoWorktreeBranch } from "../auto-worktree-branch-lifecycle.js";
38
+ import { checkResourcesStale } from "../auto-worktree-resource-version.js";
38
39
  import { getSessionLockStatus } from "../session-lock.js";
39
40
  import { resolveUokFlags } from "../uok/flags.js";
40
41
  import { emitJournalEvent as _emitJournalEvent } from "../journal.js";
@@ -49,7 +50,7 @@ import { getPriorSliceCompletionBlocker } from "../dispatch-guard.js";
49
50
  import { GitServiceImpl } from "../git-service.js";
50
51
  import { WorktreeStateProjection } from "../worktree-state-projection.js";
51
52
  import { WorktreeLifecycle } from "../worktree-lifecycle.js";
52
- import { createMilestoneMergeTransaction } from "../milestone-merge-transaction.js";
53
+ import { createDefaultMilestoneMergeTransaction } from "../milestone-merge-transaction.js";
53
54
  import { createWorkspace, scopeMilestone } from "../workspace.js";
54
55
  import { supportsStructuredQuestions } from "../workflow-mcp.js";
55
56
  import { getRegisteredToolSnapshot, getToolBaselineSnapshot } from "../auto-model-selection.js";
@@ -731,7 +732,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
731
732
  return new GitServiceImpl(basePath, gitConfig);
732
733
  },
733
734
  worktreeProjection: new WorktreeStateProjection(),
734
- mergeMilestone: createMilestoneMergeTransaction(mergeMilestoneToMain),
735
+ mergeMilestone: createDefaultMilestoneMergeTransaction(),
735
736
  });
736
737
  }
737
738
 
@@ -440,7 +440,8 @@ export async function runPreDispatch(
440
440
  if (stop) return stop;
441
441
  }
442
442
 
443
- // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
443
+ // PR creation (auto_pr) is handled by the publication handoff in
444
+ // the milestone merge transaction (#2302).
444
445
 
445
446
  deps.invalidateAllCaches();
446
447
 
@@ -551,7 +552,8 @@ export async function runPreDispatch(
551
552
  // #2909 / #5538-followup: preflight stash + always-on postflight pop.
552
553
  const stop = await _runMilestoneMergeOnceWithStashRestore(ic, s.currentMilestoneId);
553
554
  if (stop) return stop;
554
- // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
555
+ // PR creation (auto_pr) is handled by the publication handoff in
556
+ // the milestone merge transaction (#2302).
555
557
  }
556
558
  const unmappedActive = countUnmappedActiveRequirements();
557
559
  const completionStopReason = formatCompletePhaseNextAction(unmappedActive);
@@ -654,7 +656,8 @@ export async function runPreDispatch(
654
656
  // #2909 / #5538-followup: preflight stash + always-on postflight pop.
655
657
  const stop = await _runMilestoneMergeOnceWithStashRestore(ic, s.currentMilestoneId);
656
658
  if (stop) return stop;
657
- // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
659
+ // PR creation (auto_pr) is handled by the publication handoff in
660
+ // the milestone merge transaction (#2302).
658
661
  }
659
662
  deps.sendDesktopNotification(
660
663
  "GSD",
@@ -29,7 +29,7 @@ import type { MinimalModelRegistry } from "../context-budget.js";
29
29
  import { parseUnitId } from "../unit-id.js";
30
30
  import { createCheckpoint, cleanupCheckpoint, rollbackToCheckpoint } from "../safety/git-checkpoint.js";
31
31
  import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
32
- import { getUnitWorkflowDispatchReadinessError } from "../tool-contract.js";
32
+ import { getUnitWorkflowDispatchReadinessErrorForModel } from "../tool-contract.js";
33
33
  import { prepareWorkflowMcpForProject } from "../workflow-mcp-auto-prep.js";
34
34
  import {
35
35
  applyThinkingLevelForModel,
@@ -343,17 +343,13 @@ export async function runUnitPhase(
343
343
  ? `${(s.currentUnitModel as any).provider ?? ""}/${(s.currentUnitModel as any).id ?? ""}`
344
344
  : null;
345
345
 
346
- const compatibilityError = getUnitWorkflowDispatchReadinessError({
347
- provider: s.currentUnitModel?.provider ?? ctx.model?.provider,
346
+ const compatibilityError = getUnitWorkflowDispatchReadinessErrorForModel({
347
+ model: s.currentUnitModel as any,
348
+ fallbackModel: ctx.model,
349
+ getProviderAuthMode: (provider) => ctx.modelRegistry.getProviderAuthMode(provider),
348
350
  projectRoot: s.basePath,
349
351
  surface: "auto-mode",
350
352
  unitType,
351
- authMode: s.currentUnitModel?.provider
352
- ? ctx.modelRegistry.getProviderAuthMode(s.currentUnitModel.provider)
353
- : ctx.model?.provider
354
- ? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider)
355
- : undefined,
356
- baseUrl: (s.currentUnitModel as any)?.baseUrl ?? ctx.model?.baseUrl,
357
353
  activeTools: typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [],
358
354
  });
359
355
  const workflowMcpPrepModel = s.currentUnitModel;
@@ -22,7 +22,7 @@ import {
22
22
  } from "./paths.js";
23
23
  import { milestoneIdToPhaseNum } from "./layout-policy.js";
24
24
  import { parseUnitId } from "./unit-id.js";
25
- import { dirname, join, relative } from "node:path";
25
+ import { basename, dirname, join, relative } from "node:path";
26
26
  import { existsSync } from "node:fs";
27
27
 
28
28
  function resolveMilestoneArtifactPath(
@@ -221,8 +221,17 @@ export function resolveExpectedArtifactPath(
221
221
  ?? resolveProjectSlicePath(base, mid, sid!)
222
222
  ?? resolveSlicePath(base, mid, sid!);
223
223
  if (!slicePath || !tid) return null;
224
- const tasksDir = resolveTasksDir(base, mid, sid!) ?? slicePath;
225
- return join(tasksDir, buildTaskFileName(tid, "SUMMARY"));
224
+ // Legacy layout: slice dirs live under slices/<SID>/ and task summaries
225
+ // live in a tasks/ subdir. Flat-phase layout: slicePath IS the phase dir
226
+ // and task summaries live beside the plan files at the phase root. A
227
+ // tasks/ subdir may still exist in flat-phase for auxiliary task-scoped
228
+ // artifacts (e.g. T01-VERIFY.json gate outputs) — its mere existence must
229
+ // NOT redirect summary resolution into tasks/ (#1208).
230
+ const isLegacySlice = basename(dirname(slicePath)) === "slices";
231
+ const summaryDir = isLegacySlice
232
+ ? (resolveTasksDir(base, mid, sid!) ?? slicePath)
233
+ : slicePath;
234
+ return join(summaryDir, buildTaskFileName(tid, "SUMMARY"));
226
235
  }
227
236
  case "complete-slice": {
228
237
  return resolveSliceArtifactPath(base, mid, sid!, "SUMMARY");
@@ -27,11 +27,11 @@ import {
27
27
  buildRunUatPrompt,
28
28
  buildReplanSlicePrompt,
29
29
  } from "./auto-prompts.js";
30
- import { loadEffectiveGSDPreferences } from "./preferences.js";
30
+ import { loadEffectiveGSDPreferences, renderLanguageDirectiveForPrompt } from "./preferences.js";
31
31
  import type { MinimalModelRegistry } from "./context-budget.js";
32
32
  import { pauseAuto } from "./auto.js";
33
33
  import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
34
- import { getUnitWorkflowDispatchReadinessError } from "./tool-contract.js";
34
+ import { getUnitWorkflowDispatchReadinessErrorForModel } from "./tool-contract.js";
35
35
 
36
36
  export function parseDirectDispatchPhase(raw: string): { phase: string; milestoneId?: string } {
37
37
  const tokens = raw.trim().split(/\s+/).filter(Boolean);
@@ -266,13 +266,12 @@ export async function dispatchDirectPhase(
266
266
  return;
267
267
  }
268
268
 
269
- const compatibilityError = getUnitWorkflowDispatchReadinessError({
270
- provider: ctx.model?.provider,
269
+ const compatibilityError = getUnitWorkflowDispatchReadinessErrorForModel({
270
+ model: ctx.model,
271
+ getProviderAuthMode: (provider) => ctx.modelRegistry.getProviderAuthMode(provider),
271
272
  projectRoot,
272
273
  surface: "direct phase dispatch",
273
274
  unitType,
274
- authMode: ctx.model?.provider ? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider) : undefined,
275
- baseUrl: ctx.model?.baseUrl,
276
275
  activeTools: typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [],
277
276
  });
278
277
  if (compatibilityError) {
@@ -287,8 +286,15 @@ export async function dispatchDirectPhase(
287
286
  ctx.ui.notify("Session creation cancelled.", "warning");
288
287
  return;
289
288
  }
289
+ // Inject the configured response language into the dispatched prompt content
290
+ // — the new session's system prompt does not carry the preferences block, so
291
+ // the language setting would otherwise never reach the unit (#1210).
292
+ const languageDirective = renderLanguageDirectiveForPrompt(
293
+ loadEffectiveGSDPreferences(dispatchBase)?.preferences,
294
+ );
295
+ const dispatchContent = languageDirective ? `${languageDirective}\n\n${prompt}` : prompt;
290
296
  pi.sendMessage(
291
- { customType: "gsd-dispatch", content: prompt, display: false },
297
+ { customType: "gsd-dispatch", content: dispatchContent, display: false },
292
298
  { triggerTurn: true },
293
299
  );
294
300
  }
@@ -14,6 +14,7 @@
14
14
 
15
15
  import type { GSDState, TaskIO } from "./types.js";
16
16
  import type { GSDPreferences } from "./preferences.js";
17
+ import { renderLanguageDirectiveForPrompt } from "./preferences.js";
17
18
  import type { MinimalModelRegistry } from "./context-budget.js";
18
19
  import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
19
20
  import { getUatBrowserToolSupportError, type UatType } from "./uat-policy.js";
@@ -1834,6 +1835,21 @@ export const DISPATCH_RULES: DispatchRule[] = [
1834
1835
 
1835
1836
  import { getRegistry } from "./rule-registry.js";
1836
1837
 
1838
+ /**
1839
+ * Prepend the configured response-language directive to a dispatched unit
1840
+ * prompt so auto-execution units respond in the language set in PREFERENCES.md
1841
+ * (#1210). No-op for non-dispatch actions or when no language is configured.
1842
+ */
1843
+ function applyLanguageDirectiveToDispatch(
1844
+ action: DispatchAction,
1845
+ prefs: GSDPreferences | undefined,
1846
+ ): DispatchAction {
1847
+ if (action.action !== "dispatch" || !action.prompt) return action;
1848
+ const directive = renderLanguageDirectiveForPrompt(prefs);
1849
+ if (!directive) return action;
1850
+ return { ...action, prompt: `${directive}\n\n${action.prompt}` };
1851
+ }
1852
+
1837
1853
  // ─── Resolver ─────────────────────────────────────────────────────────────
1838
1854
 
1839
1855
  /**
@@ -1896,7 +1912,7 @@ export async function resolveDispatch(
1896
1912
  level: "error",
1897
1913
  };
1898
1914
  }
1899
- return action;
1915
+ return applyLanguageDirectiveToDispatch(action, ctx.prefs);
1900
1916
  } catch (err) {
1901
1917
  // Registry not initialized — fall back to inline loop
1902
1918
  logWarning("dispatch", `registry dispatch failed, falling back to inline rules: ${err instanceof Error ? err.message : String(err)}`);
@@ -1918,7 +1934,7 @@ export async function resolveDispatch(
1918
1934
  matchedRule: rule.name,
1919
1935
  };
1920
1936
  }
1921
- return action;
1937
+ return applyLanguageDirectiveToDispatch(action, ctx.prefs);
1922
1938
  }
1923
1939
  }
1924
1940
 
@@ -234,12 +234,56 @@ export function refreshRecoveryDbForArtifact(
234
234
  }
235
235
 
236
236
  if (!isClosedStatus(task.status)) {
237
- return {
238
- ok: false,
239
- fatal: true,
240
- reason: "execute-task-artifact-db-mismatch",
241
- message: `Stuck recovery found execute-task ${unitId} artifacts, but the DB task status is still '${task.status}' after refresh.`,
242
- };
237
+ // The artifact was already confirmed on disk by verifyExpectedArtifact
238
+ // upstream (Gate 1 accepts a checked disk checkbox as proof of completion),
239
+ // but the DB task row is still open. A bare refreshWorkflowDatabaseFromDisk
240
+ // never promotes the disk checkbox into task status (the checkbox is
241
+ // rendered *from* the DB, never *into* it), so this divergence can never
242
+ // self-heal. Promote the task to align the DB with disk instead of failing
243
+ // shut — otherwise the lowest-pending derivation re-picks the same task
244
+ // forever and execute-task hard-stops with "state did not advance" (#1204).
245
+ // Mirrors the promotion pattern used by the context-exhaustion and
246
+ // reactive-execute-blocker recovery paths.
247
+ const ts = new Date().toISOString();
248
+ // Only the DB promotion is load-bearing: if it throws, nothing advanced
249
+ // and failing shut is correct. The plan checkbox rewrite and cache clears
250
+ // are best-effort follow-ups — a throw there must NOT abort recovery, or
251
+ // the DB is left complete without ever emitting the stuck-artifact-recovery
252
+ // event (#1221), stranding worktree reconciliation.
253
+ try {
254
+ updateTaskStatus(mid, sid, tid, "complete", ts);
255
+ } catch (e) {
256
+ return {
257
+ ok: false,
258
+ fatal: true,
259
+ reason: "execute-task-artifact-db-promote-failed",
260
+ message: `Stuck recovery found execute-task ${unitId} artifacts, but promoting the DB task status from '${task.status}' failed: ${getErrorMessage(e)}`,
261
+ };
262
+ }
263
+ try {
264
+ const artifactBase = resolveArtifactVerificationBase(unitId, basePath);
265
+ const planPath = resolveExpectedArtifactPath("plan-slice", `${mid}/${sid}`, artifactBase);
266
+ if (planPath && existsSync(planPath)) {
267
+ const planContent = readFileSync(planPath, "utf-8");
268
+ const updatedPlan = planContent.replace(
269
+ new RegExp(`^(\\s*-\\s+)\\[ \\]\\s+\\*\\*${tid}:`, "m"),
270
+ `$1[x] **${tid}:`,
271
+ );
272
+ if (updatedPlan !== planContent) {
273
+ atomicWriteSync(planPath, updatedPlan);
274
+ }
275
+ }
276
+ clearPathCache();
277
+ clearParseCache();
278
+ } catch (e) {
279
+ logWarning("recovery", `stuck-artifact plan checkbox sync failed after DB promotion of ${unitId}: ${getErrorMessage(e)}`);
280
+ }
281
+ // Append event so worktree reconciliation can replay this recovery completion.
282
+ try {
283
+ appendEvent(basePath, { cmd: "complete-task", params: { milestoneId: mid, sliceId: sid, taskId: tid }, ts, actor: "system", trigger_reason: "stuck-artifact-recovery" });
284
+ } catch (e) {
285
+ logWarning("recovery", `appendEvent failed for stuck-artifact task promotion: ${getErrorMessage(e)}`);
286
+ }
243
287
  }
244
288
 
245
289
  return { ok: true };
@@ -63,9 +63,11 @@ import {
63
63
  detectWorktreeName,
64
64
  setActiveMilestoneId,
65
65
  } from "./worktree.js";
66
- import { getAutoWorktreePath, isInAutoWorktree } from "./auto-worktree.js";
66
+ import { isInAutoWorktree } from "./auto-worktree-entry.js";
67
+ import { getAutoWorktreePath } from "./auto-worktree-path-resolution.js";
67
68
  import { checkoutBranchWithStashGuard } from "./worktree-git-recovery.js";
68
- import { readResourceVersion, cleanStaleRuntimeUnits } from "./auto-worktree.js";
69
+ import { cleanStaleRuntimeUnits } from "./auto-worktree-runtime-cleanup.js";
70
+ import { readResourceVersion } from "./auto-worktree-resource-version.js";
69
71
  import { worktreePath as getWorktreeDir, isInsideWorktreesDir } from "./worktree-manager.js";
70
72
  import { emitWorktreeOrphaned } from "./worktree-telemetry.js";
71
73
  import { queryJournal } from "./journal.js";
@@ -1813,7 +1815,7 @@ export async function bootstrapAutoSession(
1813
1815
 
1814
1816
  // Snapshot installed skills
1815
1817
  if (resolveSkillDiscoveryMode(base) !== "off") {
1816
- snapshotSkills();
1818
+ snapshotSkills({ cwd: s.basePath });
1817
1819
  }
1818
1820
 
1819
1821
  setAutoActiveStatus(ctx, s.stepMode ? "next" : "auto");