@opengsd/gsd-pi 1.4.0 → 1.5.0-dev.553dc518

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 (606) hide show
  1. package/README.md +11 -11
  2. package/dist/onboarding.js +11 -0
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/GSD-WORKFLOW.md +20 -25
  5. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +118 -53
  6. package/dist/resources/extensions/cursor-cli/index.js +16 -0
  7. package/dist/resources/extensions/cursor-cli/models.js +63 -0
  8. package/dist/resources/extensions/cursor-cli/package.json +11 -0
  9. package/dist/resources/extensions/cursor-cli/readiness.js +128 -0
  10. package/dist/resources/extensions/cursor-cli/stream-adapter.js +353 -0
  11. package/dist/resources/extensions/gsd/activity-log.js +4 -1
  12. package/dist/resources/extensions/gsd/artifact-verification.js +25 -9
  13. package/dist/resources/extensions/gsd/auto/closeout.js +137 -42
  14. package/dist/resources/extensions/gsd/auto/finalize.js +9 -0
  15. package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -3
  16. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +6 -3
  17. package/dist/resources/extensions/gsd/auto/run-unit.js +5 -2
  18. package/dist/resources/extensions/gsd/auto/schedule-wakeup.js +3 -0
  19. package/dist/resources/extensions/gsd/auto/unit-phase.js +5 -9
  20. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +4 -5
  21. package/dist/resources/extensions/gsd/auto-dispatch.js +15 -5
  22. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -18
  23. package/dist/resources/extensions/gsd/auto-prompts.js +76 -2
  24. package/dist/resources/extensions/gsd/auto-start.js +7 -5
  25. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -0
  26. package/dist/resources/extensions/gsd/auto-worktree-branch-lifecycle.js +189 -0
  27. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +133 -0
  28. package/dist/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.js +35 -0
  29. package/dist/resources/extensions/gsd/auto-worktree-creation.js +130 -0
  30. package/dist/resources/extensions/gsd/auto-worktree-entry.js +118 -0
  31. package/dist/resources/extensions/gsd/auto-worktree-merge-already-merged.js +98 -0
  32. package/dist/resources/extensions/gsd/auto-worktree-merge-branch-head.js +52 -0
  33. package/dist/resources/extensions/gsd/auto-worktree-merge-cleanup.js +87 -0
  34. package/dist/resources/extensions/gsd/auto-worktree-merge-code-changes.js +46 -0
  35. package/dist/resources/extensions/gsd/auto-worktree-merge-db-ready.js +68 -0
  36. package/dist/resources/extensions/gsd/auto-worktree-merge-integration-branch.js +51 -0
  37. package/dist/resources/extensions/gsd/auto-worktree-merge-message.js +106 -0
  38. package/dist/resources/extensions/gsd/auto-worktree-merge-pre-teardown.js +64 -0
  39. package/dist/resources/extensions/gsd/auto-worktree-merge-stash.js +168 -0
  40. package/dist/resources/extensions/gsd/auto-worktree-merge.js +302 -0
  41. package/dist/resources/extensions/gsd/auto-worktree-milestone-shelter.js +119 -0
  42. package/dist/resources/extensions/gsd/auto-worktree-path-resolution.js +5 -0
  43. package/dist/resources/extensions/gsd/auto-worktree-path-utils.js +5 -0
  44. package/dist/resources/extensions/gsd/auto-worktree-resource-version.js +41 -0
  45. package/dist/resources/extensions/gsd/auto-worktree-runtime-cleanup.js +99 -0
  46. package/dist/resources/extensions/gsd/auto-worktree-session-registry.js +57 -0
  47. package/dist/resources/extensions/gsd/auto-worktree-sync.js +249 -0
  48. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +120 -0
  49. package/dist/resources/extensions/gsd/auto-worktree.js +20 -2046
  50. package/dist/resources/extensions/gsd/auto.js +31 -5
  51. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -0
  52. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -1
  53. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +133 -6
  54. package/dist/resources/extensions/gsd/bootstrap/schedule-wakeup-tool.js +58 -9
  55. package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
  56. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +127 -22
  57. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +14 -1
  58. package/dist/resources/extensions/gsd/codebase-generator.js +157 -19
  59. package/dist/resources/extensions/gsd/commands/handlers/core.js +40 -4
  60. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  61. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +153 -1
  62. package/dist/resources/extensions/gsd/commands-workflow-templates.js +3 -3
  63. package/dist/resources/extensions/gsd/commands-worktree.js +11 -2
  64. package/dist/resources/extensions/gsd/db/queries.js +48 -9
  65. package/dist/resources/extensions/gsd/discussion-handoff.js +8 -3
  66. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -2
  67. package/dist/resources/extensions/gsd/doctor-engine-checks.js +292 -18
  68. package/dist/resources/extensions/gsd/doctor-providers.js +38 -10
  69. package/dist/resources/extensions/gsd/doctor.js +93 -3
  70. package/dist/resources/extensions/gsd/exec-sandbox.js +6 -2
  71. package/dist/resources/extensions/gsd/flat-phase-migration.js +88 -26
  72. package/dist/resources/extensions/gsd/forensics.js +1 -1
  73. package/dist/resources/extensions/gsd/git-conflict-resolve.js +2 -2
  74. package/dist/resources/extensions/gsd/git-service.js +59 -18
  75. package/dist/resources/extensions/gsd/gsd-db.js +63 -0
  76. package/dist/resources/extensions/gsd/guidance.js +1 -0
  77. package/dist/resources/extensions/gsd/guided-flow.js +46 -12
  78. package/dist/resources/extensions/gsd/key-manager.js +1 -0
  79. package/dist/resources/extensions/gsd/markdown-renderer.js +40 -11
  80. package/dist/resources/extensions/gsd/migrate-external.js +24 -7
  81. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +14 -3
  82. package/dist/resources/extensions/gsd/milestone-settlement.js +1 -1
  83. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  84. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -1
  85. package/dist/resources/extensions/gsd/preferences-diagnostics.js +24 -1
  86. package/dist/resources/extensions/gsd/preferences-models.js +6 -4
  87. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  88. package/dist/resources/extensions/gsd/preferences-validation.js +107 -2
  89. package/dist/resources/extensions/gsd/preferences.js +29 -2
  90. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  91. package/dist/resources/extensions/gsd/prompts/system.md +6 -6
  92. package/dist/resources/extensions/gsd/quick.js +12 -3
  93. package/dist/resources/extensions/gsd/redact-secrets.js +37 -0
  94. package/dist/resources/extensions/gsd/repo-identity.js +16 -0
  95. package/dist/resources/extensions/gsd/repository-registry.js +6 -1
  96. package/dist/resources/extensions/gsd/root-write-leak-guard.js +4 -2
  97. package/dist/resources/extensions/gsd/safe-fs.js +23 -2
  98. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
  99. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -0
  100. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +2 -1
  101. package/dist/resources/extensions/gsd/state/derive/from-db.js +88 -153
  102. package/dist/resources/extensions/gsd/tool-contract.js +14 -0
  103. package/dist/resources/extensions/gsd/tools/plan-task.js +76 -8
  104. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -0
  105. package/dist/resources/extensions/gsd/unit-context-manifest.js +5 -4
  106. package/dist/resources/extensions/gsd/unit-registry.js +37 -2
  107. package/dist/resources/extensions/gsd/unit-runtime.js +21 -0
  108. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +1 -1
  109. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -1
  110. package/dist/resources/extensions/gsd/workspace-git-preflight.js +2 -2
  111. package/dist/resources/extensions/gsd/workspace.js +26 -8
  112. package/dist/resources/extensions/gsd/worktree-command.js +1 -1
  113. package/dist/resources/extensions/gsd/worktree-lifecycle.js +81 -14
  114. package/dist/resources/extensions/gsd/worktree-manager.js +97 -4
  115. package/dist/resources/extensions/gsd/worktree-reentry.js +2 -1
  116. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  117. package/dist/web/standalone/.next/BUILD_ID +1 -1
  118. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  119. package/dist/web/standalone/.next/build-manifest.json +3 -3
  120. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  121. package/dist/web/standalone/.next/required-server-files.json +3 -3
  122. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  123. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  133. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  149. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  161. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  183. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  193. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  199. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  215. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  219. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  223. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  224. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  227. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  228. package/dist/web/standalone/.next/server/app/index.html +1 -1
  229. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  230. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  231. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  232. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  233. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  234. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  235. package/dist/web/standalone/.next/server/app/page.js +2 -2
  236. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  237. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  238. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  239. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  240. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  241. package/dist/web/standalone/.next/server/middleware.js +3 -3
  242. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  243. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  244. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  245. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  246. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  247. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  248. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  249. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  250. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  251. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  252. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  253. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  254. package/dist/web/standalone/server.js +1 -1
  255. package/dist/wizard.d.ts +8 -0
  256. package/dist/wizard.js +8 -1
  257. package/integrations/hermes/CONTEXT.md +47 -0
  258. package/integrations/hermes/README.md +21 -0
  259. package/integrations/hermes/__init__.py +31 -0
  260. package/integrations/hermes/docs/issue-1162-grilling.md +197 -0
  261. package/integrations/hermes/docs/setup.md +4 -0
  262. package/integrations/hermes/open_gsd_hermes/commands.py +141 -0
  263. package/integrations/hermes/open_gsd_hermes/config.py +2 -0
  264. package/integrations/hermes/open_gsd_hermes/gsd_client.py +591 -39
  265. package/integrations/hermes/open_gsd_hermes/notifications.py +10 -1
  266. package/integrations/hermes/plugin.yaml +4 -0
  267. package/integrations/hermes/tests/test_config.py +6 -0
  268. package/integrations/hermes/tests/test_directory_loader.py +37 -0
  269. package/integrations/hermes/tests/test_gsd_client_cache.py +3 -0
  270. package/integrations/hermes/tests/test_gsd_client_execute.py +35 -0
  271. package/integrations/hermes/tests/test_gsd_client_process_cwd.py +22 -0
  272. package/integrations/hermes/tests/test_gsd_client_timeout.py +98 -0
  273. package/integrations/hermes/tests/test_milestone_client.py +447 -0
  274. package/integrations/hermes/tests/test_new_milestone_command.py +313 -0
  275. package/integrations/hermes/tests/test_supervisor_fsm.py +40 -0
  276. package/package.json +8 -8
  277. package/packages/cloud-mcp-gateway/dist/auth-store.d.ts +1 -0
  278. package/packages/cloud-mcp-gateway/dist/auth-store.d.ts.map +1 -1
  279. package/packages/cloud-mcp-gateway/dist/auth-store.js +21 -1
  280. package/packages/cloud-mcp-gateway/dist/auth-store.js.map +1 -1
  281. package/packages/cloud-mcp-gateway/dist/auth-store.test.js +34 -0
  282. package/packages/cloud-mcp-gateway/dist/auth-store.test.js.map +1 -1
  283. package/packages/cloud-mcp-gateway/package.json +2 -2
  284. package/packages/contracts/package.json +1 -1
  285. package/packages/daemon/dist/cloud-runtime.d.ts +2 -0
  286. package/packages/daemon/dist/cloud-runtime.d.ts.map +1 -1
  287. package/packages/daemon/dist/cloud-runtime.js +25 -1
  288. package/packages/daemon/dist/cloud-runtime.js.map +1 -1
  289. package/packages/daemon/dist/cloud-runtime.test.js +51 -0
  290. package/packages/daemon/dist/cloud-runtime.test.js.map +1 -1
  291. package/packages/daemon/dist/message-batcher.d.ts +7 -0
  292. package/packages/daemon/dist/message-batcher.d.ts.map +1 -1
  293. package/packages/daemon/dist/message-batcher.js +13 -0
  294. package/packages/daemon/dist/message-batcher.js.map +1 -1
  295. package/packages/daemon/dist/message-batcher.test.js +48 -0
  296. package/packages/daemon/dist/message-batcher.test.js.map +1 -1
  297. package/packages/daemon/dist/session-manager.js +1 -1
  298. package/packages/daemon/dist/session-manager.js.map +1 -1
  299. package/packages/daemon/package.json +5 -5
  300. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts +13 -1
  301. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  302. package/packages/gsd-agent-core/dist/compaction/compaction.js +15 -1
  303. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  304. package/packages/gsd-agent-core/dist/export-html/template.js +53 -4
  305. package/packages/gsd-agent-core/dist/session/agent-session-navigation.d.ts.map +1 -1
  306. package/packages/gsd-agent-core/dist/session/agent-session-navigation.js +4 -1
  307. package/packages/gsd-agent-core/dist/session/agent-session-navigation.js.map +1 -1
  308. package/packages/gsd-agent-core/package.json +5 -5
  309. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  310. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +3 -2
  311. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  312. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -1
  313. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +1 -0
  314. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -1
  315. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +1 -1
  316. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
  317. package/packages/gsd-agent-modes/package.json +7 -7
  318. package/packages/mcp-server/dist/server.d.ts +18 -5
  319. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  320. package/packages/mcp-server/dist/server.js +46 -5
  321. package/packages/mcp-server/dist/server.js.map +1 -1
  322. package/packages/mcp-server/dist/session-manager.js +1 -1
  323. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  324. package/packages/mcp-server/package.json +4 -4
  325. package/packages/native/package.json +1 -1
  326. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  327. package/packages/pi-agent-core/dist/agent-loop.js +14 -9
  328. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  329. package/packages/pi-agent-core/package.json +1 -1
  330. package/packages/pi-ai/dist/env-api-keys.d.ts.map +1 -1
  331. package/packages/pi-ai/dist/env-api-keys.js +3 -0
  332. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  333. package/packages/pi-ai/dist/index.d.ts +1 -0
  334. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  335. package/packages/pi-ai/dist/index.js +1 -0
  336. package/packages/pi-ai/dist/index.js.map +1 -1
  337. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  338. package/packages/pi-ai/dist/providers/transform-messages.js +7 -3
  339. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  340. package/packages/pi-ai/dist/tool-result-content.d.ts +3 -0
  341. package/packages/pi-ai/dist/tool-result-content.d.ts.map +1 -0
  342. package/packages/pi-ai/dist/tool-result-content.js +62 -0
  343. package/packages/pi-ai/dist/tool-result-content.js.map +1 -0
  344. package/packages/pi-ai/dist/types.d.ts +10 -22
  345. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  346. package/packages/pi-ai/dist/types.js.map +1 -1
  347. package/packages/pi-ai/package.json +1 -1
  348. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  349. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  350. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  351. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +1 -0
  352. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -1
  354. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/session-manager.js +3 -0
  356. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  357. package/packages/pi-coding-agent/package.json +7 -7
  358. package/packages/pi-tui/package.json +2 -2
  359. package/packages/rpc-client/dist/rpc-client.js +1 -1
  360. package/packages/rpc-client/dist/rpc-client.js.map +1 -1
  361. package/packages/rpc-client/package.json +2 -2
  362. package/pkg/dist/core/export-html/template.js +53 -4
  363. package/pkg/package.json +1 -1
  364. package/scripts/link-workspace-packages.cjs +14 -4
  365. package/src/resources/GSD-WORKFLOW.md +20 -25
  366. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +130 -51
  367. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +371 -39
  368. package/src/resources/extensions/cursor-cli/index.ts +18 -0
  369. package/src/resources/extensions/cursor-cli/models.ts +65 -0
  370. package/src/resources/extensions/cursor-cli/package.json +11 -0
  371. package/src/resources/extensions/cursor-cli/readiness.ts +143 -0
  372. package/src/resources/extensions/cursor-cli/stream-adapter.ts +440 -0
  373. package/src/resources/extensions/cursor-cli/tests/index.test.ts +54 -0
  374. package/src/resources/extensions/cursor-cli/tests/readiness.test.ts +29 -0
  375. package/src/resources/extensions/cursor-cli/tests/stream-adapter.test.ts +166 -0
  376. package/src/resources/extensions/gsd/activity-log.ts +4 -1
  377. package/src/resources/extensions/gsd/artifact-verification.ts +25 -9
  378. package/src/resources/extensions/gsd/auto/closeout.ts +163 -58
  379. package/src/resources/extensions/gsd/auto/finalize.ts +8 -0
  380. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  381. package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -3
  382. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +6 -3
  383. package/src/resources/extensions/gsd/auto/run-unit.ts +5 -2
  384. package/src/resources/extensions/gsd/auto/schedule-wakeup.ts +8 -0
  385. package/src/resources/extensions/gsd/auto/unit-phase.ts +5 -9
  386. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +4 -5
  387. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -5
  388. package/src/resources/extensions/gsd/auto-model-selection.ts +49 -18
  389. package/src/resources/extensions/gsd/auto-prompts.ts +73 -2
  390. package/src/resources/extensions/gsd/auto-start.ts +8 -5
  391. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +4 -0
  392. package/src/resources/extensions/gsd/auto-worktree-branch-lifecycle.ts +237 -0
  393. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +166 -0
  394. package/src/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.ts +37 -0
  395. package/src/resources/extensions/gsd/auto-worktree-creation.ts +171 -0
  396. package/src/resources/extensions/gsd/auto-worktree-entry.ts +154 -0
  397. package/src/resources/extensions/gsd/auto-worktree-merge-already-merged.ts +161 -0
  398. package/src/resources/extensions/gsd/auto-worktree-merge-branch-head.ts +83 -0
  399. package/src/resources/extensions/gsd/auto-worktree-merge-cleanup.ts +132 -0
  400. package/src/resources/extensions/gsd/auto-worktree-merge-code-changes.ts +71 -0
  401. package/src/resources/extensions/gsd/auto-worktree-merge-db-ready.ts +112 -0
  402. package/src/resources/extensions/gsd/auto-worktree-merge-integration-branch.ts +99 -0
  403. package/src/resources/extensions/gsd/auto-worktree-merge-message.ts +166 -0
  404. package/src/resources/extensions/gsd/auto-worktree-merge-pre-teardown.ts +93 -0
  405. package/src/resources/extensions/gsd/auto-worktree-merge-stash.ts +213 -0
  406. package/src/resources/extensions/gsd/auto-worktree-merge.ts +391 -0
  407. package/src/resources/extensions/gsd/auto-worktree-milestone-shelter.ts +159 -0
  408. package/src/resources/extensions/gsd/auto-worktree-path-resolution.ts +6 -0
  409. package/src/resources/extensions/gsd/auto-worktree-path-utils.ts +10 -0
  410. package/src/resources/extensions/gsd/auto-worktree-resource-version.ts +44 -0
  411. package/src/resources/extensions/gsd/auto-worktree-runtime-cleanup.ts +119 -0
  412. package/src/resources/extensions/gsd/auto-worktree-session-registry.ts +71 -0
  413. package/src/resources/extensions/gsd/auto-worktree-sync.ts +370 -0
  414. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +161 -0
  415. package/src/resources/extensions/gsd/auto-worktree.ts +69 -2390
  416. package/src/resources/extensions/gsd/auto.ts +32 -19
  417. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -0
  418. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -1
  419. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +147 -6
  420. package/src/resources/extensions/gsd/bootstrap/schedule-wakeup-tool.ts +80 -12
  421. package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
  422. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +163 -22
  423. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +23 -1
  424. package/src/resources/extensions/gsd/codebase-generator.ts +179 -18
  425. package/src/resources/extensions/gsd/commands/handlers/core.ts +39 -3
  426. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  427. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +135 -1
  428. package/src/resources/extensions/gsd/commands-workflow-templates.ts +3 -3
  429. package/src/resources/extensions/gsd/commands-worktree.ts +13 -2
  430. package/src/resources/extensions/gsd/db/queries.ts +49 -9
  431. package/src/resources/extensions/gsd/discussion-handoff.ts +10 -2
  432. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -2
  433. package/src/resources/extensions/gsd/doctor-engine-checks.ts +372 -22
  434. package/src/resources/extensions/gsd/doctor-providers.ts +39 -10
  435. package/src/resources/extensions/gsd/doctor-types.ts +5 -1
  436. package/src/resources/extensions/gsd/doctor.ts +95 -3
  437. package/src/resources/extensions/gsd/exec-sandbox.ts +6 -2
  438. package/src/resources/extensions/gsd/flat-phase-migration.ts +112 -25
  439. package/src/resources/extensions/gsd/forensics.ts +1 -1
  440. package/src/resources/extensions/gsd/git-conflict-resolve.ts +2 -2
  441. package/src/resources/extensions/gsd/git-service.ts +67 -17
  442. package/src/resources/extensions/gsd/gsd-db.ts +85 -0
  443. package/src/resources/extensions/gsd/guidance.ts +2 -0
  444. package/src/resources/extensions/gsd/guided-flow.ts +52 -13
  445. package/src/resources/extensions/gsd/key-manager.ts +1 -0
  446. package/src/resources/extensions/gsd/markdown-renderer.ts +40 -10
  447. package/src/resources/extensions/gsd/migrate-external.ts +23 -6
  448. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +19 -4
  449. package/src/resources/extensions/gsd/milestone-settlement.ts +1 -1
  450. package/src/resources/extensions/gsd/model-router.ts +4 -5
  451. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  452. package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -1
  453. package/src/resources/extensions/gsd/preferences-diagnostics.ts +24 -0
  454. package/src/resources/extensions/gsd/preferences-models.ts +6 -3
  455. package/src/resources/extensions/gsd/preferences-types.ts +30 -0
  456. package/src/resources/extensions/gsd/preferences-validation.ts +97 -2
  457. package/src/resources/extensions/gsd/preferences.ts +38 -4
  458. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  459. package/src/resources/extensions/gsd/prompts/system.md +6 -6
  460. package/src/resources/extensions/gsd/quick.ts +11 -3
  461. package/src/resources/extensions/gsd/redact-secrets.ts +40 -0
  462. package/src/resources/extensions/gsd/repo-identity.ts +17 -0
  463. package/src/resources/extensions/gsd/repository-registry.ts +7 -1
  464. package/src/resources/extensions/gsd/root-write-leak-guard.ts +3 -2
  465. package/src/resources/extensions/gsd/safe-fs.ts +22 -2
  466. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
  467. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -0
  468. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -1
  469. package/src/resources/extensions/gsd/state/derive/from-db.ts +201 -157
  470. package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +2 -1
  471. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +131 -5
  472. package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +18 -0
  473. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +178 -0
  474. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +43 -1
  475. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +54 -0
  476. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +41 -0
  477. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +41 -0
  478. package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +4 -4
  479. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +3 -0
  480. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +1 -1
  481. package/src/resources/extensions/gsd/tests/auto-timeout-recovery-harness-abort.test.ts +55 -0
  482. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +10 -1
  483. package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +1 -1
  484. package/src/resources/extensions/gsd/tests/auto-worktree-merge-already-merged.test.ts +177 -0
  485. package/src/resources/extensions/gsd/tests/auto-worktree-merge-branch-head.test.ts +118 -0
  486. package/src/resources/extensions/gsd/tests/auto-worktree-merge-cleanup.test.ts +115 -0
  487. package/src/resources/extensions/gsd/tests/auto-worktree-merge-code-changes.test.ts +76 -0
  488. package/src/resources/extensions/gsd/tests/auto-worktree-merge-db-ready.test.ts +140 -0
  489. package/src/resources/extensions/gsd/tests/auto-worktree-merge-integration-branch.test.ts +123 -0
  490. package/src/resources/extensions/gsd/tests/auto-worktree-merge-message.test.ts +114 -0
  491. package/src/resources/extensions/gsd/tests/auto-worktree-merge-pre-teardown.test.ts +84 -0
  492. package/src/resources/extensions/gsd/tests/auto-worktree-merge-stash.test.ts +70 -0
  493. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-shelter.test.ts +52 -0
  494. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +6 -6
  495. package/src/resources/extensions/gsd/tests/auto-worktree-resource-version.test.ts +59 -0
  496. package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +3 -1
  497. package/src/resources/extensions/gsd/tests/batch-task-query.test.ts +85 -0
  498. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +29 -0
  499. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +365 -0
  500. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +62 -1
  501. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +1 -1
  502. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -0
  503. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +138 -1
  504. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +571 -5
  505. package/src/resources/extensions/gsd/tests/doctor-workspace.test.ts +207 -0
  506. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +1 -1
  507. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +82 -2
  508. package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +25 -1
  509. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +87 -19
  510. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +89 -0
  511. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +40 -0
  512. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +9 -0
  513. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +4 -6
  514. package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +2 -1
  515. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +3 -3
  516. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +7 -8
  517. package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +2 -5
  518. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +76 -0
  519. package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +1 -1
  520. package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +1 -1
  521. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +2 -1
  522. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +5 -7
  523. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  524. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +2 -4
  525. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +122 -0
  526. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +1 -1
  527. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +4 -4
  528. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +1 -1
  529. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +1 -1
  530. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +116 -0
  531. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +592 -23
  532. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +25 -1
  533. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +1 -1
  534. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -3
  535. package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +1 -1
  536. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +2 -2
  537. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +50 -6
  538. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +17 -0
  539. package/src/resources/extensions/gsd/tests/plan-task.test.ts +264 -1
  540. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +1 -4
  541. package/src/resources/extensions/gsd/tests/preferences.test.ts +150 -0
  542. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +147 -0
  543. package/src/resources/extensions/gsd/tests/recovery-verify-logs.test.ts +4 -4
  544. package/src/resources/extensions/gsd/tests/redact-secrets.test.ts +56 -0
  545. package/src/resources/extensions/gsd/tests/register-hooks-flat-phase-migration.test.ts +73 -0
  546. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +275 -0
  547. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +41 -2
  548. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +55 -0
  549. package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +31 -9
  550. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
  551. package/src/resources/extensions/gsd/tests/schedule-wakeup-tool.test.ts +167 -0
  552. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -5
  553. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -0
  554. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +2 -1
  555. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +2 -1
  556. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -1
  557. package/src/resources/extensions/gsd/tests/status-per-repo.test.ts +94 -0
  558. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +1 -1
  559. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +1 -1
  560. package/src/resources/extensions/gsd/tests/system-flat-phase-layout.test.ts +33 -0
  561. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +4 -4
  562. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +2 -1
  563. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +4 -4
  564. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +35 -0
  565. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +166 -0
  566. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +1 -1
  567. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +66 -18
  568. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +81 -0
  569. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
  570. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +52 -0
  571. package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +53 -1
  572. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +208 -1
  573. package/src/resources/extensions/gsd/tests/workspace.test.ts +18 -4
  574. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -1
  575. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +1 -1
  576. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +1 -3
  577. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +1 -1
  578. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +1 -1
  579. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +4 -4
  580. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +2 -2
  581. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +1 -1
  582. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +1 -1
  583. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +2 -1
  584. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +36 -3
  585. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +1 -1
  586. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +1 -1
  587. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +32 -0
  588. package/src/resources/extensions/gsd/tool-contract.ts +29 -0
  589. package/src/resources/extensions/gsd/tools/plan-task.ts +107 -9
  590. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +58 -0
  591. package/src/resources/extensions/gsd/unit-context-manifest.ts +11 -5
  592. package/src/resources/extensions/gsd/unit-registry.ts +48 -2
  593. package/src/resources/extensions/gsd/unit-runtime.ts +42 -0
  594. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +1 -1
  595. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -1
  596. package/src/resources/extensions/gsd/workspace-git-preflight.ts +2 -2
  597. package/src/resources/extensions/gsd/workspace.ts +42 -8
  598. package/src/resources/extensions/gsd/worktree-command.ts +1 -1
  599. package/src/resources/extensions/gsd/worktree-lifecycle.ts +154 -26
  600. package/src/resources/extensions/gsd/worktree-manager.ts +143 -5
  601. package/src/resources/extensions/gsd/worktree-reentry.ts +2 -1
  602. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  603. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  604. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  605. /package/dist/web/standalone/.next/static/{zQLcXm0Za8lexoXtgDpMG → ZpFDazP-38PXBPiI_LdZf}/_buildManifest.js +0 -0
  606. /package/dist/web/standalone/.next/static/{zQLcXm0Za8lexoXtgDpMG → ZpFDazP-38PXBPiI_LdZf}/_ssgManifest.js +0 -0
