@opengsd/gsd-pi 1.5.0 → 1.6.0

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 (499) 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/browser-tools/engine/managed-gsd-browser.js +114 -36
  5. package/dist/resources/extensions/gsd/activity-log.js +1 -1
  6. package/dist/resources/extensions/gsd/auto/closeout.js +97 -5
  7. package/dist/resources/extensions/gsd/auto/orchestrator.js +20 -13
  8. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +6 -3
  9. package/dist/resources/extensions/gsd/auto/unit-phase.js +5 -9
  10. package/dist/resources/extensions/gsd/auto-artifact-paths.js +14 -5
  11. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -7
  12. package/dist/resources/extensions/gsd/auto-dispatch.js +69 -17
  13. package/dist/resources/extensions/gsd/auto-model-selection.js +28 -1
  14. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
  15. package/dist/resources/extensions/gsd/auto-prompts.js +29 -117
  16. package/dist/resources/extensions/gsd/auto-recovery.js +50 -6
  17. package/dist/resources/extensions/gsd/auto-start.js +57 -33
  18. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +12 -2
  19. package/dist/resources/extensions/gsd/auto-timers.js +9 -2
  20. package/dist/resources/extensions/gsd/auto-worktree-branch-lifecycle.js +189 -0
  21. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +133 -0
  22. package/dist/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.js +35 -0
  23. package/dist/resources/extensions/gsd/auto-worktree-creation.js +130 -0
  24. package/dist/resources/extensions/gsd/auto-worktree-entry.js +118 -0
  25. package/dist/resources/extensions/gsd/auto-worktree-merge-already-merged.js +98 -0
  26. package/dist/resources/extensions/gsd/auto-worktree-merge-branch-head.js +52 -0
  27. package/dist/resources/extensions/gsd/auto-worktree-merge-cleanup.js +87 -0
  28. package/dist/resources/extensions/gsd/auto-worktree-merge-code-changes.js +46 -0
  29. package/dist/resources/extensions/gsd/auto-worktree-merge-db-ready.js +68 -0
  30. package/dist/resources/extensions/gsd/auto-worktree-merge-integration-branch.js +51 -0
  31. package/dist/resources/extensions/gsd/auto-worktree-merge-message.js +106 -0
  32. package/dist/resources/extensions/gsd/auto-worktree-merge-pre-teardown.js +64 -0
  33. package/dist/resources/extensions/gsd/auto-worktree-merge-stash.js +168 -0
  34. package/dist/resources/extensions/gsd/auto-worktree-merge.js +302 -0
  35. package/dist/resources/extensions/gsd/auto-worktree-milestone-shelter.js +119 -0
  36. package/dist/resources/extensions/gsd/auto-worktree-path-resolution.js +5 -0
  37. package/dist/resources/extensions/gsd/auto-worktree-path-utils.js +5 -0
  38. package/dist/resources/extensions/gsd/auto-worktree-resource-version.js +41 -0
  39. package/dist/resources/extensions/gsd/auto-worktree-runtime-cleanup.js +99 -0
  40. package/dist/resources/extensions/gsd/auto-worktree-session-registry.js +57 -0
  41. package/dist/resources/extensions/gsd/auto-worktree-sync.js +249 -0
  42. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +120 -0
  43. package/dist/resources/extensions/gsd/auto-worktree.js +20 -2073
  44. package/dist/resources/extensions/gsd/auto.js +106 -34
  45. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -1
  46. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +20 -2
  47. package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
  48. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +185 -27
  49. package/dist/resources/extensions/gsd/codebase-generator.js +7 -1
  50. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  51. package/dist/resources/extensions/gsd/commands-workflow-templates.js +3 -3
  52. package/dist/resources/extensions/gsd/compat/compat-marker.js +44 -0
  53. package/dist/resources/extensions/gsd/config-overlay.js +7 -2
  54. package/dist/resources/extensions/gsd/db/engine.js +33 -0
  55. package/dist/resources/extensions/gsd/db/queries.js +9 -9
  56. package/dist/resources/extensions/gsd/db/writers/cascades.js +20 -2
  57. package/dist/resources/extensions/gsd/db-adapter.js +30 -3
  58. package/dist/resources/extensions/gsd/docs/preferences-reference.md +3 -3
  59. package/dist/resources/extensions/gsd/doctor-engine-checks.js +93 -11
  60. package/dist/resources/extensions/gsd/flat-phase-migration.js +32 -3
  61. package/dist/resources/extensions/gsd/forensics.js +1 -1
  62. package/dist/resources/extensions/gsd/git-conflict-resolve.js +2 -2
  63. package/dist/resources/extensions/gsd/git-service.js +45 -0
  64. package/dist/resources/extensions/gsd/gsd-db.js +23 -11
  65. package/dist/resources/extensions/gsd/guided-flow.js +22 -17
  66. package/dist/resources/extensions/gsd/journal.js +1 -1
  67. package/dist/resources/extensions/gsd/markdown-renderer.js +34 -79
  68. package/dist/resources/extensions/gsd/md-importer.js +89 -23
  69. package/dist/resources/extensions/gsd/metrics.js +2 -2
  70. package/dist/resources/extensions/gsd/migration-auto-check.js +30 -3
  71. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +11 -0
  72. package/dist/resources/extensions/gsd/milestone-settlement.js +1 -1
  73. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  74. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -1
  75. package/dist/resources/extensions/gsd/paths.js +87 -52
  76. package/dist/resources/extensions/gsd/post-unit-hooks.js +27 -0
  77. package/dist/resources/extensions/gsd/preferences-models.js +66 -15
  78. package/dist/resources/extensions/gsd/preferences-skills.js +10 -16
  79. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  80. package/dist/resources/extensions/gsd/preferences-validation.js +148 -10
  81. package/dist/resources/extensions/gsd/preferences.js +20 -0
  82. package/dist/resources/extensions/gsd/prompts/system.md +6 -6
  83. package/dist/resources/extensions/gsd/quick.js +12 -3
  84. package/dist/resources/extensions/gsd/rule-registry.js +106 -10
  85. package/dist/resources/extensions/gsd/skill-discovery.js +36 -23
  86. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +2 -1
  87. package/dist/resources/extensions/gsd/state/derive/from-db.js +88 -153
  88. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +1 -10
  89. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +3 -24
  90. package/dist/resources/extensions/gsd/state-reconciliation/index.js +10 -0
  91. package/dist/resources/extensions/gsd/tool-contract.js +14 -0
  92. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -5
  93. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +16 -10
  94. package/dist/resources/extensions/gsd/tools/reopen-slice.js +5 -0
  95. package/dist/resources/extensions/gsd/tools/reopen-task.js +13 -5
  96. package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -8
  97. package/dist/resources/extensions/gsd/uat-dispatch.js +94 -0
  98. package/dist/resources/extensions/gsd/unit-registry.js +12 -2
  99. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +1 -1
  100. package/dist/resources/extensions/gsd/uok/audit-toggle.js +31 -2
  101. package/dist/resources/extensions/gsd/uok/audit.js +3 -0
  102. package/dist/resources/extensions/gsd/uok/gate-runner.js +22 -30
  103. package/dist/resources/extensions/gsd/uok/gitops.js +18 -15
  104. package/dist/resources/extensions/gsd/uok/kernel.js +120 -46
  105. package/dist/resources/extensions/gsd/uok/model-policy.js +17 -14
  106. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -1
  107. package/dist/resources/extensions/gsd/workflow-event-ledger.js +1 -1
  108. package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
  109. package/dist/resources/extensions/gsd/workflow-projections.js +9 -26
  110. package/dist/resources/extensions/gsd/workspace-git-preflight.js +2 -2
  111. package/dist/resources/extensions/gsd/workspace.js +5 -14
  112. package/dist/resources/extensions/gsd/worktree-command.js +1 -1
  113. package/dist/resources/extensions/gsd/worktree-lifecycle.js +14 -9
  114. package/dist/resources/extensions/gsd/worktree-reentry.js +2 -1
  115. package/dist/resources/extensions/shared/gsd-browser-cli.js +29 -0
  116. package/dist/resources/extensions/shared/interview-ui.js +62 -9
  117. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  118. package/dist/web/standalone/.next/BUILD_ID +1 -1
  119. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  120. package/dist/web/standalone/.next/build-manifest.json +2 -2
  121. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  122. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  142. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  146. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  156. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  158. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  164. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  168. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  170. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/index.html +1 -1
  173. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  174. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  176. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  177. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  178. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  179. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  180. package/dist/web/standalone/.next/server/chunks/{1128.js → 1991.js} +1 -1
  181. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  182. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  184. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  185. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  186. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  187. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  188. package/dist/worktree-cli-create.d.ts +10 -0
  189. package/dist/worktree-cli-create.js +11 -0
  190. package/dist/worktree-cli-format.d.ts +12 -0
  191. package/dist/worktree-cli-format.js +38 -0
  192. package/dist/worktree-cli-plan.d.ts +16 -0
  193. package/dist/worktree-cli-plan.js +19 -0
  194. package/dist/worktree-cli-session.d.ts +13 -0
  195. package/dist/worktree-cli-session.js +18 -0
  196. package/dist/worktree-cli-status.d.ts +35 -0
  197. package/dist/worktree-cli-status.js +54 -0
  198. package/dist/worktree-cli.d.ts +1 -16
  199. package/dist/worktree-cli.js +28 -122
  200. package/integrations/hermes/open_gsd_hermes/gsd_client.py +25 -36
  201. package/integrations/hermes/pyproject.toml +1 -1
  202. package/integrations/hermes/tests/test_gsd_client_timeout.py +4 -4
  203. package/package.json +6 -6
  204. package/packages/cloud-mcp-gateway/package.json +2 -2
  205. package/packages/contracts/package.json +1 -1
  206. package/packages/daemon/dist/orchestrator-agent.d.ts +21 -0
  207. package/packages/daemon/dist/orchestrator-agent.d.ts.map +1 -0
  208. package/packages/daemon/dist/orchestrator-agent.js +113 -0
  209. package/packages/daemon/dist/orchestrator-agent.js.map +1 -0
  210. package/packages/daemon/dist/orchestrator-tools.d.ts +12 -0
  211. package/packages/daemon/dist/orchestrator-tools.d.ts.map +1 -0
  212. package/packages/daemon/dist/orchestrator-tools.js +137 -0
  213. package/packages/daemon/dist/orchestrator-tools.js.map +1 -0
  214. package/packages/daemon/dist/orchestrator.d.ts +4 -56
  215. package/packages/daemon/dist/orchestrator.d.ts.map +1 -1
  216. package/packages/daemon/dist/orchestrator.js +13 -303
  217. package/packages/daemon/dist/orchestrator.js.map +1 -1
  218. package/packages/daemon/dist/orchestrator.test.js +11 -1
  219. package/packages/daemon/dist/orchestrator.test.js.map +1 -1
  220. package/packages/daemon/package.json +4 -4
  221. package/packages/gsd-agent-core/dist/export-html/template.js +53 -4
  222. package/packages/gsd-agent-core/package.json +5 -5
  223. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  224. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +3 -2
  225. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  226. package/packages/gsd-agent-modes/package.json +7 -7
  227. package/packages/mcp-server/package.json +4 -4
  228. package/packages/native/package.json +1 -1
  229. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  230. package/packages/pi-agent-core/dist/agent-loop.js +14 -9
  231. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  232. package/packages/pi-agent-core/package.json +1 -1
  233. package/packages/pi-ai/dist/index.d.ts +1 -0
  234. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  235. package/packages/pi-ai/dist/index.js +1 -0
  236. package/packages/pi-ai/dist/index.js.map +1 -1
  237. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  238. package/packages/pi-ai/dist/providers/transform-messages.js +7 -3
  239. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  240. package/packages/pi-ai/dist/tool-result-content.d.ts +3 -0
  241. package/packages/pi-ai/dist/tool-result-content.d.ts.map +1 -0
  242. package/packages/pi-ai/dist/tool-result-content.js +62 -0
  243. package/packages/pi-ai/dist/tool-result-content.js.map +1 -0
  244. package/packages/pi-ai/dist/types.d.ts +8 -20
  245. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  246. package/packages/pi-ai/dist/types.js.map +1 -1
  247. package/packages/pi-ai/package.json +1 -1
  248. package/packages/pi-coding-agent/dist/core/package-manager.d.ts +9 -0
  249. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/package-manager.js +74 -53
  251. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +6 -0
  253. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  254. package/packages/pi-coding-agent/dist/core/resource-loader.js +30 -2
  255. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  256. package/packages/pi-coding-agent/dist/core/skill-directories.d.ts +66 -0
  257. package/packages/pi-coding-agent/dist/core/skill-directories.d.ts.map +1 -0
  258. package/packages/pi-coding-agent/dist/core/skill-directories.js +138 -0
  259. package/packages/pi-coding-agent/dist/core/skill-directories.js.map +1 -0
  260. package/packages/pi-coding-agent/dist/core/skills.d.ts +4 -1
  261. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  262. package/packages/pi-coding-agent/dist/core/skills.js +4 -1
  263. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  264. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  265. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/index.js +1 -0
  267. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  268. package/packages/pi-coding-agent/package.json +7 -7
  269. package/packages/pi-tui/package.json +2 -2
  270. package/packages/rpc-client/package.json +2 -2
  271. package/pkg/dist/core/export-html/template.js +53 -4
  272. package/pkg/package.json +1 -1
  273. package/src/resources/extensions/ask-user-questions.ts +1 -1
  274. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +146 -33
  275. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +25 -0
  276. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +93 -0
  277. package/src/resources/extensions/gsd/activity-log.ts +1 -1
  278. package/src/resources/extensions/gsd/auto/closeout.ts +114 -7
  279. package/src/resources/extensions/gsd/auto/orchestrator.ts +21 -14
  280. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +6 -3
  281. package/src/resources/extensions/gsd/auto/unit-phase.ts +5 -9
  282. package/src/resources/extensions/gsd/auto-artifact-paths.ts +14 -4
  283. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +13 -7
  284. package/src/resources/extensions/gsd/auto-dispatch.ts +77 -16
  285. package/src/resources/extensions/gsd/auto-model-selection.ts +33 -1
  286. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -2
  287. package/src/resources/extensions/gsd/auto-prompts.ts +53 -113
  288. package/src/resources/extensions/gsd/auto-recovery.ts +50 -6
  289. package/src/resources/extensions/gsd/auto-start.ts +62 -31
  290. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -2
  291. package/src/resources/extensions/gsd/auto-timers.ts +9 -2
  292. package/src/resources/extensions/gsd/auto-worktree-branch-lifecycle.ts +237 -0
  293. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +166 -0
  294. package/src/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.ts +37 -0
  295. package/src/resources/extensions/gsd/auto-worktree-creation.ts +171 -0
  296. package/src/resources/extensions/gsd/auto-worktree-entry.ts +154 -0
  297. package/src/resources/extensions/gsd/auto-worktree-merge-already-merged.ts +161 -0
  298. package/src/resources/extensions/gsd/auto-worktree-merge-branch-head.ts +83 -0
  299. package/src/resources/extensions/gsd/auto-worktree-merge-cleanup.ts +132 -0
  300. package/src/resources/extensions/gsd/auto-worktree-merge-code-changes.ts +71 -0
  301. package/src/resources/extensions/gsd/auto-worktree-merge-db-ready.ts +112 -0
  302. package/src/resources/extensions/gsd/auto-worktree-merge-integration-branch.ts +99 -0
  303. package/src/resources/extensions/gsd/auto-worktree-merge-message.ts +166 -0
  304. package/src/resources/extensions/gsd/auto-worktree-merge-pre-teardown.ts +93 -0
  305. package/src/resources/extensions/gsd/auto-worktree-merge-stash.ts +213 -0
  306. package/src/resources/extensions/gsd/auto-worktree-merge.ts +391 -0
  307. package/src/resources/extensions/gsd/auto-worktree-milestone-shelter.ts +159 -0
  308. package/src/resources/extensions/gsd/auto-worktree-path-resolution.ts +6 -0
  309. package/src/resources/extensions/gsd/auto-worktree-path-utils.ts +10 -0
  310. package/src/resources/extensions/gsd/auto-worktree-resource-version.ts +44 -0
  311. package/src/resources/extensions/gsd/auto-worktree-runtime-cleanup.ts +119 -0
  312. package/src/resources/extensions/gsd/auto-worktree-session-registry.ts +71 -0
  313. package/src/resources/extensions/gsd/auto-worktree-sync.ts +370 -0
  314. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +161 -0
  315. package/src/resources/extensions/gsd/auto-worktree.ts +69 -2429
  316. package/src/resources/extensions/gsd/auto.ts +114 -47
  317. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -1
  318. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +20 -2
  319. package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
  320. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +218 -27
  321. package/src/resources/extensions/gsd/codebase-generator.ts +7 -1
  322. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  323. package/src/resources/extensions/gsd/commands-workflow-templates.ts +3 -3
  324. package/src/resources/extensions/gsd/compat/compat-marker.ts +47 -0
  325. package/src/resources/extensions/gsd/config-overlay.ts +7 -1
  326. package/src/resources/extensions/gsd/db/engine.ts +36 -0
  327. package/src/resources/extensions/gsd/db/queries.ts +9 -9
  328. package/src/resources/extensions/gsd/db/writers/cascades.ts +23 -1
  329. package/src/resources/extensions/gsd/db-adapter.ts +29 -3
  330. package/src/resources/extensions/gsd/docs/preferences-reference.md +3 -3
  331. package/src/resources/extensions/gsd/doctor-engine-checks.ts +109 -10
  332. package/src/resources/extensions/gsd/flat-phase-migration.ts +34 -3
  333. package/src/resources/extensions/gsd/forensics.ts +1 -1
  334. package/src/resources/extensions/gsd/git-conflict-resolve.ts +2 -2
  335. package/src/resources/extensions/gsd/git-service.ts +53 -0
  336. package/src/resources/extensions/gsd/gsd-db.ts +33 -11
  337. package/src/resources/extensions/gsd/guided-flow.ts +26 -18
  338. package/src/resources/extensions/gsd/journal.ts +1 -1
  339. package/src/resources/extensions/gsd/markdown-renderer.ts +52 -91
  340. package/src/resources/extensions/gsd/md-importer.ts +93 -22
  341. package/src/resources/extensions/gsd/metrics.ts +2 -2
  342. package/src/resources/extensions/gsd/migration-auto-check.ts +32 -3
  343. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +15 -0
  344. package/src/resources/extensions/gsd/milestone-settlement.ts +1 -1
  345. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  346. package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -1
  347. package/src/resources/extensions/gsd/paths.ts +108 -51
  348. package/src/resources/extensions/gsd/post-unit-hooks.ts +32 -0
  349. package/src/resources/extensions/gsd/preferences-models.ts +74 -20
  350. package/src/resources/extensions/gsd/preferences-skills.ts +10 -16
  351. package/src/resources/extensions/gsd/preferences-types.ts +54 -1
  352. package/src/resources/extensions/gsd/preferences-validation.ts +146 -9
  353. package/src/resources/extensions/gsd/preferences.ts +20 -0
  354. package/src/resources/extensions/gsd/prompts/system.md +6 -6
  355. package/src/resources/extensions/gsd/quick.ts +11 -3
  356. package/src/resources/extensions/gsd/rule-registry.ts +111 -9
  357. package/src/resources/extensions/gsd/skill-discovery.ts +47 -23
  358. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -1
  359. package/src/resources/extensions/gsd/state/derive/from-db.ts +201 -157
  360. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +1 -9
  361. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +2 -22
  362. package/src/resources/extensions/gsd/state-reconciliation/index.ts +14 -0
  363. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +169 -1
  364. package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +2 -1
  365. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +41 -2
  366. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +48 -1
  367. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +57 -0
  368. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +1 -1
  369. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +29 -1
  370. package/src/resources/extensions/gsd/tests/auto-timeout-recovery-supervisor-inflight-guard.test.ts +159 -0
  371. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +2 -1
  372. package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +1 -1
  373. package/src/resources/extensions/gsd/tests/auto-worktree-merge-already-merged.test.ts +177 -0
  374. package/src/resources/extensions/gsd/tests/auto-worktree-merge-branch-head.test.ts +118 -0
  375. package/src/resources/extensions/gsd/tests/auto-worktree-merge-cleanup.test.ts +115 -0
  376. package/src/resources/extensions/gsd/tests/auto-worktree-merge-code-changes.test.ts +76 -0
  377. package/src/resources/extensions/gsd/tests/auto-worktree-merge-db-ready.test.ts +140 -0
  378. package/src/resources/extensions/gsd/tests/auto-worktree-merge-integration-branch.test.ts +123 -0
  379. package/src/resources/extensions/gsd/tests/auto-worktree-merge-message.test.ts +114 -0
  380. package/src/resources/extensions/gsd/tests/auto-worktree-merge-pre-teardown.test.ts +84 -0
  381. package/src/resources/extensions/gsd/tests/auto-worktree-merge-stash.test.ts +70 -0
  382. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-shelter.test.ts +52 -0
  383. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +6 -6
  384. package/src/resources/extensions/gsd/tests/auto-worktree-resource-version.test.ts +59 -0
  385. package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +3 -1
  386. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  387. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +3 -1
  388. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +85 -0
  389. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +45 -0
  390. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +1 -1
  391. package/src/resources/extensions/gsd/tests/db-adapter.test.ts +39 -0
  392. package/src/resources/extensions/gsd/tests/db-writable-probe.test.ts +66 -0
  393. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -0
  394. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +174 -0
  395. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +1 -1
  396. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +71 -1
  397. package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +46 -1
  398. package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +72 -32
  399. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +40 -0
  400. package/src/resources/extensions/gsd/tests/import-completion-lost-update.test.ts +196 -0
  401. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +4 -6
  402. package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +2 -1
  403. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +3 -3
  404. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +7 -8
  405. package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +2 -5
  406. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +76 -0
  407. package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +1 -1
  408. package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +1 -1
  409. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +2 -1
  410. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +5 -7
  411. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +88 -1
  412. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +2 -4
  413. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -15
  414. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +1 -1
  415. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +1 -1
  416. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +1 -1
  417. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +91 -0
  418. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +2 -1
  419. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +439 -0
  420. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +24 -0
  421. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +1 -1
  422. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -3
  423. package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +1 -1
  424. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +0 -1
  425. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +269 -0
  426. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +8 -1
  427. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +1 -4
  428. package/src/resources/extensions/gsd/tests/preferences.test.ts +19 -0
  429. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +5 -0
  430. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +54 -0
  431. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +49 -1
  432. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +52 -0
  433. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +95 -1
  434. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
  435. package/src/resources/extensions/gsd/tests/sibling-model-fallbacks.test.ts +189 -0
  436. package/src/resources/extensions/gsd/tests/single-field-model-thinking.test.ts +156 -0
  437. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +46 -0
  438. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +6 -1
  439. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -5
  440. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +32 -0
  441. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +2 -1
  442. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +2 -1
  443. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +1 -1
  444. package/src/resources/extensions/gsd/tests/supervisor-model-swap-inflight-guard.test.ts +181 -0
  445. package/src/resources/extensions/gsd/tests/supervisor-model-swap-thinking-clamp.test.ts +122 -0
  446. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +1 -1
  447. package/src/resources/extensions/gsd/tests/system-flat-phase-layout.test.ts +33 -0
  448. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +4 -4
  449. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +2 -1
  450. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +4 -4
  451. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +196 -0
  452. package/src/resources/extensions/gsd/tests/uat-dispatch.test.ts +211 -0
  453. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +1 -1
  454. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +26 -1
  455. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +39 -0
  456. package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +226 -2
  457. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +6 -0
  458. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +213 -2
  459. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -1
  460. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +1 -1
  461. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +1 -3
  462. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +1 -1
  463. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +1 -1
  464. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +1 -1
  465. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +1 -1
  466. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +2 -1
  467. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +5 -2
  468. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +1 -1
  469. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +1 -1
  470. package/src/resources/extensions/gsd/tool-contract.ts +29 -0
  471. package/src/resources/extensions/gsd/tools/complete-milestone.ts +9 -5
  472. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +19 -8
  473. package/src/resources/extensions/gsd/tools/reopen-slice.ts +5 -0
  474. package/src/resources/extensions/gsd/tools/reopen-task.ts +13 -5
  475. package/src/resources/extensions/gsd/tools/validate-milestone.ts +13 -9
  476. package/src/resources/extensions/gsd/types.ts +23 -4
  477. package/src/resources/extensions/gsd/uat-dispatch.ts +176 -0
  478. package/src/resources/extensions/gsd/unit-registry.ts +16 -2
  479. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +1 -1
  480. package/src/resources/extensions/gsd/uok/audit-toggle.ts +32 -2
  481. package/src/resources/extensions/gsd/uok/audit.ts +2 -0
  482. package/src/resources/extensions/gsd/uok/gate-runner.ts +26 -36
  483. package/src/resources/extensions/gsd/uok/gitops.ts +21 -18
  484. package/src/resources/extensions/gsd/uok/kernel.ts +169 -48
  485. package/src/resources/extensions/gsd/uok/model-policy.ts +20 -17
  486. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -1
  487. package/src/resources/extensions/gsd/workflow-event-ledger.ts +1 -1
  488. package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
  489. package/src/resources/extensions/gsd/workflow-projections.ts +9 -24
  490. package/src/resources/extensions/gsd/workspace-git-preflight.ts +2 -2
  491. package/src/resources/extensions/gsd/workspace.ts +5 -21
  492. package/src/resources/extensions/gsd/worktree-command.ts +1 -1
  493. package/src/resources/extensions/gsd/worktree-lifecycle.ts +19 -15
  494. package/src/resources/extensions/gsd/worktree-reentry.ts +2 -1
  495. package/src/resources/extensions/shared/gsd-browser-cli.ts +29 -0
  496. package/src/resources/extensions/shared/interview-ui.ts +58 -11
  497. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +32 -0
  498. /package/dist/web/standalone/.next/static/{bCg3aYrFN1DKZr2dqgE7L → 6xYMOzxVhsQgryneJ5KRc}/_buildManifest.js +0 -0
  499. /package/dist/web/standalone/.next/static/{bCg3aYrFN1DKZr2dqgE7L → 6xYMOzxVhsQgryneJ5KRc}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { mkdtempSync, mkdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
3
+ import { mkdtempSync, mkdirSync, realpathSync, rmSync, utimesSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
 
@@ -360,6 +360,174 @@ test("canonical worktree + project-root legacy dir produces legacy filename (#bu
360
360
  }
361
361
  });
362
362
 
363
+ // ── cursor[bot] 3523932401: bare milestone id must not match a team-suffix ────
364
+ //
365
+ // A bare milestone id (M001, no team-mode suffix) resolves its phase dir by
366
+ // scanning phases/NN-*. Before the guard (commit 8f45bf3),
367
+ // phaseDirMatchesMilestoneId returned true for ANY same-number dir, so a
368
+ // leftover team-mode projection (phases/01-<6char>-.../, from a prior
369
+ // team-suffixed run) matched the bare id too. When that stale dir carried a
370
+ // newer mtime, pickPreferredPhaseDir selected it over the real title dir and
371
+ // resolved the ROADMAP into a directory that has no ROADMAP — the file-not-found
372
+ // retry loop. The guard (slugLooksLikeTeamSuffixProjection) rejects
373
+ // team-suffix-looking slugs for bare ids in the primary pass; the suffixed
374
+ // projection stays available only as a fallback when the primary pass finds
375
+ // nothing (#1195, guarded by the second test below).
376
+
377
+ test("bare milestone id prefers the real title dir over a newer team-suffix projection (cursor 3523932401)", () => {
378
+ const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-bare-teamsuffix-")));
379
+ try {
380
+ const phasesDir = join(root, ".gsd", "phases");
381
+ // Intended flat-phase dir for the bare id: 01-<title-slug>/ with the ROADMAP.
382
+ const intendedDir = join(phasesDir, "01-clean-continuation");
383
+ mkdirSync(intendedDir, { recursive: true });
384
+ writeFileSync(join(intendedDir, "01-ROADMAP.md"), "# roadmap\n");
385
+
386
+ // Leftover team-mode projection: 01-<6char>-.../ with NO ROADMAP, made
387
+ // NEWER so an mtime tiebreak would wrongly prefer it without the guard.
388
+ const staleDir = join(phasesDir, "01-re4q3k-old-team-projection");
389
+ mkdirSync(staleDir, { recursive: true });
390
+ const newer = new Date(Date.now() + 60_000);
391
+ const older = new Date(Date.now() - 60_000);
392
+ utimesSync(staleDir, newer, newer);
393
+ utimesSync(intendedDir, older, older);
394
+
395
+ _clearGsdRootCache();
396
+ clearPathCache();
397
+
398
+ const resolved = resolveExpectedArtifactPath("plan-milestone", "M001", root);
399
+ assert.equal(
400
+ resolved,
401
+ join(intendedDir, "01-ROADMAP.md"),
402
+ "bare id must resolve to the real title dir, not the newer team-suffix projection",
403
+ );
404
+ assert.notEqual(
405
+ resolved,
406
+ join(staleDir, "01-ROADMAP.md"),
407
+ "must NOT resolve into the team-suffix projection dir that has no ROADMAP",
408
+ );
409
+ } finally {
410
+ _clearGsdRootCache();
411
+ clearPathCache();
412
+ rmSync(root, { recursive: true, force: true });
413
+ }
414
+ });
415
+
416
+ test("bare milestone id still falls back to a lone team-suffix projection (#1195)", () => {
417
+ const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-bare-teamsuffix-only-")));
418
+ try {
419
+ const phasesDir = join(root, ".gsd", "phases");
420
+ // The only on-disk dir for the bare id is a team-mode projection. With no
421
+ // non-suffixed candidate, the fallback pass must still resolve to it.
422
+ const onlyDir = join(phasesDir, "01-re4q3k-clean-continuation");
423
+ mkdirSync(onlyDir, { recursive: true });
424
+ writeFileSync(join(onlyDir, "01-ROADMAP.md"), "# roadmap\n");
425
+
426
+ _clearGsdRootCache();
427
+ clearPathCache();
428
+
429
+ const resolved = resolveExpectedArtifactPath("plan-milestone", "M001", root);
430
+ assert.equal(
431
+ resolved,
432
+ join(onlyDir, "01-ROADMAP.md"),
433
+ "with no non-suffixed dir, the team-suffix projection is the correct fallback",
434
+ );
435
+ } finally {
436
+ _clearGsdRootCache();
437
+ clearPathCache();
438
+ rmSync(root, { recursive: true, force: true });
439
+ }
440
+ });
441
+
442
+ // ── #1208: flat-phase execute-task summaries resolve at the phase root ────────
443
+ //
444
+ // In flat-phase layout task summaries are written beside the plan files
445
+ // (phases/<phase>/T##-SUMMARY.md), NOT under a tasks/ subdir. A tasks/ dir may
446
+ // still exist to hold auxiliary task-scoped gate artifacts (e.g. T01-VERIFY.json).
447
+ // Before the fix, the mere existence of that tasks/ dir redirected summary
448
+ // verification into tasks/T##-SUMMARY.md — which never exists — trapping auto-mode
449
+ // in a false verification retry that eventually paused after a successful task.
450
+
451
+ test("flat-phase execute-task summary resolves at phase root when no tasks/ dir exists (#1208)", () => {
452
+ const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-flat-task-summary-")));
453
+ try {
454
+ const gsd = join(root, ".gsd");
455
+ const phaseDir = join(gsd, "phases", "49-end-to-end-mandates");
456
+ mkdirSync(phaseDir, { recursive: true });
457
+ writeFileSync(join(phaseDir, "49-03-PLAN.md"), "# plan\n- [x] T02\n");
458
+
459
+ _clearGsdRootCache();
460
+ clearPathCache();
461
+
462
+ assert.equal(
463
+ resolveExpectedArtifactPath("execute-task", "M049/S03/T02", root),
464
+ join(phaseDir, "T02-SUMMARY.md"),
465
+ );
466
+ } finally {
467
+ _clearGsdRootCache();
468
+ clearPathCache();
469
+ rmSync(root, { recursive: true, force: true });
470
+ }
471
+ });
472
+
473
+ test("flat-phase execute-task summary resolves at phase root even when tasks/ dir holds gate artifacts (#1208)", () => {
474
+ const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-flat-task-tasksdir-")));
475
+ try {
476
+ const gsd = join(root, ".gsd");
477
+ const phaseDir = join(gsd, "phases", "49-end-to-end-mandates");
478
+ mkdirSync(phaseDir, { recursive: true });
479
+ writeFileSync(join(phaseDir, "49-03-PLAN.md"), "# plan\n- [x] T02\n");
480
+ // Auxiliary task-scoped gate artifact — creates the tasks/ dir but must not
481
+ // redirect the T02 summary into tasks/.
482
+ const tasksDir = join(phaseDir, "tasks");
483
+ mkdirSync(tasksDir, { recursive: true });
484
+ writeFileSync(join(tasksDir, "T01-VERIFY.json"), '{"ok":true}');
485
+
486
+ _clearGsdRootCache();
487
+ clearPathCache();
488
+
489
+ const resolved = resolveExpectedArtifactPath("execute-task", "M049/S03/T02", root);
490
+ assert.equal(
491
+ resolved,
492
+ join(phaseDir, "T02-SUMMARY.md"),
493
+ "flat-phase task summary must resolve at the phase root, not tasks/",
494
+ );
495
+ assert.notEqual(
496
+ resolved,
497
+ join(tasksDir, "T02-SUMMARY.md"),
498
+ "a tasks/ dir with gate artifacts must NOT redirect summary resolution into tasks/",
499
+ );
500
+ } finally {
501
+ _clearGsdRootCache();
502
+ clearPathCache();
503
+ rmSync(root, { recursive: true, force: true });
504
+ }
505
+ });
506
+
507
+ test("legacy execute-task summary still resolves under slices/<SID>/tasks/ (#1208 regression guard)", () => {
508
+ const root = realpathSync(mkdtempSync(join(tmpdir(), "gsd-legacy-task-summary-")));
509
+ try {
510
+ const milestoneDir = join(root, ".gsd", "milestones", "M001");
511
+ const sliceDir = join(milestoneDir, "slices", "S01");
512
+ const tasksDir = join(sliceDir, "tasks");
513
+ mkdirSync(tasksDir, { recursive: true });
514
+ writeFileSync(join(milestoneDir, "M001-CONTEXT.md"), "# context\n");
515
+ writeFileSync(join(sliceDir, "S01-PLAN.md"), "# plan\n");
516
+
517
+ _clearGsdRootCache();
518
+ clearPathCache();
519
+
520
+ assert.equal(
521
+ resolveExpectedArtifactPath("execute-task", "M001/S01/T02", root),
522
+ join(tasksDir, "T02-SUMMARY.md"),
523
+ );
524
+ } finally {
525
+ _clearGsdRootCache();
526
+ clearPathCache();
527
+ rmSync(root, { recursive: true, force: true });
528
+ }
529
+ });
530
+
363
531
  // ── resolveSliceResearchLocation / resolveExistingSliceResearchPath ───────────