@@ -409,7 +409,13 @@ export function resolvePreferredModelConfig(
409
409
  availableModelIds?: string[],
410
410
  preferredModelId?: string,
411
411
  ): PreferredModelConfig | undefined {
412
- const explicitConfig = resolveModelWithFallbacksForUnit(unitType, basePath, availableModelIds, preferredModelId);
412
+ const explicitConfig = resolveModelWithFallbacksForUnit(
413
+ unitType,
414
+ basePath,
415
+ availableModelIds,
416
+ preferredModelId,
417
+ true,
418
+ );
413
419
  if (explicitConfig) {
414
420
  return {
415
421
  ...explicitConfig,
@@ -422,26 +428,55 @@ export function resolvePreferredModelConfig(
422
428
  if (!isAutoMode) return undefined;
423
429
 
424
430
  const routingConfig = resolveDynamicRoutingConfig();
425
- if (!routingConfig.enabled || !routingConfig.tier_models) return undefined;
431
+ if (!routingConfig.enabled) return undefined;
426
432
 
427
- // Don't synthesize a routing config for flat-rate providers (#3453).
428
- // Users can opt into routing for flat-rate subscriptions (e.g. claude-code)
429
- // via dynamic_routing.allow_flat_rate_providers (#4386).
433
+ // Only an explicit flat-rate opt-out suppresses synthesized routing.
434
+ // `dynamic_routing.enabled: true` is user intent to run routing even when
435
+ // the start provider is a flat-rate subscription. Applied ahead of both the
436
+ // tier-pin and profile-derived synthesis paths so the opt-out is uniform.
430
437
  if (
431
- !routingConfig.allow_flat_rate_providers &&
438
+ routingConfig.allow_flat_rate_providers === false &&
432
439
  autoModeStartModel &&
433
440
  isFlatRateProvider(autoModeStartModel.provider, autoModeStartModel.flatRateCtx)
434
441
  ) {
435
442
  return undefined;
436
443
  }
437
444
 
438
- const ceilingModel = routingConfig.tier_models.heavy
439
- ?? (autoModeStartModel ? `${autoModeStartModel.provider}/${autoModeStartModel.id}` : undefined);
440
- if (!ceilingModel) return undefined;
445
+ // With explicit `tier_models` pins, synthesize a heavy-tier ceiling that
446
+ // dynamic routing downgrades from per unit.
447
+ if (routingConfig.tier_models) {
448
+ const ceilingModel = routingConfig.tier_models.heavy
449
+ ?? (autoModeStartModel ? `${autoModeStartModel.provider}/${autoModeStartModel.id}` : undefined);
450
+ if (!ceilingModel) return undefined;
451
+
452
+ return {
453
+ primary: ceilingModel,
454
+ fallbacks: [],
455
+ source: "synthesized",
456
+ };
457
+ }
458
+
459
+ // No `tier_models` pins: fall back to the token-profile's per-phase model so
460
+ // profile tier resolution survives. `skipProfileDefaults` is left false here
461
+ // (unlike the explicit-detection call above) precisely because we WANT the
462
+ // profile defaults this time — they are the routing ceiling, not a hard
463
+ // user selection. Labeling the result `synthesized` (not `explicit`) keeps
464
+ // dynamic routing and fallbacks enabled downstream. Without this branch,
465
+ // `resolvePreferredModelConfig` returns undefined for profile-only configs
466
+ // and auto dispatch bleeds the start model onto every unit, silently
467
+ // discarding the profile (#1115: routing/fallbacks disabled when a
468
+ // token_profile is set but no tier_models are pinned).
469
+ const profileConfig = resolveModelWithFallbacksForUnit(
470
+ unitType,
471
+ basePath,
472
+ availableModelIds,
473
+ preferredModelId,
474
+ false,
475
+ );
476
+ if (!profileConfig) return undefined;
441
477
 
442
478
  return {
443
- primary: ceilingModel,
444
- fallbacks: [],
479
+ ...profileConfig,
445
480
  source: "synthesized",
446
481
  };
447
482
  }
@@ -647,15 +682,11 @@ export async function selectAndApplyModel(
647
682
  }
648
683
  }
649
684
 
650
- // Disable routing for flat-rate providers like GitHub Copilot (#3453).
651
- // All models cost the same per request, so downgrading to a cheaper
652
- // model provides no cost benefit — it only degrades quality.
685
+ // Disable routing for flat-rate providers only when the user explicitly
686
+ // opts out with dynamic_routing.allow_flat_rate_providers: false.
653
687
  // Fail-closed: if primary model can't be resolved, fall back to
654
688
  // provider-level signals rather than allowing unwanted downgrades.
655
- // Opt-in: dynamic_routing.allow_flat_rate_providers skips the bypass so
656
- // claude-code subscribers can still get intelligent per-task selection
657
- // across their subscription (#4386).
658
- if (routingConfig.enabled && !routingConfig.allow_flat_rate_providers) {
689
+ if (routingConfig.enabled && routingConfig.allow_flat_rate_providers === false) {
659
690
  const primaryModel = resolveModelId(modelConfig.primary, routingEligibleModels, ctx.model?.provider);
660
691
  if (primaryModel) {
661
692
  const primaryFlatRateCtx = buildFlatRateContext(primaryModel.provider, ctx, prefs);
@@ -20,14 +20,15 @@ import {
20
20
  relTaskFile, resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile,
21
21
  } from "./paths.js";
22
22
  import { resolveInlineLevel, loadEffectiveGSDPreferences } from "./preferences.js";
23
+ import { createRepositoryRegistryFromPreferences } from "./repository-registry.js";
23
24
  import { isContextModeEnabled } from "./preferences-types.js";
24
25
  import { parseRoadmap } from "./parsers-legacy.js";
25
26
  import type { GSDState, InlineLevel } from "./types.js";
26
27
  import type { GSDPreferences } from "./preferences.js";
27
- import { join, basename, relative } from "node:path";
28
+ import { join, basename, relative, sep } from "node:path";
28
29
  import { existsSync } from "node:fs";
29
30
  import { computeBudgets, resolveExecutorContextWindow, truncateAtSectionBoundary, type MinimalModelRegistry } from "./context-budget.js";
30
- import { getPendingGates, getPendingGatesForTurn } from "./gsd-db.js";
31
+ import { getGateResults, getPendingGates, getPendingGatesForTurn } from "./gsd-db.js";
31
32
  import {
32
33
  GATE_REGISTRY,
33
34
  assertGateCoverage,
@@ -393,6 +394,37 @@ function formatExecutorConstraints(
393
394
  ].join("\n");
394
395
  }
395
396
 
397
+ /**
398
+ * Builds the Declared Repositories block for parent-workspace planners.
399
+ * Returns "" for single-repo projects so the common-case prompt is unchanged;
400
+ * only parent mode with declared child repos gets the registry list and the
401
+ * targetRepositories assignment instruction.
402
+ */
403
+ export function buildRepoRegistryBlock(base: string): string {
404
+ let registry;
405
+ try {
406
+ registry = createRepositoryRegistryFromPreferences(base, loadEffectiveGSDPreferences(base)?.preferences);
407
+ } catch {
408
+ return "";
409
+ }
410
+ const hasChildRepo = registry.repositories.some((repo) => repo.id !== "project");
411
+ if (registry.mode !== "parent" || !hasChildRepo) return "";
412
+
413
+ const lines = registry.repositories.map((repo) => {
414
+ const relPath = relative(registry.projectRoot, repo.root).split(sep).join("/") || ".";
415
+ const role = repo.role ? ` — ${repo.role}` : "";
416
+ const root = repo.id === "project" ? " (root)" : ` (${relPath})`;
417
+ return `- \`${repo.id}\`${root}${role}`;
418
+ });
419
+ return [
420
+ "### Declared Repositories",
421
+ "",
422
+ ...lines,
423
+ "",
424
+ "This is a parent workspace. Assign each task's `targetRepositories` to the repository id(s) it touches (from the list above). Omit `targetRepositories` to inherit the slice-wide default from `gsd_plan_slice`; set it explicitly when a task differs (e.g. `[\"project\"]` for parent-root work).",
425
+ ].join("\n");
426
+ }
427
+
396
428
  /**
397
429
  * Returns a markdown bullet list of known context file paths for the given
398
430
  * milestone (and optionally slice). Falls back to a generic tool-agnostic
@@ -2504,6 +2536,7 @@ async function renderSlicePrompt(options: {
2504
2536
  inlinedContext,
2505
2537
  dependencySummaries: depContent,
2506
2538
  sourceFilePaths: buildSourceFilePaths(base, mid, sid),
2539
+ repoRegistry: buildRepoRegistryBlock(base),
2507
2540
  executorContextConstraints,
2508
2541
  commitInstruction,
2509
2542
  skillActivation: buildSkillActivationBlock({
@@ -3362,6 +3395,44 @@ export async function buildValidateMilestonePrompt(
3362
3395
  trackPromptContext(contextTelemetry, "outstanding-items", "inline", outstandingBlock);
3363
3396
  }
3364
3397
 
3398
+ const persistedGateFlags: string[] = [];
3399
+ try {
3400
+ const gateLabels = {
3401
+ Q3: "Threat Surface",
3402
+ Q4: "Requirement Impact",
3403
+ } as const;
3404
+ for (const sid of seenValSlices) {
3405
+ for (const gate of getGateResults(mid, sid, "slice")) {
3406
+ if (gate.gate_id !== "Q3" && gate.gate_id !== "Q4") continue;
3407
+ const findings = gate.findings.trim();
3408
+ const rationale = gate.rationale.trim();
3409
+ const verdict = gate.verdict ?? "";
3410
+ const hasNonPassVerdict = verdict !== "" && verdict !== "pass" && verdict !== "omitted";
3411
+ if (!findings && !hasNonPassVerdict) continue;
3412
+
3413
+ const displayVerdict = verdict || gate.status;
3414
+ const detail = findings || rationale || "_No findings text recorded; reconcile the persisted non-pass verdict._";
3415
+ persistedGateFlags.push(`- **${sid} / ${gate.gate_id} (${gateLabels[gate.gate_id]}) / ${displayVerdict}:** ${detail}`);
3416
+ if (findings && rationale) persistedGateFlags.push(` - Rationale: ${rationale}`);
3417
+ }
3418
+ }
3419
+ } catch (err) {
3420
+ logWarning("prompt", `buildValidateMilestonePrompt persisted gate flags lookup failed: ${err instanceof Error ? err.message : String(err)}`);
3421
+ }
3422
+ if (persistedGateFlags.length > 0) {
3423
+ const persistedGateFlagsBlock = [
3424
+ "### Persisted Slice-Level Gate Flags (from quality_gates)",
3425
+ "",
3426
+ "These slice gates recorded findings or non-pass verdicts during execution. Reconcile each against the milestone-level evidence before returning MV03/MV04 verdicts.",
3427
+ "",
3428
+ ...persistedGateFlags,
3429
+ ].join("\n");
3430
+ inlined.push(persistedGateFlagsBlock);
3431
+ trackPromptContext(contextTelemetry, "persisted-slice-gate-flags", "inline", persistedGateFlagsBlock);
3432
+ } else {
3433
+ trackPromptContext(contextTelemetry, "persisted-slice-gate-flags", "skipped", null, "none");
3434
+ }
3435
+
3365
3436
  // Inline existing VALIDATION file if this is a re-validation round
3366
3437
  const validationPath = resolveMilestoneFile(base, mid, "VALIDATION");
3367
3438
  const validationRel = relMilestoneFile(base, mid, "VALIDATION");
@@ -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";
@@ -1849,8 +1851,9 @@ export async function bootstrapAutoSession(
1849
1851
  : ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : "default";
1850
1852
 
1851
1853
  // Flat-rate providers (e.g. GitHub Copilot, claude-code, user-declared
1852
- // subscription proxies, externalCli CLIs) suppress routing at dispatch
1853
- // time (#3453) reflect that in the banner. Thread the same
1854
+ // subscription proxies, externalCli CLIs) suppress routing only when the
1855
+ // user explicitly opts out with allow_flat_rate_providers: false. Reflect
1856
+ // that in the banner. Thread the same
1854
1857
  // FlatRateContext used by selectAndApplyModel so user-declared
1855
1858
  // flat-rate providers and externalCli auto-detection are respected.
1856
1859
  const { isFlatRateProvider, buildFlatRateContext } = await import("./auto-model-selection.js");
@@ -1862,7 +1865,7 @@ export async function bootstrapAutoSession(
1862
1865
  )?.preferences;
1863
1866
  const effectiveProvider = s.autoModeStartModel?.provider ?? ctx.model?.provider;
1864
1867
  const effectivelyEnabled = routingConfig.enabled
1865
- && (routingConfig.allow_flat_rate_providers
1868
+ && (routingConfig.allow_flat_rate_providers !== false
1866
1869
  || !(effectiveProvider && isFlatRateProvider(
1867
1870
  effectiveProvider,
1868
1871
  buildFlatRateContext(effectiveProvider, ctx, bannerPrefs),
@@ -97,6 +97,8 @@ export async function recoverTimedOutUnit(
97
97
  lastProgressAt: Date.now(),
98
98
  progressCount: (runtime?.progressCount ?? 0) + 1,
99
99
  lastProgressKind: reason === "idle" ? "idle-recovery-retry" : "hard-recovery-retry",
100
+ // This steering retry is a fresh chance for the same unit to save a valid result.
101
+ harnessAbort: undefined,
100
102
  });
101
103
 
102
104
  const steeringLines = isEscalation
@@ -222,6 +224,8 @@ export async function recoverTimedOutUnit(
222
224
  lastProgressAt: Date.now(),
223
225
  progressCount: (runtime?.progressCount ?? 0) + 1,
224
226
  lastProgressKind: reason === "idle" ? "idle-recovery-retry" : "hard-recovery-retry",
227
+ // This steering retry is a fresh chance for the same unit to save a valid result.
228
+ harnessAbort: undefined,
225
229
  });
226
230
 
227
231
  const steeringLines = isEscalation
@@ -0,0 +1,237 @@
1
+ // gsd-pi — Auto-worktree branch lifecycle module.
2
+ //
3
+ // Owns milestone branch naming, branch-mode entry, and safe fast-forward of
4
+ // reused milestone branches. Worktree creation/merge code imports this module
5
+ // instead of keeping branch policy inside the legacy auto-worktree barrel.
6
+
7
+ import { GSDError, GSD_GIT_ERROR } from "./errors.js";
8
+ import { readIntegrationBranch } from "./git-service.js";
9
+ import { loadEffectiveGSDPreferences } from "./preferences.js";
10
+ import { debugLog } from "./debug-logger.js";
11
+ import { checkoutBranchWithStashGuard } from "./worktree-git-recovery.js";
12
+ import {
13
+ nativeBranchExists,
14
+ nativeBranchForceReset,
15
+ nativeDetectMainBranch,
16
+ nativeIsAncestor,
17
+ nativeUpdateRef,
18
+ nativeWorktreeList,
19
+ } from "./native-git-bridge.js";
20
+
21
+ /** Returns the git branch name for a milestone worktree (`milestone/<MID>`). */
22
+ export function autoWorktreeBranch(milestoneId: string): string {
23
+ return `milestone/${milestoneId}`;
24
+ }
25
+
26
+ export function _resolveAutoWorktreeStartPoint(
27
+ integrationBranch: string | null | undefined,
28
+ gitMainBranch: string | null | undefined,
29
+ branchExists: (branch: string) => boolean,
30
+ ): string | undefined {
31
+ if (integrationBranch) return integrationBranch;
32
+ return gitMainBranch &&
33
+ typeof gitMainBranch === "string" &&
34
+ gitMainBranch.length > 0 &&
35
+ branchExists(gitMainBranch)
36
+ ? gitMainBranch
37
+ : undefined;
38
+ }
39
+
40
+ /**
41
+ * Enter branch isolation mode for a milestone.
42
+ *
43
+ * Creates `milestone/<MID>` from the integration branch (if it doesn't
44
+ * exist yet) and checks out to it. No worktree directory is created — the
45
+ * project root is the working copy; only HEAD changes.
46
+ *
47
+ * Uses the same 3-tier integration-branch fallback as createAutoWorktree:
48
+ * 1. META.json recorded integration branch
49
+ * 2. git.main_branch preference
50
+ * 3. nativeDetectMainBranch (origin/HEAD auto-detection)
51
+ */
52
+ export function enterBranchModeForMilestone(
53
+ basePath: string,
54
+ milestoneId: string,
55
+ ): void {
56
+ const branch = autoWorktreeBranch(milestoneId);
57
+ const branchExists = nativeBranchExists(basePath, branch);
58
+
59
+ if (!branchExists) {
60
+ // Create the milestone branch from the integration branch start-point.
61
+ const integrationBranch =
62
+ readIntegrationBranch(basePath, milestoneId) ?? undefined;
63
+ const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
64
+ const startPoint =
65
+ _resolveAutoWorktreeStartPoint(
66
+ integrationBranch,
67
+ gitPrefs?.main_branch,
68
+ (branchName) => nativeBranchExists(basePath, branchName),
69
+ ) ??
70
+ nativeDetectMainBranch(basePath);
71
+
72
+ // TOCTOU ancestry guard (Issue #4980 HIGH-3).
73
+ //
74
+ // The outer `branchExists` check is racy: a concurrent process
75
+ // (parallel-orchestrator worker, side-by-side `gsd` instance, or manual
76
+ // `git branch` invocation) may have created the branch with real commits
77
+ // between that check and this point. `nativeBranchForceReset` does
78
+ // `git branch -f`, which silently overwrites the branch ref — orphaning
79
+ // any commits not reachable from `startPoint`. Re-check immediately
80
+ // before the destructive call and refuse if the branch suddenly exists
81
+ // with non-ancestor commits.
82
+ const concurrentlyCreated = nativeBranchExists(basePath, branch);
83
+ if (
84
+ concurrentlyCreated &&
85
+ !nativeIsAncestor(basePath, branch, startPoint)
86
+ ) {
87
+ throw new GSDError(
88
+ GSD_GIT_ERROR,
89
+ `Branch "${branch}" was created concurrently with commits not reachable from "${startPoint}". ` +
90
+ `Refusing to force-reset — would orphan prior work. ` +
91
+ `Resume the existing milestone or run \`git branch -D ${branch}\` to discard.`,
92
+ );
93
+ }
94
+ // nativeBranchForceReset creates (or resets) branch at startPoint,
95
+ // then checkout switches HEAD to it.
96
+ nativeBranchForceReset(basePath, branch, startPoint);
97
+ debugLog("auto-worktree", {
98
+ action: "enterBranchMode",
99
+ milestoneId,
100
+ branch,
101
+ startPoint,
102
+ created: true,
103
+ });
104
+ } else {
105
+ debugLog("auto-worktree", {
106
+ action: "enterBranchMode",
107
+ milestoneId,
108
+ branch,
109
+ reused: true,
110
+ });
111
+ }
112
+
113
+ checkoutBranchWithStashGuard(
114
+ basePath,
115
+ branch,
116
+ `enter-branch-mode:${milestoneId}`,
117
+ );
118
+ }
119
+
120
+ /**
121
+ * True when `branch` is checked out in any worktree listed by
122
+ * `git worktree list --porcelain`. Used to gate ref updates that would
123
+ * otherwise leave a concurrent worktree's HEAD inconsistent with its
124
+ * index/working tree (Codex peer-review of #5538-followup).
125
+ *
126
+ * Best-effort: a `nativeWorktreeList` failure returns true so we err on
127
+ * the side of NOT moving the ref. Better to skip a fast-forward than to
128
+ * silently corrupt another worktree.
129
+ */
130
+ export function _isBranchCheckedOutElsewhere(
131
+ basePath: string,
132
+ branch: string,
133
+ ): boolean {
134
+ try {
135
+ const entries = nativeWorktreeList(basePath);
136
+ return entries.some((entry) => entry.branch === branch);
137
+ } catch {
138
+ return true;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Resolve the integration branch using the same 3-tier fallback as the
144
+ * fresh-create path: META.json → git.main_branch preference → detected
145
+ * main branch. Returns null when no usable target exists.
146
+ */
147
+ function resolveIntegrationBranchForReuse(
148
+ basePath: string,
149
+ milestoneId: string,
150
+ ): string | null {
151
+ const fromMeta = readIntegrationBranch(basePath, milestoneId);
152
+ if (fromMeta) return fromMeta;
153
+
154
+ const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
155
+ const fromPref = gitPrefs?.main_branch &&
156
+ typeof gitPrefs.main_branch === "string" &&
157
+ gitPrefs.main_branch.length > 0 &&
158
+ nativeBranchExists(basePath, gitPrefs.main_branch)
159
+ ? gitPrefs.main_branch
160
+ : null;
161
+ if (fromPref) return fromPref;
162
+
163
+ try {
164
+ return nativeDetectMainBranch(basePath);
165
+ } catch {
166
+ return null;
167
+ }
168
+ }
169
+
170
+ /**
171
+ * When reusing an existing milestone branch, fast-forward it onto the
172
+ * integration branch when that's safe (branch is a strict ancestor of
173
+ * integration — no commits would be lost). Skips when the branch has its
174
+ * own commits ahead of integration, when the integration branch can't be
175
+ * resolved, or when any git operation fails — the merge gate at milestone
176
+ * completion will surface real divergence as a conflict.
177
+ *
178
+ * The previous behavior re-attached the worktree to whatever stale tip
179
+ * the branch held, which caused new milestone work to fork from a base
180
+ * missing prior milestones' merges (#5538-followup).
181
+ */
182
+ export function fastForwardReusedMilestoneBranchIfSafe(
183
+ basePath: string,
184
+ milestoneId: string,
185
+ branch: string,
186
+ ): void {
187
+ try {
188
+ const integrationBranch = resolveIntegrationBranchForReuse(
189
+ basePath,
190
+ milestoneId,
191
+ );
192
+ if (!integrationBranch || integrationBranch === branch) return;
193
+ if (!nativeBranchExists(basePath, integrationBranch)) return;
194
+
195
+ // Pure fast-forward only: branch must be a strict ancestor of integration.
196
+ // If the branch has its own commits ahead, leave it alone.
197
+ if (!nativeIsAncestor(basePath, branch, integrationBranch)) {
198
+ debugLog("createAutoWorktree", {
199
+ phase: "skip-ff-branch-not-ancestor",
200
+ milestoneId,
201
+ branch,
202
+ integration: integrationBranch,
203
+ });
204
+ return;
205
+ }
206
+
207
+ // Codex peer-review: `nativeUpdateRef` succeeds even when the branch is
208
+ // currently checked out in another worktree, leaving that worktree's HEAD
209
+ // inconsistent with its index/work tree. Skip the fast-forward if any
210
+ // listed worktree has this branch checked out — the merge gate at
211
+ // milestone-completion will surface stale-base divergence as a conflict
212
+ // instead of silently corrupting the other worktree's state.
213
+ if (_isBranchCheckedOutElsewhere(basePath, branch)) {
214
+ debugLog("createAutoWorktree", {
215
+ phase: "skip-ff-branch-checked-out-elsewhere",
216
+ milestoneId,
217
+ branch,
218
+ });
219
+ return;
220
+ }
221
+
222
+ nativeUpdateRef(basePath, `refs/heads/${branch}`, integrationBranch);
223
+ debugLog("createAutoWorktree", {
224
+ phase: "fast-forward-reused-branch",
225
+ milestoneId,
226
+ branch,
227
+ integration: integrationBranch,
228
+ });
229
+ } catch (err) {
230
+ debugLog("createAutoWorktree", {
231
+ phase: "fast-forward-reused-branch-failed",
232
+ milestoneId,
233
+ branch,
234
+ error: err instanceof Error ? err.message : String(err),
235
+ });
236
+ }
237
+ }
@@ -0,0 +1,166 @@
1
+ // gsd-pi — Auto-worktree cleanup helpers.
2
+ //
3
+ // Owns shared cleanup primitives used by teardown and merge cleanup paths:
4
+ // same-file DB reconciliation checks, transient project-root state removal,
5
+ // git pathspec conversion for externally-rooted .gsd paths, and expected
6
+ // unlink error classification.
7
+
8
+ import { execFileSync } from "node:child_process";
9
+ import { existsSync, realpathSync, unlinkSync } from "node:fs";
10
+ import { isAbsolute, join, relative } from "node:path";
11
+
12
+ import { gsdRoot } from "./paths.js";
13
+ import { logWarning } from "./workflow-logger.js";
14
+
15
+ function isSamePath(a: string, b: string): boolean {
16
+ try {
17
+ return realpathSync(a) === realpathSync(b);
18
+ } catch (e) {
19
+ if ((e as NodeJS.ErrnoException).code === "ENOENT") return false;
20
+ logWarning("worktree", `isSamePath failed: ${(e as Error).message}`);
21
+ return false;
22
+ }
23
+ }
24
+
25
+ export function _isSamePath(a: string, b: string): boolean {
26
+ return isSamePath(a, b);
27
+ }
28
+
29
+ export function _shouldReconcileWorktreeDb(
30
+ worktreeDbPath: string,
31
+ mainDbPath: string,
32
+ pathExists: (path: string) => boolean = existsSync,
33
+ samePath: (a: string, b: string) => boolean = isSamePath,
34
+ ): boolean {
35
+ return pathExists(worktreeDbPath) && !samePath(worktreeDbPath, mainDbPath);
36
+ }
37
+
38
+ export function _isExpectedWorktreeUnlinkError(
39
+ code: string | undefined,
40
+ ): boolean {
41
+ return code === "ENOENT" || code === "EISDIR";
42
+ }
43
+
44
+ function gitPathspecForWorktreePath(
45
+ basePath: string,
46
+ targetPath: string,
47
+ ): string | null {
48
+ let base = basePath;
49
+ let target = targetPath;
50
+ try {
51
+ base = execFileSync("git", ["rev-parse", "--show-toplevel"], {
52
+ cwd: basePath,
53
+ stdio: ["ignore", "pipe", "ignore"],
54
+ encoding: "utf-8",
55
+ }).trim() || basePath;
56
+ } catch {
57
+ /* keep original */
58
+ void base;
59
+ }
60
+ try {
61
+ base = realpathSync.native(base);
62
+ } catch {
63
+ /* keep original */
64
+ void base;
65
+ }
66
+ try {
67
+ target = realpathSync.native(targetPath);
68
+ } catch {
69
+ /* keep original */
70
+ void target;
71
+ }
72
+
73
+ const rel = relative(base, target);
74
+ if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) return null;
75
+ return rel.replaceAll("\\", "/");
76
+ }
77
+
78
+ export function _gitPathspecForWorktreePath(
79
+ basePath: string,
80
+ targetPath: string,
81
+ ): string | null {
82
+ return gitPathspecForWorktreePath(basePath, targetPath);
83
+ }
84
+
85
+ export function clearProjectRootStateFiles(
86
+ basePath: string,
87
+ milestoneId: string,
88
+ ): void {
89
+ const gsdDir = gsdRoot(basePath);
90
+ // Phase C pt 2: auto.lock removed from this list — the file is gone
91
+ // (migrated to the workers + unit_dispatches + runtime_kv tables). The
92
+ // remaining transient files (STATE.md, {MID}-META.json) are still
93
+ // worth removing on teardown.
94
+ const transientFiles = [
95
+ join(gsdDir, "STATE.md"),
96
+ join(gsdDir, "milestones", milestoneId, `${milestoneId}-META.json`),
97
+ ];
98
+
99
+ for (const file of transientFiles) {
100
+ try {
101
+ unlinkSync(file);
102
+ } catch (err) {
103
+ // ENOENT is expected — file may not exist (#3597)
104
+ if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
105
+ logWarning(
106
+ "worktree",
107
+ `file unlink failed: ${err instanceof Error ? err.message : String(err)}`,
108
+ );
109
+ }
110
+ }
111
+ }
112
+
113
+ // Clean up legacy synced milestone directories and runtime/units.
114
+ // Older versions copied these into the project root during execution.
115
+ // If they remain as untracked files when we attempt
116
+ // `git merge --squash`, git rejects the merge with "local changes would
117
+ // be overwritten", causing silent data loss (#1738).
118
+ const syncedDirs = [
119
+ join(gsdDir, "milestones", milestoneId),
120
+ join(gsdDir, "runtime", "units"),
121
+ ];
122
+
123
+ for (const dir of syncedDirs) {
124
+ try {
125
+ if (!existsSync(dir)) continue;
126
+
127
+ const pathspec = gitPathspecForWorktreePath(basePath, dir);
128
+ if (!pathspec) continue;
129
+
130
+ // Only remove files that are untracked by git — tracked files are
131
+ // managed by the branch checkout and should not be deleted.
132
+ const untrackedOutput = execFileSync(
133
+ "git",
134
+ ["ls-files", "--others", "--exclude-standard", pathspec],
135
+ {
136
+ cwd: basePath,
137
+ stdio: ["ignore", "pipe", "pipe"],
138
+ encoding: "utf-8",
139
+ },
140
+ ).trim();
141
+ if (!untrackedOutput) continue;
142
+
143
+ for (const f of untrackedOutput.split("\n").filter(Boolean)) {
144
+ try {
145
+ unlinkSync(join(basePath, f));
146
+ } catch (err) {
147
+ // ENOENT/EISDIR are expected for already-removed or
148
+ // directory entries (#3597).
149
+ const code = (err as NodeJS.ErrnoException).code;
150
+ if (!_isExpectedWorktreeUnlinkError(code)) {
151
+ logWarning(
152
+ "worktree",
153
+ `untracked file unlink failed: ${err instanceof Error ? err.message : String(err)}`,
154
+ );
155
+ }
156
+ }
157
+ }
158
+ } catch (err) {
159
+ /* non-fatal — git command may fail if not in repo */
160
+ logWarning(
161
+ "worktree",
162
+ `untracked file cleanup failed: ${err instanceof Error ? err.message : String(err)}`,
163
+ );
164
+ }
165
+ }
166
+ }