364
532
  //
365
533
  // Added in the code-quality consolidation PR as the shared dual-path resolver
@@ -14,7 +14,8 @@ import { join } from "node:path";
14
14
  import { tmpdir } from "node:os";
15
15
  import { execFileSync } from "node:child_process";
16
16
 
17
- import { createAutoWorktree, teardownAutoWorktree } from "../auto-worktree.ts";
17
+ import { createAutoWorktree } from "../auto-worktree-creation.ts";
18
+ import { teardownAutoWorktree } from "../auto-worktree-teardown.ts";
18
19
 
19
20
  function git(args: string[], cwd: string): void {
20
21
  execFileSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
@@ -797,9 +797,11 @@ test("stuck-loop: empty ring on a freshly constructed orchestrator advances norm
797
797
  assert.equal(result.kind, "advanced");
798
798
  });
799
799
 
800
- test("stuck-loop: partial fill of mixed units does not block", async (t) => {
800
+ test("stuck-loop: distinct units making forward progress do not block", async (t) => {
801
+ // Healthy forward progress visits new units every advance — no key repeats,
802
+ // so no oscillation/repeat rule fires even once the window is full.
801
803
  let i = 0;
802
- const sequence = ["M001/S01/A", "M001/S01/B", "M001/S01/A", "M001/S01/B", "M001/S01/A", "M001/S01/B"];
804
+ const sequence = ["M001/S01/A", "M001/S01/B", "M001/S01/C", "M001/S01/D", "M001/S01/E", "M001/S01/F"];
803
805
  const f = makeFixture({
804
806
  dispatch: () => ({ action: "dispatch", unitType: "execute-task", unitId: sequence[i++ % sequence.length], prompt: "p" }),
805
807
  });
@@ -811,6 +813,43 @@ test("stuck-loop: partial fill of mixed units does not block", async (t) => {
811
813
  }
812
814
  });
813
815
 
816
+ test("stuck-loop #1225: two-unit oscillation blocks once the window saturates", async (t) => {
817
+ // Reproduces the execute-task ↔ complete-slice loop: a slice gate keeps
818
+ // reopening the same task, so two keys alternate forever. Neither key ever
819
+ // saturates the window on its own, so the old matchingCount>=SIZE gate never
820
+ // consulted detect-stuck and the loop ran until an external kill. The window
821
+ // still fills, so detect-stuck's oscillation/repeat rules must now fire.
822
+ let i = 0;
823
+ const sequence: Array<{ unitType: string; unitId: string }> = [
824
+ { unitType: "execute-task", unitId: "M001/S01/T01" },
825
+ { unitType: "complete-slice", unitId: "M001/S01" },
826
+ ];
827
+ const f = makeFixture({
828
+ dispatch: () => {
829
+ const next = sequence[i++ % sequence.length];
830
+ return { action: "dispatch", unitType: next.unitType, unitId: next.unitId, prompt: "p" };
831
+ },
832
+ });
833
+ t.after(() => f.cleanup());
834
+
835
+ let blocked: Awaited<ReturnType<typeof f.orchestrator.advance>> | undefined;
836
+ for (let round = 0; round < STUCK_WINDOW_SIZE; round++) {
837
+ const result = await f.orchestrator.advance();
838
+ if (result.kind === "blocked") {
839
+ blocked = result;
840
+ break;
841
+ }
842
+ }
843
+
844
+ assert.ok(blocked, "oscillation must be detected once the window saturates");
845
+ if (!blocked || blocked.kind !== "blocked") return;
846
+ assert.equal(blocked.action, "stop");
847
+ assert.ok(
848
+ blocked.reason.startsWith("stuck-loop:"),
849
+ `expected stuck-loop verdict, got: ${blocked.reason}`,
850
+ );
851
+ });
852
+
814
853
  test("stuck-loop: ring saturated with same unit blocks with action 'stop' and stuck-loop reason", async (t) => {
815
854
  const f = makeFixture();
816
855
  t.after(() => f.cleanup());
@@ -1,6 +1,6 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
3
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
  import {
@@ -8,6 +8,7 @@ import {
8
8
  maybeWriteParallelResearchCostSpikeBlocker,
9
9
  } from "../auto-post-unit.ts";
10
10
  import { resolveExpectedArtifactPath } from "../auto-recovery.ts";
11
+ import { _clearGsdRootCache, clearPathCache } from "../paths.ts";
11
12
 
12
13
  test("missing execute-task artifact includes completion contract and completion-tool hint", () => {
13
14
  const base = mkdtempSync(join(tmpdir(), "gsd-artifact-diag-"));
@@ -56,3 +57,49 @@ test("parallel research cost spike writes durable PARALLEL-BLOCKER", () => {
56
57
  rmSync(base, { recursive: true, force: true });
57
58
  }
58
59
  });
60
+
61
+ // ── #1238: symlinked project root must not produce a ../ path walk ────────────
62
+ //
63
+ // On WSL (and any layout where the project root is reached through a symlink),
64
+ // artifact resolution canonicalizes through gsdRoot (realpathSync), so the
65
+ // resolved artifact path lives under the REAL root while `basePath` is still the
66
+ // symlink. Before the fix, relative(symlinkBase, realArtifactPath) walked up out
67
+ // of the symlink (../../…/home/…) and the diagnostic reported that broken path as
68
+ // "not found on disk". Normalizing basePath to its real path first keeps the
69
+ // displayed path anchored at the real .gsd root.
70
+
71
+ test("symlinked project root yields a clean .gsd-relative artifact path, not a ../ walk (#1238)", () => {
72
+ const realRoot = realpathSync(mkdtempSync(join(tmpdir(), "gsd-symlink-real-")));
73
+ const linkParent = realpathSync(mkdtempSync(join(tmpdir(), "gsd-symlink-link-")));
74
+ const linkRoot = join(linkParent, "project");
75
+ try {
76
+ // Content-bearing legacy milestone dir so plan-milestone resolves the
77
+ // canonical (realpath) ROADMAP path under realRoot/.gsd/milestones/M001/.
78
+ const milestoneDir = join(realRoot, ".gsd", "milestones", "M001");
79
+ mkdirSync(milestoneDir, { recursive: true });
80
+ writeFileSync(join(milestoneDir, "M001-CONTEXT.md"), "# context\n");
81
+ // The ROADMAP intentionally does not exist — this hits the "not found on
82
+ // disk" branch, the exact symptom in #1238.
83
+ symlinkSync(realRoot, linkRoot);
84
+
85
+ _clearGsdRootCache();
86
+ clearPathCache();
87
+
88
+ const msg = _describeArtifactVerificationFailureForTest("plan-milestone", "M001", linkRoot);
89
+
90
+ assert.match(msg, /was not found on disk after unit execution/);
91
+ // The displayed path must be anchored at the real .gsd root, not a broken
92
+ // parent-walk out of the symlinked base.
93
+ assert.doesNotMatch(msg, /\.\.[/\\]/, "must not contain a ../ walk out of the symlinked base");
94
+ assert.match(
95
+ msg,
96
+ /\.gsd[/\\]milestones[/\\]M001[/\\]M001-ROADMAP\.md/,
97
+ "must show the clean .gsd-relative ROADMAP path",
98
+ );
99
+ } finally {
100
+ _clearGsdRootCache();
101
+ clearPathCache();
102
+ rmSync(linkParent, { recursive: true, force: true });
103
+ rmSync(realRoot, { recursive: true, force: true });
104
+ }
105
+ });
@@ -299,6 +299,63 @@ test("refreshRecoveryDbForArtifact treats missing execute-task DB rows as fatal
299
299
  });
300
300
  });
301
301
 
302
+ test("refreshRecoveryDbForArtifact promotes an open execute-task DB row when artifacts are verified on disk (#1204)", () => {
303
+ const dir = makeTmpProject();
304
+ insertTask({
305
+ milestoneId: "M001",
306
+ sliceId: "S01",
307
+ id: "T01",
308
+ title: "Stuck Task",
309
+ status: "pending",
310
+ });
311
+ const sliceDir = join(dir, ".gsd", "milestones", "M001", "slices", "S01");
312
+ mkdirSync(sliceDir, { recursive: true });
313
+ writeFileSync(join(sliceDir, "S01-PLAN.md"), [
314
+ "# S01 Plan",
315
+ "",
316
+ "- [ ] **T01: Implement feature** `est:1h`",
317
+ "",
318
+ ].join("\n"));
319
+
320
+ const result = refreshRecoveryDbForArtifact("execute-task", "M001/S01/T01", dir);
321
+
322
+ assert.deepEqual(result, { ok: true });
323
+ assert.equal(getTask("M001", "S01", "T01")?.status, "complete");
324
+ const planContent = readFileSync(join(sliceDir, "S01-PLAN.md"), "utf-8");
325
+ assert.ok(planContent.includes("[x] **T01:"), "plan checkbox should be re-rendered to [x]");
326
+ const events = readEvents(join(dir, ".gsd", "event-log.jsonl"));
327
+ assert.ok(
328
+ events.some((e) => e.cmd === "complete-task" && e.trigger_reason === "stuck-artifact-recovery"),
329
+ "a complete-task recovery event should be appended",
330
+ );
331
+ });
332
+
333
+ test("refreshRecoveryDbForArtifact still appends the recovery event when the plan checkbox sync throws after DB promotion (#1221)", () => {
334
+ const dir = makeTmpProject();
335
+ insertTask({
336
+ milestoneId: "M001",
337
+ sliceId: "S01",
338
+ id: "T01",
339
+ title: "Stuck Task",
340
+ status: "pending",
341
+ });
342
+ const sliceDir = join(dir, ".gsd", "milestones", "M001", "slices", "S01");
343
+ mkdirSync(sliceDir, { recursive: true });
344
+ // Make the expected plan path a directory so the best-effort checkbox
345
+ // rewrite (readFileSync) throws EISDIR after the DB row is already promoted.
346
+ mkdirSync(join(sliceDir, "S01-PLAN.md"), { recursive: true });
347
+
348
+ const result = refreshRecoveryDbForArtifact("execute-task", "M001/S01/T01", dir);
349
+
350
+ assert.deepEqual(result, { ok: true });
351
+ assert.equal(getTask("M001", "S01", "T01")?.status, "complete");
352
+ const events = readEvents(join(dir, ".gsd", "event-log.jsonl"));
353
+ assert.ok(
354
+ events.some((e) => e.cmd === "complete-task" && e.trigger_reason === "stuck-artifact-recovery"),
355
+ "recovery event must still be appended even when the plan checkbox sync fails",
356
+ );
357
+ });
358
+
302
359
  test("refreshRecoveryDbForArtifact closes complete-milestone DB row when artifacts exist but DB is stale (#5568)", async () => {
303
360
  const base = mkdtempSync(join(tmpdir(), "auto-recovery-complete-ms-"));
304
361
  mkdirSync(join(base, ".gsd"), { recursive: true });
@@ -6,7 +6,7 @@ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
6
6
  import { join } from "node:path";
7
7
  import { tmpdir } from "node:os";
8
8
  import { randomUUID } from "node:crypto";
9
- import { cleanStaleRuntimeUnits } from "../auto-worktree.ts";
9
+ import { cleanStaleRuntimeUnits } from "../auto-worktree-runtime-cleanup.ts";
10
10
 
11
11
  function makeBase(): string {
12
12
  return join(tmpdir(), `gsd-clean-runtime-${randomUUID()}`);
@@ -4,7 +4,7 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
 
7
- import { closeDatabase, getAllMilestones, getMilestone, insertMilestone, isDbAvailable, openDatabase } from "../gsd-db.ts";
7
+ import { _getAdapter, closeDatabase, getAllMilestones, getMilestone, insertMilestone, isDbAvailable, openDatabase } from "../gsd-db.ts";
8
8
  import { reconcileMergedMilestonesFromJournal, reconcileProjectMilestonesFromDisk } from "../auto-start.ts";
9
9
  import { emitWorktreeMerged } from "../worktree-telemetry.ts";
10
10
 
@@ -69,3 +69,31 @@ test("#5389: bootstrap reconciles PROJECT.md milestones that are missing from DB
69
69
  rmSync(base, { recursive: true, force: true });
70
70
  }
71
71
  });
72
+
73
+ test("#1236: bootstrap merged-milestone reconciliation degrades to a warning instead of aborting when the DB is degraded", () => {
74
+ const base = mkdtempSync(join(tmpdir(), "gsd-merged-reconcile-degraded-"));
75
+ try {
76
+ mkdirSync(join(base, ".gsd"), { recursive: true });
77
+ openDatabase(join(base, ".gsd", "gsd.db"));
78
+ insertMilestone({ id: "M001", title: "Merged Milestone", status: "active" });
79
+
80
+ emitWorktreeMerged(base, "M001", { reason: "milestone-complete", conflict: false });
81
+
82
+ // Simulate a degraded DB: the connection stays "available" (isDbAvailable()
83
+ // remains true because the handle is non-null), but the milestones table is
84
+ // gone, so the reconciler's DB access throws partway through bootstrap.
85
+ _getAdapter()!.exec("DROP TABLE milestones");
86
+ assert.equal(isDbAvailable(), true);
87
+
88
+ // Regression (#1236): this reconciler was previously unguarded, so a
89
+ // degraded-DB failure threw and aborted the rest of `/gsd auto` bootstrap.
90
+ // It must now catch, warn, and return 0, matching its sibling
91
+ // reconcileProjectMilestonesFromDisk. Reaching the assertion proves it did
92
+ // not throw.
93
+ const closed = reconcileMergedMilestonesFromJournal(base);
94
+ assert.equal(closed, 0);
95
+ } finally {
96
+ if (isDbAvailable()) closeDatabase();
97
+ rmSync(base, { recursive: true, force: true });
98
+ }
99
+ });
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Idle/hard timeout recovery honors the in-flight-tool guard (#1229 follow-up).
3
+ *
4
+ * `recoverTimedOutUnit` steers a still-running unit with `deliverAs: "steer"`
5
+ * and, before that, may swap the session model via
6
+ * `applySupervisorModelIfConfigured`. Swapping the model and triggering a turn
7
+ * while non-interactive tool calls are still open skips tool results and trips
8
+ * provider errors (#3512) — the same failure the soft wrap-up and continue-here
9
+ * timers guard against. This test pins that the idle and hard steering branches
10
+ * gate both the model swap and `triggerTurn` on `getInFlightToolCount() === 0`.
11
+ */
12
+
13
+ import test from "node:test";
14
+ import assert from "node:assert/strict";
15
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
16
+ import { join } from "node:path";
17
+ import { tmpdir } from "node:os";
18
+
19
+ import { recoverTimedOutUnit, type RecoveryContext } from "../auto-timeout-recovery.ts";
20
+ import { clearGSDPreferencesCache } from "../preferences.ts";
21
+ import {
22
+ markToolStart,
23
+ markToolEnd,
24
+ clearInFlightTools,
25
+ } from "../auto-tool-tracking.ts";
26
+
27
+ const SUPERVISOR_PREFS = [
28
+ "auto_supervisor:",
29
+ " soft_timeout_minutes: 1",
30
+ " idle_timeout_minutes: 100",
31
+ " hard_timeout_minutes: 100",
32
+ " model:",
33
+ " model: supervisor-primary",
34
+ " fallbacks: [supervisor-fb]",
35
+ ];
36
+
37
+ interface Harness {
38
+ home: string;
39
+ base: string;
40
+ ctx: any;
41
+ pi: any;
42
+ rctx: RecoveryContext;
43
+ setModelCalls: unknown[][];
44
+ sendMessageCalls: unknown[][];
45
+ }
46
+
47
+ function makeHarness(): Harness {
48
+ const home = mkdtempSync(join(tmpdir(), "gsd-recovery-guard-home-"));
49
+ const base = mkdtempSync(join(tmpdir(), "gsd-recovery-guard-base-"));
50
+ process.env.GSD_HOME = home;
51
+ writeFileSync(join(home, "preferences.md"), ["---", ...SUPERVISOR_PREFS, "---", ""].join("\n"));
52
+ clearGSDPreferencesCache();
53
+
54
+ const setModelCalls: unknown[][] = [];
55
+ const sendMessageCalls: unknown[][] = [];
56
+
57
+ const ctx = {
58
+ ui: { notify: () => {} },
59
+ model: { provider: "anthropic" },
60
+ modelRegistry: {
61
+ getAvailable: () => [
62
+ { id: "supervisor-primary", provider: "anthropic" },
63
+ { id: "supervisor-fb", provider: "anthropic" },
64
+ ],
65
+ },
66
+ } as any;
67
+
68
+ const pi = {
69
+ sendMessage: (...args: unknown[]) => {
70
+ sendMessageCalls.push(args);
71
+ },
72
+ setModel: async (...args: unknown[]) => {
73
+ setModelCalls.push(args);
74
+ return true;
75
+ },
76
+ getThinkingLevel: () => "off",
77
+ setThinkingLevel: () => {},
78
+ } as any;
79
+
80
+ const rctx: RecoveryContext = {
81
+ basePath: base,
82
+ verbose: false,
83
+ currentUnitStartedAt: 1234,
84
+ unitRecoveryCount: new Map(),
85
+ };
86
+
87
+ return { home, base, ctx, pi, rctx, setModelCalls, sendMessageCalls };
88
+ }
89
+
90
+ function cleanup(h: Harness): void {
91
+ clearInFlightTools();
92
+ clearGSDPreferencesCache();
93
+ delete process.env.GSD_HOME;
94
+ rmSync(h.home, { recursive: true, force: true });
95
+ rmSync(h.base, { recursive: true, force: true });
96
+ }
97
+
98
+ // "discuss-project" resolves to a PROJECT.md that never exists in the temp base,
99
+ // so recovery skips the "already on disk" shortcut and reaches the steering
100
+ // branch with recoveryAttempts (0) < maxRecoveryAttempts.
101
+ for (const reason of ["idle", "hard"] as const) {
102
+ test(`${reason} recovery skips the supervisor model swap while a tool is in flight`, async () => {
103
+ const h = makeHarness();
104
+ try {
105
+ markToolStart("call-1", true, "some_tool");
106
+
107
+ const outcome = await recoverTimedOutUnit(
108
+ h.ctx,
109
+ h.pi,
110
+ "discuss-project",
111
+ "P01",
112
+ reason,
113
+ h.rctx,
114
+ );
115
+
116
+ assert.equal(outcome, "recovered");
117
+ assert.equal(
118
+ h.setModelCalls.length,
119
+ 0,
120
+ "model must NOT swap while a tool is in flight",
121
+ );
122
+ assert.equal(h.sendMessageCalls.length, 1, "steer message still sent (queued)");
123
+ const opts = h.sendMessageCalls[0][1] as { triggerTurn?: boolean; deliverAs?: string };
124
+ assert.equal(opts.triggerTurn, false, "turn is not triggered mid-tool-call");
125
+ assert.equal(opts.deliverAs, "steer");
126
+
127
+ markToolEnd("call-1");
128
+ } finally {
129
+ cleanup(h);
130
+ }
131
+ });
132
+
133
+ test(`${reason} recovery applies the supervisor model swap when no tools are in flight`, async () => {
134
+ const h = makeHarness();
135
+ try {
136
+ const outcome = await recoverTimedOutUnit(
137
+ h.ctx,
138
+ h.pi,
139
+ "discuss-project",
140
+ "P01",
141
+ reason,
142
+ h.rctx,
143
+ );
144
+
145
+ assert.equal(outcome, "recovered");
146
+ assert.equal(h.setModelCalls.length, 1, "model swaps to the supervisor model");
147
+ assert.deepEqual(
148
+ h.setModelCalls[0][0],
149
+ { id: "supervisor-primary", provider: "anthropic" },
150
+ "swaps to the configured supervisor primary",
151
+ );
152
+ assert.equal(h.sendMessageCalls.length, 1);
153
+ const opts = h.sendMessageCalls[0][1] as { triggerTurn?: boolean };
154
+ assert.equal(opts.triggerTurn, true, "turn is triggered when no tools are open");
155
+ } finally {
156
+ cleanup(h);
157
+ }
158
+ });
159
+ }
@@ -28,7 +28,8 @@ import { join } from "node:path";
28
28
  import { tmpdir } from "node:os";
29
29
 
30
30
  import { buildFlatRateContext } from "../auto-model-selection.ts";
31
- import { _isSamePath, _resetAutoWorktreeOriginalBaseForTests } from "../auto-worktree.ts";
31
+ import { _resetAutoWorktreeOriginalBaseForTests } from "../auto-worktree-session-registry.ts";
32
+ import { _isSamePath } from "../auto-worktree-path-utils.ts";
32
33
  import {
33
34
  checkAutoStartAfterDiscuss,
34
35
  clearPendingAutoStart,
@@ -11,7 +11,7 @@ import assert from "node:assert/strict";
11
11
  import {
12
12
  isSafeToAutoResolve,
13
13
  SAFE_AUTO_RESOLVE_PATTERNS,
14
- } from "../auto-worktree.ts";
14
+ } from "../auto-worktree-conflict-auto-resolve.ts";
15
15
 
16
16
  describe("isSafeToAutoResolve", () => {
17
17
  // ─── .gsd/ state files ───────────────────────────────────────────────────