@opengsd/gsd-pi 1.5.0 → 1.6.0-dev.aa7f94e8

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 (633) 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 +23 -6
  15. package/dist/resources/extensions/gsd/auto-prompts.js +49 -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 +118 -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/browser-daemon-auto-prep.js +68 -2
  50. package/dist/resources/extensions/gsd/codebase-generator.js +7 -1
  51. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  52. package/dist/resources/extensions/gsd/commands-workflow-templates.js +3 -3
  53. package/dist/resources/extensions/gsd/compat/compat-marker.js +44 -0
  54. package/dist/resources/extensions/gsd/config-overlay.js +7 -2
  55. package/dist/resources/extensions/gsd/db/engine.js +33 -0
  56. package/dist/resources/extensions/gsd/db/queries.js +9 -9
  57. package/dist/resources/extensions/gsd/db/writers/cascades.js +20 -2
  58. package/dist/resources/extensions/gsd/db-adapter.js +30 -3
  59. package/dist/resources/extensions/gsd/docs/preferences-reference.md +3 -3
  60. package/dist/resources/extensions/gsd/doctor-engine-checks.js +93 -11
  61. package/dist/resources/extensions/gsd/flat-phase-migration.js +32 -3
  62. package/dist/resources/extensions/gsd/forensics.js +1 -1
  63. package/dist/resources/extensions/gsd/git-conflict-resolve.js +2 -2
  64. package/dist/resources/extensions/gsd/git-service.js +45 -0
  65. package/dist/resources/extensions/gsd/gsd-db.js +23 -11
  66. package/dist/resources/extensions/gsd/guided-flow.js +22 -17
  67. package/dist/resources/extensions/gsd/journal.js +1 -1
  68. package/dist/resources/extensions/gsd/markdown-renderer.js +34 -79
  69. package/dist/resources/extensions/gsd/md-importer.js +89 -23
  70. package/dist/resources/extensions/gsd/metrics.js +2 -2
  71. package/dist/resources/extensions/gsd/migration-auto-check.js +30 -3
  72. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +11 -0
  73. package/dist/resources/extensions/gsd/milestone-settlement.js +1 -1
  74. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  75. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -1
  76. package/dist/resources/extensions/gsd/paths.js +87 -52
  77. package/dist/resources/extensions/gsd/post-unit-hooks.js +27 -0
  78. package/dist/resources/extensions/gsd/preferences-models.js +66 -15
  79. package/dist/resources/extensions/gsd/preferences-skills.js +10 -16
  80. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  81. package/dist/resources/extensions/gsd/preferences-validation.js +148 -10
  82. package/dist/resources/extensions/gsd/preferences.js +20 -0
  83. package/dist/resources/extensions/gsd/prompts/system.md +6 -6
  84. package/dist/resources/extensions/gsd/quick.js +12 -3
  85. package/dist/resources/extensions/gsd/reopen-reason.js +98 -0
  86. package/dist/resources/extensions/gsd/rule-registry.js +106 -10
  87. package/dist/resources/extensions/gsd/session-status-io.js +31 -0
  88. package/dist/resources/extensions/gsd/skill-discovery.js +36 -23
  89. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +2 -1
  90. package/dist/resources/extensions/gsd/state/derive/from-db.js +88 -153
  91. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +1 -10
  92. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +3 -24
  93. package/dist/resources/extensions/gsd/state-reconciliation/index.js +10 -0
  94. package/dist/resources/extensions/gsd/tool-contract.js +14 -0
  95. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -5
  96. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +16 -10
  97. package/dist/resources/extensions/gsd/tools/reopen-slice.js +5 -0
  98. package/dist/resources/extensions/gsd/tools/reopen-task.js +28 -5
  99. package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -8
  100. package/dist/resources/extensions/gsd/uat-dispatch.js +94 -0
  101. package/dist/resources/extensions/gsd/unit-registry.js +12 -2
  102. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +1 -1
  103. package/dist/resources/extensions/gsd/uok/audit-toggle.js +31 -2
  104. package/dist/resources/extensions/gsd/uok/audit.js +3 -0
  105. package/dist/resources/extensions/gsd/uok/gate-runner.js +22 -30
  106. package/dist/resources/extensions/gsd/uok/gitops.js +18 -15
  107. package/dist/resources/extensions/gsd/uok/kernel.js +120 -46
  108. package/dist/resources/extensions/gsd/uok/model-policy.js +17 -14
  109. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -1
  110. package/dist/resources/extensions/gsd/workflow-event-ledger.js +1 -1
  111. package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
  112. package/dist/resources/extensions/gsd/workflow-projections.js +9 -26
  113. package/dist/resources/extensions/gsd/workspace-git-preflight.js +2 -2
  114. package/dist/resources/extensions/gsd/workspace.js +5 -14
  115. package/dist/resources/extensions/gsd/worktree-command.js +1 -1
  116. package/dist/resources/extensions/gsd/worktree-lifecycle.js +14 -9
  117. package/dist/resources/extensions/gsd/worktree-reentry.js +2 -1
  118. package/dist/resources/extensions/shared/gsd-browser-cli.js +51 -5
  119. package/dist/resources/extensions/shared/interview-ui.js +62 -9
  120. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  121. package/dist/web/standalone/.next/BUILD_ID +1 -1
  122. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  123. package/dist/web/standalone/.next/build-manifest.json +3 -3
  124. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  125. package/dist/web/standalone/.next/required-server-files.json +3 -3
  126. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  127. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  137. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  145. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  156. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  162. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  170. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  172. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  178. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  184. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  190. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  202. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  204. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  205. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  208. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  213. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  216. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  218. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  221. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  223. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  224. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  226. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  227. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  228. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  229. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  230. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  231. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  232. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  233. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  234. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  235. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  236. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  237. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  238. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  239. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  240. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  241. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  242. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  243. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  244. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  245. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  246. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  247. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  248. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  249. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  250. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  251. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  252. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  253. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  254. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  255. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  256. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  257. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  258. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  259. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  260. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  261. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  262. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  263. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  264. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  265. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  266. package/dist/web/standalone/.next/server/app/index.html +1 -1
  267. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  268. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  269. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  270. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  271. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  272. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  273. package/dist/web/standalone/.next/server/app/page.js +2 -2
  274. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  275. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  276. package/dist/web/standalone/.next/server/chunks/{1128.js → 1991.js} +1 -1
  277. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  278. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  279. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  280. package/dist/web/standalone/.next/server/middleware.js +3 -3
  281. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  282. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  283. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  284. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  285. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  286. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  287. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  288. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  289. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  290. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  291. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  292. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  293. package/dist/web/standalone/server.js +1 -1
  294. package/dist/worktree-cli-create.d.ts +10 -0
  295. package/dist/worktree-cli-create.js +11 -0
  296. package/dist/worktree-cli-format.d.ts +12 -0
  297. package/dist/worktree-cli-format.js +38 -0
  298. package/dist/worktree-cli-plan.d.ts +16 -0
  299. package/dist/worktree-cli-plan.js +19 -0
  300. package/dist/worktree-cli-session.d.ts +13 -0
  301. package/dist/worktree-cli-session.js +18 -0
  302. package/dist/worktree-cli-status.d.ts +35 -0
  303. package/dist/worktree-cli-status.js +54 -0
  304. package/dist/worktree-cli.d.ts +1 -16
  305. package/dist/worktree-cli.js +28 -122
  306. package/integrations/hermes/open_gsd_hermes/gsd_client.py +25 -36
  307. package/integrations/hermes/pyproject.toml +1 -1
  308. package/integrations/hermes/tests/test_gsd_client_timeout.py +4 -4
  309. package/package.json +6 -6
  310. package/packages/cloud-mcp-gateway/package.json +2 -2
  311. package/packages/contracts/package.json +1 -1
  312. package/packages/daemon/dist/cloud-cli.d.ts +1 -1
  313. package/packages/daemon/dist/cloud-cli.d.ts.map +1 -1
  314. package/packages/daemon/dist/cloud-cli.js +42 -2
  315. package/packages/daemon/dist/cloud-cli.js.map +1 -1
  316. package/packages/daemon/dist/cloud-config.d.ts +1 -0
  317. package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
  318. package/packages/daemon/dist/cloud-config.js +1 -1
  319. package/packages/daemon/dist/cloud-config.js.map +1 -1
  320. package/packages/daemon/dist/device-flow.d.ts +24 -0
  321. package/packages/daemon/dist/device-flow.d.ts.map +1 -0
  322. package/packages/daemon/dist/device-flow.js +128 -0
  323. package/packages/daemon/dist/device-flow.js.map +1 -0
  324. package/packages/daemon/dist/device-flow.test.d.ts +2 -0
  325. package/packages/daemon/dist/device-flow.test.d.ts.map +1 -0
  326. package/packages/daemon/dist/device-flow.test.js +172 -0
  327. package/packages/daemon/dist/device-flow.test.js.map +1 -0
  328. package/packages/daemon/dist/orchestrator-agent.d.ts +21 -0
  329. package/packages/daemon/dist/orchestrator-agent.d.ts.map +1 -0
  330. package/packages/daemon/dist/orchestrator-agent.js +113 -0
  331. package/packages/daemon/dist/orchestrator-agent.js.map +1 -0
  332. package/packages/daemon/dist/orchestrator-tools.d.ts +12 -0
  333. package/packages/daemon/dist/orchestrator-tools.d.ts.map +1 -0
  334. package/packages/daemon/dist/orchestrator-tools.js +137 -0
  335. package/packages/daemon/dist/orchestrator-tools.js.map +1 -0
  336. package/packages/daemon/dist/orchestrator.d.ts +4 -56
  337. package/packages/daemon/dist/orchestrator.d.ts.map +1 -1
  338. package/packages/daemon/dist/orchestrator.js +13 -303
  339. package/packages/daemon/dist/orchestrator.js.map +1 -1
  340. package/packages/daemon/dist/orchestrator.test.js +11 -1
  341. package/packages/daemon/dist/orchestrator.test.js.map +1 -1
  342. package/packages/daemon/package.json +5 -5
  343. package/packages/gsd-agent-core/dist/export-html/template.js +53 -4
  344. package/packages/gsd-agent-core/package.json +5 -5
  345. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  346. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +3 -2
  347. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  348. package/packages/gsd-agent-modes/package.json +7 -7
  349. package/packages/gsd-cloud/README.md +34 -0
  350. package/packages/gsd-cloud/bin/gsd-cloud.js +27 -0
  351. package/packages/gsd-cloud/package.json +38 -0
  352. package/packages/mcp-server/package.json +4 -4
  353. package/packages/native/package.json +1 -1
  354. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  355. package/packages/pi-agent-core/dist/agent-loop.js +14 -9
  356. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  357. package/packages/pi-agent-core/package.json +1 -1
  358. package/packages/pi-ai/dist/index.d.ts +1 -0
  359. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  360. package/packages/pi-ai/dist/index.js +1 -0
  361. package/packages/pi-ai/dist/index.js.map +1 -1
  362. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  363. package/packages/pi-ai/dist/providers/transform-messages.js +7 -3
  364. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  365. package/packages/pi-ai/dist/tool-result-content.d.ts +3 -0
  366. package/packages/pi-ai/dist/tool-result-content.d.ts.map +1 -0
  367. package/packages/pi-ai/dist/tool-result-content.js +62 -0
  368. package/packages/pi-ai/dist/tool-result-content.js.map +1 -0
  369. package/packages/pi-ai/dist/types.d.ts +8 -20
  370. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  371. package/packages/pi-ai/dist/types.js.map +1 -1
  372. package/packages/pi-ai/package.json +1 -1
  373. package/packages/pi-coding-agent/dist/core/package-manager.d.ts +9 -0
  374. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  375. package/packages/pi-coding-agent/dist/core/package-manager.js +74 -53
  376. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  377. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +6 -0
  378. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  379. package/packages/pi-coding-agent/dist/core/resource-loader.js +30 -2
  380. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  381. package/packages/pi-coding-agent/dist/core/skill-directories.d.ts +66 -0
  382. package/packages/pi-coding-agent/dist/core/skill-directories.d.ts.map +1 -0
  383. package/packages/pi-coding-agent/dist/core/skill-directories.js +138 -0
  384. package/packages/pi-coding-agent/dist/core/skill-directories.js.map +1 -0
  385. package/packages/pi-coding-agent/dist/core/skills.d.ts +4 -1
  386. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  387. package/packages/pi-coding-agent/dist/core/skills.js +4 -1
  388. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  389. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  390. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  391. package/packages/pi-coding-agent/dist/index.js +1 -0
  392. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  393. package/packages/pi-coding-agent/package.json +7 -7
  394. package/packages/pi-tui/package.json +2 -2
  395. package/packages/rpc-client/package.json +2 -2
  396. package/pkg/dist/core/export-html/template.js +53 -4
  397. package/pkg/package.json +1 -1
  398. package/src/resources/extensions/ask-user-questions.ts +1 -1
  399. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +146 -33
  400. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +44 -0
  401. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +93 -0
  402. package/src/resources/extensions/gsd/activity-log.ts +1 -1
  403. package/src/resources/extensions/gsd/auto/closeout.ts +114 -7
  404. package/src/resources/extensions/gsd/auto/orchestrator.ts +21 -14
  405. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +6 -3
  406. package/src/resources/extensions/gsd/auto/unit-phase.ts +5 -9
  407. package/src/resources/extensions/gsd/auto-artifact-paths.ts +14 -4
  408. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +13 -7
  409. package/src/resources/extensions/gsd/auto-dispatch.ts +77 -16
  410. package/src/resources/extensions/gsd/auto-model-selection.ts +33 -1
  411. package/src/resources/extensions/gsd/auto-post-unit.ts +26 -5
  412. package/src/resources/extensions/gsd/auto-prompts.ts +73 -113
  413. package/src/resources/extensions/gsd/auto-recovery.ts +50 -6
  414. package/src/resources/extensions/gsd/auto-start.ts +62 -31
  415. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -2
  416. package/src/resources/extensions/gsd/auto-timers.ts +9 -2
  417. package/src/resources/extensions/gsd/auto-worktree-branch-lifecycle.ts +237 -0
  418. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +166 -0
  419. package/src/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.ts +37 -0
  420. package/src/resources/extensions/gsd/auto-worktree-creation.ts +171 -0
  421. package/src/resources/extensions/gsd/auto-worktree-entry.ts +154 -0
  422. package/src/resources/extensions/gsd/auto-worktree-merge-already-merged.ts +161 -0
  423. package/src/resources/extensions/gsd/auto-worktree-merge-branch-head.ts +83 -0
  424. package/src/resources/extensions/gsd/auto-worktree-merge-cleanup.ts +132 -0
  425. package/src/resources/extensions/gsd/auto-worktree-merge-code-changes.ts +71 -0
  426. package/src/resources/extensions/gsd/auto-worktree-merge-db-ready.ts +112 -0
  427. package/src/resources/extensions/gsd/auto-worktree-merge-integration-branch.ts +99 -0
  428. package/src/resources/extensions/gsd/auto-worktree-merge-message.ts +166 -0
  429. package/src/resources/extensions/gsd/auto-worktree-merge-pre-teardown.ts +93 -0
  430. package/src/resources/extensions/gsd/auto-worktree-merge-stash.ts +213 -0
  431. package/src/resources/extensions/gsd/auto-worktree-merge.ts +391 -0
  432. package/src/resources/extensions/gsd/auto-worktree-milestone-shelter.ts +159 -0
  433. package/src/resources/extensions/gsd/auto-worktree-path-resolution.ts +6 -0
  434. package/src/resources/extensions/gsd/auto-worktree-path-utils.ts +10 -0
  435. package/src/resources/extensions/gsd/auto-worktree-resource-version.ts +44 -0
  436. package/src/resources/extensions/gsd/auto-worktree-runtime-cleanup.ts +119 -0
  437. package/src/resources/extensions/gsd/auto-worktree-session-registry.ts +71 -0
  438. package/src/resources/extensions/gsd/auto-worktree-sync.ts +370 -0
  439. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +161 -0
  440. package/src/resources/extensions/gsd/auto-worktree.ts +69 -2429
  441. package/src/resources/extensions/gsd/auto.ts +126 -47
  442. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -1
  443. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +20 -2
  444. package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
  445. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +218 -27
  446. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +77 -1
  447. package/src/resources/extensions/gsd/codebase-generator.ts +7 -1
  448. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  449. package/src/resources/extensions/gsd/commands-workflow-templates.ts +3 -3
  450. package/src/resources/extensions/gsd/compat/compat-marker.ts +47 -0
  451. package/src/resources/extensions/gsd/config-overlay.ts +7 -1
  452. package/src/resources/extensions/gsd/db/engine.ts +36 -0
  453. package/src/resources/extensions/gsd/db/queries.ts +9 -9
  454. package/src/resources/extensions/gsd/db/writers/cascades.ts +23 -1
  455. package/src/resources/extensions/gsd/db-adapter.ts +29 -3
  456. package/src/resources/extensions/gsd/docs/preferences-reference.md +3 -3
  457. package/src/resources/extensions/gsd/doctor-engine-checks.ts +109 -10
  458. package/src/resources/extensions/gsd/flat-phase-migration.ts +34 -3
  459. package/src/resources/extensions/gsd/forensics.ts +1 -1
  460. package/src/resources/extensions/gsd/git-conflict-resolve.ts +2 -2
  461. package/src/resources/extensions/gsd/git-service.ts +53 -0
  462. package/src/resources/extensions/gsd/gsd-db.ts +33 -11
  463. package/src/resources/extensions/gsd/guided-flow.ts +26 -18
  464. package/src/resources/extensions/gsd/journal.ts +1 -1
  465. package/src/resources/extensions/gsd/markdown-renderer.ts +52 -91
  466. package/src/resources/extensions/gsd/md-importer.ts +93 -22
  467. package/src/resources/extensions/gsd/metrics.ts +2 -2
  468. package/src/resources/extensions/gsd/migration-auto-check.ts +32 -3
  469. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +15 -0
  470. package/src/resources/extensions/gsd/milestone-settlement.ts +1 -1
  471. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  472. package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -1
  473. package/src/resources/extensions/gsd/paths.ts +108 -51
  474. package/src/resources/extensions/gsd/post-unit-hooks.ts +32 -0
  475. package/src/resources/extensions/gsd/preferences-models.ts +74 -20
  476. package/src/resources/extensions/gsd/preferences-skills.ts +10 -16
  477. package/src/resources/extensions/gsd/preferences-types.ts +54 -1
  478. package/src/resources/extensions/gsd/preferences-validation.ts +146 -9
  479. package/src/resources/extensions/gsd/preferences.ts +20 -0
  480. package/src/resources/extensions/gsd/prompts/system.md +6 -6
  481. package/src/resources/extensions/gsd/quick.ts +11 -3
  482. package/src/resources/extensions/gsd/reopen-reason.ts +109 -0
  483. package/src/resources/extensions/gsd/rule-registry.ts +111 -9
  484. package/src/resources/extensions/gsd/session-status-io.ts +34 -0
  485. package/src/resources/extensions/gsd/skill-discovery.ts +47 -23
  486. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -1
  487. package/src/resources/extensions/gsd/state/derive/from-db.ts +201 -157
  488. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +1 -9
  489. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +2 -22
  490. package/src/resources/extensions/gsd/state-reconciliation/index.ts +14 -0
  491. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +169 -1
  492. package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +2 -1
  493. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +41 -2
  494. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +48 -1
  495. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +57 -0
  496. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +1 -1
  497. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +29 -1
  498. package/src/resources/extensions/gsd/tests/auto-timeout-recovery-supervisor-inflight-guard.test.ts +159 -0
  499. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +2 -1
  500. package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +1 -1
  501. package/src/resources/extensions/gsd/tests/auto-worktree-merge-already-merged.test.ts +177 -0
  502. package/src/resources/extensions/gsd/tests/auto-worktree-merge-branch-head.test.ts +118 -0
  503. package/src/resources/extensions/gsd/tests/auto-worktree-merge-cleanup.test.ts +115 -0
  504. package/src/resources/extensions/gsd/tests/auto-worktree-merge-code-changes.test.ts +76 -0
  505. package/src/resources/extensions/gsd/tests/auto-worktree-merge-db-ready.test.ts +140 -0
  506. package/src/resources/extensions/gsd/tests/auto-worktree-merge-integration-branch.test.ts +123 -0
  507. package/src/resources/extensions/gsd/tests/auto-worktree-merge-message.test.ts +114 -0
  508. package/src/resources/extensions/gsd/tests/auto-worktree-merge-pre-teardown.test.ts +84 -0
  509. package/src/resources/extensions/gsd/tests/auto-worktree-merge-stash.test.ts +70 -0
  510. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-shelter.test.ts +52 -0
  511. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +6 -6
  512. package/src/resources/extensions/gsd/tests/auto-worktree-resource-version.test.ts +59 -0
  513. package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +3 -1
  514. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +26 -0
  515. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  516. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +3 -1
  517. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +85 -0
  518. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +45 -0
  519. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +1 -1
  520. package/src/resources/extensions/gsd/tests/db-adapter.test.ts +39 -0
  521. package/src/resources/extensions/gsd/tests/db-writable-probe.test.ts +66 -0
  522. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -0
  523. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +174 -0
  524. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +1 -1
  525. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +71 -1
  526. package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +46 -1
  527. package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +72 -32
  528. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +40 -0
  529. package/src/resources/extensions/gsd/tests/import-completion-lost-update.test.ts +196 -0
  530. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +4 -6
  531. package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +2 -1
  532. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +3 -3
  533. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +7 -8
  534. package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +2 -5
  535. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +76 -0
  536. package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +1 -1
  537. package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +1 -1
  538. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +2 -1
  539. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +5 -7
  540. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +88 -1
  541. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +2 -4
  542. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -15
  543. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +1 -1
  544. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +1 -1
  545. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +1 -1
  546. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +91 -0
  547. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +2 -1
  548. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +439 -0
  549. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +24 -0
  550. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +1 -1
  551. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -3
  552. package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +1 -1
  553. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +0 -1
  554. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +269 -0
  555. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +8 -1
  556. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +1 -4
  557. package/src/resources/extensions/gsd/tests/preferences.test.ts +19 -0
  558. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +5 -0
  559. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +54 -0
  560. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +49 -1
  561. package/src/resources/extensions/gsd/tests/reopen-reason.test.ts +117 -0
  562. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +52 -0
  563. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +95 -1
  564. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
  565. package/src/resources/extensions/gsd/tests/sibling-model-fallbacks.test.ts +189 -0
  566. package/src/resources/extensions/gsd/tests/single-field-model-thinking.test.ts +156 -0
  567. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +46 -0
  568. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +6 -1
  569. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -5
  570. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +32 -0
  571. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +2 -1
  572. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +2 -1
  573. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +1 -1
  574. package/src/resources/extensions/gsd/tests/supervisor-model-swap-inflight-guard.test.ts +181 -0
  575. package/src/resources/extensions/gsd/tests/supervisor-model-swap-thinking-clamp.test.ts +122 -0
  576. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +1 -1
  577. package/src/resources/extensions/gsd/tests/system-flat-phase-layout.test.ts +33 -0
  578. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +4 -4
  579. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +2 -1
  580. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +4 -4
  581. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +196 -0
  582. package/src/resources/extensions/gsd/tests/uat-dispatch.test.ts +211 -0
  583. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +1 -1
  584. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +26 -1
  585. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +39 -0
  586. package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +226 -2
  587. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +6 -0
  588. package/src/resources/extensions/gsd/tests/worker-resume-wait.test.ts +73 -0
  589. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +213 -2
  590. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -1
  591. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +1 -1
  592. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +1 -3
  593. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +1 -1
  594. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +1 -1
  595. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +1 -1
  596. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +1 -1
  597. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +2 -1
  598. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +5 -2
  599. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +1 -1
  600. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +1 -1
  601. package/src/resources/extensions/gsd/tool-contract.ts +29 -0
  602. package/src/resources/extensions/gsd/tools/complete-milestone.ts +9 -5
  603. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +19 -8
  604. package/src/resources/extensions/gsd/tools/reopen-slice.ts +5 -0
  605. package/src/resources/extensions/gsd/tools/reopen-task.ts +28 -5
  606. package/src/resources/extensions/gsd/tools/validate-milestone.ts +13 -9
  607. package/src/resources/extensions/gsd/types.ts +23 -4
  608. package/src/resources/extensions/gsd/uat-dispatch.ts +176 -0
  609. package/src/resources/extensions/gsd/unit-registry.ts +16 -2
  610. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +1 -1
  611. package/src/resources/extensions/gsd/uok/audit-toggle.ts +32 -2
  612. package/src/resources/extensions/gsd/uok/audit.ts +2 -0
  613. package/src/resources/extensions/gsd/uok/gate-runner.ts +26 -36
  614. package/src/resources/extensions/gsd/uok/gitops.ts +21 -18
  615. package/src/resources/extensions/gsd/uok/kernel.ts +169 -48
  616. package/src/resources/extensions/gsd/uok/model-policy.ts +20 -17
  617. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -1
  618. package/src/resources/extensions/gsd/workflow-event-ledger.ts +1 -1
  619. package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
  620. package/src/resources/extensions/gsd/workflow-projections.ts +9 -24
  621. package/src/resources/extensions/gsd/workspace-git-preflight.ts +2 -2
  622. package/src/resources/extensions/gsd/workspace.ts +5 -21
  623. package/src/resources/extensions/gsd/worktree-command.ts +1 -1
  624. package/src/resources/extensions/gsd/worktree-lifecycle.ts +19 -15
  625. package/src/resources/extensions/gsd/worktree-reentry.ts +2 -1
  626. package/src/resources/extensions/shared/gsd-browser-cli.ts +64 -7
  627. package/src/resources/extensions/shared/interview-ui.ts +58 -11
  628. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +32 -0
  629. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  630. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  631. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  632. /package/dist/web/standalone/.next/static/{bCg3aYrFN1DKZr2dqgE7L → XFuMvz26Zb_lrrR-8dvkd}/_buildManifest.js +0 -0
  633. /package/dist/web/standalone/.next/static/{bCg3aYrFN1DKZr2dqgE7L → XFuMvz26Zb_lrrR-8dvkd}/_ssgManifest.js +0 -0
@@ -116,7 +116,8 @@ import {
116
116
  } from "./auto-tool-tracking.js";
117
117
  import { closeoutUnit } from "./auto-unit-closeout.js";
118
118
  import { recoverTimedOutUnit } from "./auto-timeout-recovery.js";
119
- import { selectAndApplyModel, resolveModelId, clearToolBaseline } from "./auto-model-selection.js";
119
+ import { selectAndApplyModel, resolveModelId, clearToolBaseline, isModelUnavailable, applyThinkingLevelForModel } from "./auto-model-selection.js";
120
+ import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
120
121
  import { resetRoutingHistory, recordOutcome } from "./routing-history.js";
121
122
  import {
122
123
  checkPostUnitHooks,
@@ -127,6 +128,7 @@ import {
127
128
  runPreDispatchHooks,
128
129
  persistHookState,
129
130
  restoreHookState,
131
+ reconcileRestoredHookDispatch,
130
132
  clearPersistedHookState,
131
133
  } from "./post-unit-hooks.js";
132
134
  import { runGSDDoctor, rebuildState } from "./doctor.js";
@@ -177,24 +179,19 @@ import {
177
179
  import { GitServiceImpl } from "./git-service.js";
178
180
  import { nativeCheckoutBranch } from "./native-git-bridge.js";
179
181
  import { getPriorSliceCompletionBlocker } from "./dispatch-guard.js";
180
- import {
181
- createAutoWorktree,
182
- enterAutoWorktree,
183
- enterBranchModeForMilestone,
184
- teardownAutoWorktree,
185
- isInAutoWorktree,
186
- getAutoWorktreePath,
187
- getAutoWorktreeOriginalBase,
188
- mergeMilestoneToMain,
189
- autoWorktreeBranch,
190
- syncWorktreeStateBack,
191
- readResourceVersion,
192
- checkResourcesStale,
193
- escapeStaleWorktree,
194
- } from "./auto-worktree.js";
182
+ import { autoWorktreeBranch, enterBranchModeForMilestone } from "./auto-worktree-branch-lifecycle.js";
183
+ import { createAutoWorktree } from "./auto-worktree-creation.js";
184
+ import { enterAutoWorktree, isInAutoWorktree } from "./auto-worktree-entry.js";
185
+ import { getAutoWorktreePath } from "./auto-worktree-path-resolution.js";
186
+ import { checkResourcesStale, readResourceVersion } from "./auto-worktree-resource-version.js";
187
+ import { escapeStaleWorktree } from "./auto-worktree-runtime-cleanup.js";
188
+ import { teardownWarmedBrowserDaemons } from "./browser-daemon-auto-prep.js";
189
+ import { getAutoWorktreeOriginalBase } from "./auto-worktree-session-registry.js";
190
+ import { syncWorktreeStateBack } from "./auto-worktree-sync.js";
191
+ import { teardownAutoWorktree } from "./auto-worktree-teardown.js";
195
192
  import { pruneQueueOrder } from "./queue-order.js";
196
193
  import { startCommandPolling as _startCommandPolling, isRemoteConfigured } from "../remote-questions/manager.js";
197
- import { createMilestoneMergeTransaction } from "./milestone-merge-transaction.js";
194
+ import { createDefaultMilestoneMergeTransaction } from "./milestone-merge-transaction.js";
198
195
 
199
196
  import { debugLog, isDebugEnabled, writeDebugSummary } from "./debug-logger.js";
200
197
  import {
@@ -621,11 +618,27 @@ export function startAutoDetached(
621
618
  milestoneLock?: string | null;
622
619
  },
623
620
  ): void {
624
- void withDetachedAutoKeepalive(startAuto(ctx, pi, base, verboseMode, options)).catch((err) => {
621
+ void withDetachedAutoKeepalive(startAuto(ctx, pi, base, verboseMode, options)).catch(async (err) => {
625
622
  const message = getErrorMessage(err);
626
623
  ctx.ui.notify(`Auto-start failed: ${message}`, "error");
627
624
  logWarning("engine", `auto start error: ${message}`, { file: "auto.ts" });
628
625
  debugLog("auto-start-failed", { error: message });
626
+ // Backstop cleanup (#1235): if startAuto threw after auto-mode was activated
627
+ // (e.g. an exception during bootstrap, before the loop's try/finally could
628
+ // run cleanupAfterLoopExit), s.active and the on-disk auto lock leak, so the
629
+ // re-entry guard silently no-ops every later /gsd auto until restart. Clear
630
+ // the leaked activation here so a failed start is always recoverable.
631
+ if (s.active) {
632
+ try {
633
+ await cleanupAfterLoopExit(ctx);
634
+ } catch (cleanupErr) {
635
+ logWarning(
636
+ "engine",
637
+ `auto start cleanup failed: ${cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr)}`,
638
+ { file: "auto.ts" },
639
+ );
640
+ }
641
+ }
629
642
  });
630
643
  }
631
644
 
@@ -1478,6 +1491,17 @@ export async function cleanupAfterLoopExit(ctx: ExtensionContext): Promise<void>
1478
1491
  logWarning("session", `lock cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1479
1492
  }
1480
1493
 
1494
+ // Symmetric teardown for the browser-UAT warm-up preflight (#1259): stop any
1495
+ // gsd-browser daemon this session started so the Chrome process does not
1496
+ // linger after the loop exits. Re-warms on the next browser-backed run-uat.
1497
+ try {
1498
+ for (const { projectRoot, error } of teardownWarmedBrowserDaemons()) {
1499
+ logWarning("session", `gsd-browser daemon stop failed for ${projectRoot}: ${error}`, { file: "auto.ts" });
1500
+ }
1501
+ } catch (err) {
1502
+ logWarning("session", `browser daemon teardown failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1503
+ }
1504
+
1481
1505
  // A transient provider-error pause intentionally leaves the paused badge
1482
1506
  // visible so the user still has a resumable auto-mode signal on screen.
1483
1507
  if (!s.paused) {
@@ -2326,7 +2350,7 @@ export function buildWorktreeLifecycleDeps(): WorktreeLifecycleDeps {
2326
2350
  return new GitServiceImpl(basePath, gitConfig);
2327
2351
  },
2328
2352
  worktreeProjection: new WorktreeStateProjection(),
2329
- mergeMilestone: createMilestoneMergeTransaction(mergeMilestoneToMain),
2353
+ mergeMilestone: createDefaultMilestoneMergeTransaction(),
2330
2354
  };
2331
2355
  }
2332
2356
 
@@ -2833,6 +2857,10 @@ export async function startAuto(
2833
2857
  "info",
2834
2858
  );
2835
2859
  restoreHookState(s.basePath);
2860
+ // A restored activeHook has no live dispatch (the sidecar queue is not
2861
+ // persisted); re-enqueue it so the hook runs instead of blocking the next
2862
+ // unrelated unit's close-out (#1246).
2863
+ reconcileRestoredHookDispatch(s.basePath, s.sidecarQueue);
2836
2864
  // Re-sync managed resources on resume so long-lived auto sessions pick up
2837
2865
  // bundled extension updates before resume-time verification/state logic runs.
2838
2866
  // GSD_PKG_ROOT is set by loader.ts and points to the gsd-pi package root.
@@ -2901,15 +2929,18 @@ export async function startAuto(
2901
2929
  debugLog("resume-orchestration-resume", { error: err instanceof Error ? err.message : String(err) });
2902
2930
  }
2903
2931
  startAutoCommandPolling(s.basePath);
2904
- await runAutoLoopWithUok({
2905
- ctx,
2906
- pi,
2907
- s,
2908
- deps: loopDeps,
2909
- runKernelLoop: runUokKernelLoop,
2910
- runLegacyLoop: runLegacyAutoLoop,
2911
- });
2912
- await cleanupAfterLoopExit(ctx);
2932
+ try {
2933
+ await runAutoLoopWithUok({
2934
+ ctx,
2935
+ pi,
2936
+ s,
2937
+ deps: loopDeps,
2938
+ runKernelLoop: runUokKernelLoop,
2939
+ runLegacyLoop: runLegacyAutoLoop,
2940
+ });
2941
+ } finally {
2942
+ await cleanupAfterLoopExit(ctx);
2943
+ }
2913
2944
  return;
2914
2945
  }
2915
2946
 
@@ -2937,7 +2968,15 @@ export async function startAuto(
2937
2968
  bootstrapDeps,
2938
2969
  freshStartAssessment,
2939
2970
  );
2940
- if (!ready) return;
2971
+ if (!ready) {
2972
+ // bootstrapAutoSession sets s.active = true (auto-start.ts) before several
2973
+ // post-activation bail-outs return false without a loop ever running (e.g.
2974
+ // the SQLite-unavailable gate). Without this, s.active and the auto lock
2975
+ // leak and every later /gsd auto silently no-ops via the re-entry guard
2976
+ // (#1235). Run the canonical cleanup so a failed bootstrap stays recoverable.
2977
+ if (s.active) await cleanupAfterLoopExit(ctx);
2978
+ return;
2979
+ }
2941
2980
 
2942
2981
  // Build scope after bootstrap has populated s.basePath / s.originalBasePath /
2943
2982
  // s.currentMilestoneId (including worktree setup inside bootstrapAutoSession).
@@ -2963,15 +3002,18 @@ export async function startAuto(
2963
3002
  startAutoCommandPolling(s.basePath);
2964
3003
 
2965
3004
  // Dispatch the first unit
2966
- await runAutoLoopWithUok({
2967
- ctx,
2968
- pi,
2969
- s,
2970
- deps: loopDeps,
2971
- runKernelLoop: runUokKernelLoop,
2972
- runLegacyLoop: runLegacyAutoLoop,
2973
- });
2974
- await cleanupAfterLoopExit(ctx);
3005
+ try {
3006
+ await runAutoLoopWithUok({
3007
+ ctx,
3008
+ pi,
3009
+ s,
3010
+ deps: loopDeps,
3011
+ runKernelLoop: runUokKernelLoop,
3012
+ runLegacyLoop: runLegacyAutoLoop,
3013
+ });
3014
+ } finally {
3015
+ await cleanupAfterLoopExit(ctx);
3016
+ }
2975
3017
  }
2976
3018
 
2977
3019
  // describeNextUnit is imported from auto-dashboard.ts and re-exported
@@ -3129,19 +3171,56 @@ export async function dispatchHookUnit(
3129
3171
  workspaceRoot: s.basePath,
3130
3172
  });
3131
3173
 
3132
- if (hookModel) {
3133
- const availableModels = ctx.modelRegistry.getAvailable();
3134
- const match = resolveModelId(hookModel, availableModels, ctx.model?.provider);
3135
- if (match) {
3174
+ // Resolve the hook's model honoring the configured `fallbacks[]` chain
3175
+ // (#1229). The manual trigger path bypasses selectAndApplyModel, so resolve
3176
+ // the primary→fallbacks order here and apply the first candidate available in
3177
+ // the registry — a blocked or unconfigured primary then transparently drops
3178
+ // to a fallback instead of silently reverting to the session model.
3179
+ const availableModels = ctx.modelRegistry.getAvailable();
3180
+ const availableModelIds = availableModels.map(
3181
+ (m: { provider: string; id: string }) => `${m.provider}/${m.id}`,
3182
+ );
3183
+ const hookModelConfig = resolveModelWithFallbacksForUnit(
3184
+ hookUnitType,
3185
+ targetBasePath,
3186
+ availableModelIds,
3187
+ );
3188
+ const modelCandidates = hookModelConfig
3189
+ ? [hookModelConfig.primary, ...hookModelConfig.fallbacks]
3190
+ : hookModel
3191
+ ? [hookModel]
3192
+ : [];
3193
+ if (modelCandidates.length > 0) {
3194
+ let applied = false;
3195
+ for (const candidate of modelCandidates) {
3196
+ const match = resolveModelId(candidate, availableModels, ctx.model?.provider);
3197
+ if (!match) continue;
3198
+ // Skip models the runtime has marked blocked or temporarily unavailable
3199
+ // (e.g. a primary that just tripped a provider limit) so the configured
3200
+ // fallbacks[] chain actually engages — parity with auto-mode's
3201
+ // selectAndApplyModel, which consults the same blocked-models store (#1229).
3202
+ if (isModelUnavailable(targetBasePath, match.provider, match.id)) continue;
3136
3203
  try {
3137
- await pi.setModel(match);
3204
+ if (await pi.setModel(match)) {
3205
+ // The manual trigger path bypasses selectAndApplyModel, so apply the
3206
+ // hook's per-field `thinking` (from `post_unit_hooks[].model`'s object
3207
+ // form) here against the just-set model rather than leaving the hook at
3208
+ // the session level (#1269). Absent → session level, unchanged.
3209
+ if (hookModelConfig?.thinking) {
3210
+ applyThinkingLevelForModel(pi, hookModelConfig.thinking, match, ctx);
3211
+ }
3212
+ applied = true;
3213
+ break;
3214
+ }
3138
3215
  } catch (err) {
3139
- /* non-fatal */
3140
- logWarning("dispatch", `hook model set failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
3216
+ /* non-fatal — try the next fallback */
3217
+ logWarning("dispatch", `hook model set failed for ${candidate}: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
3141
3218
  }
3142
- } else {
3219
+ }
3220
+ if (!applied) {
3143
3221
  ctx.ui.notify(
3144
- `Hook model "${hookModel}" not found in available models. Falling back to current session model. ` +
3222
+ `Hook model${modelCandidates.length > 1 ? "s" : ""} "${modelCandidates.join(", ")}" not available. ` +
3223
+ `Falling back to current session model. ` +
3145
3224
  `Ensure the model is defined in models.json and has auth configured.`,
3146
3225
  "warning",
3147
3226
  );
@@ -14,7 +14,7 @@ import {
14
14
  type WorkflowDatabaseOpenResult,
15
15
  type WorkflowDatabaseStatus,
16
16
  } from "../db-workspace.js";
17
- import { getAutoWorktreePath } from "../auto-worktree.js";
17
+ import { getAutoWorktreePath } from "../auto-worktree-path-resolution.js";
18
18
  import { resolveWorktreeProjectRoot } from "../worktree-root.js";
19
19
  import { worktreesDirs } from "../worktree-placement.js";
20
20
 
@@ -40,7 +40,7 @@ import {
40
40
  } from "../auto-tool-tracking.js";
41
41
  import { applyProviderPayloadPolicy } from "../provider-payload-policy.js";
42
42
 
43
- import { checkToolCallLoop, recordToolCallLoopMutation, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
43
+ import { checkToolCallLoop, configureToolCallLoopGuard, recordToolCallLoopMutation, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
44
44
  import { MINIMAL_AUTO_BASE_TOOL_NAMES } from "./core-session-tools.js";
45
45
  import { maybePauseAutoForApprovalGate, resetPendingGatePauseGuard } from "./pending-gate-pause.js";
46
46
  import { saveActivityLog } from "../activity-log.js";
@@ -594,6 +594,22 @@ async function applyCompactionThresholdOverride(ctx: ExtensionContext): Promise<
594
594
  }
595
595
  }
596
596
 
597
+ /**
598
+ * Apply user-tunable tool-call loop guard thresholds (#1198) from GSD
599
+ * preferences plus GSD_TOOL_LOOP_* env overrides. Runs at session boundaries
600
+ * so both interactive sessions and `/gsd auto` pick up the configuration.
601
+ * Non-fatal: falls back to built-in defaults when preferences cannot be loaded.
602
+ */
603
+ async function applyToolCallLoopGuardConfig(basePath: string): Promise<void> {
604
+ try {
605
+ const { loadEffectiveGSDPreferences } = await import("../preferences.js");
606
+ const prefs = loadEffectiveGSDPreferences(basePath);
607
+ configureToolCallLoopGuard(prefs?.preferences.tool_call_loop_guard);
608
+ } catch {
609
+ configureToolCallLoopGuard(null);
610
+ }
611
+ }
612
+
597
613
  function clearDeferredApprovalGate(basePath?: string): void {
598
614
  if (!basePath) {
599
615
  deferredApprovalGates.clear();
@@ -996,6 +1012,7 @@ export function registerHooks(
996
1012
  }
997
1013
  resetWriteGateState(basePath);
998
1014
  resetToolCallLoopGuard();
1015
+ await applyToolCallLoopGuardConfig(basePath);
999
1016
  approvalQuestionAbortInFlight = false;
1000
1017
  clearDeferredApprovalGate();
1001
1018
  await resetAskUserQuestionsTurnCache();
@@ -1087,6 +1104,7 @@ export function registerHooks(
1087
1104
  initSessionNotifications(ctx);
1088
1105
  resetWriteGateState(basePath);
1089
1106
  resetToolCallLoopGuard();
1107
+ await applyToolCallLoopGuardConfig(basePath);
1090
1108
  clearDeferredApprovalGate();
1091
1109
  await resetAskUserQuestionsTurnCache();
1092
1110
  clearDiscussionFlowState(basePath);
@@ -1707,7 +1725,7 @@ export function registerHooks(
1707
1725
  }
1708
1726
  }
1709
1727
  if (!event.isError) {
1710
- recordToolCallLoopMutation(toolName);
1728
+ recordToolCallLoopMutation(toolName, event.details);
1711
1729
  refreshSourceObservationAfterMutation(toolName, event.input, ctx);
1712
1730
  clearSourceObservationsAfterShell(toolName);
1713
1731
  }
@@ -14,7 +14,7 @@ import { resolveModelWithFallbacksForUnit } from "../preferences-models.js";
14
14
  import { resolveGsdRootFile, resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveTaskFiles, resolveTasksDir, relSliceFile, relSlicePath, relTaskFile } from "../paths.js";
15
15
  import { extractIntroAndRules } from "../knowledge-parser.js";
16
16
  import { ensureCodebaseMapFresh, readCodebaseMap } from "../codebase-generator.js";
17
- import { getActiveAutoWorktreeContext } from "../auto-worktree.js";
17
+ import { getActiveAutoWorktreeContext } from "../auto-worktree-session-registry.js";
18
18
  import { getActiveWorktreeName, getWorktreeOriginalCwd } from "../worktree-session-state.js";
19
19
  import { deriveState } from "../state.js";
20
20
  import { formatOverridesSection, formatShortcut, loadActiveOverrides, loadFile, parseContinue, parseSummary } from "../files.js";
@@ -14,13 +14,21 @@
14
14
  * to stop tooling for the rest of that turn and answer in text.
15
15
  *
16
16
  * The per-tool-name check (#783 Brief C) tracks call counts within a
17
- * turn regardless of args, decaying after successful state-mutating tools.
17
+ * turn regardless of args, decaying after successful state-progressing tools.
18
18
  * This catches improvisation
19
19
  * loops where the model attempts the same missing workflow tool through
20
20
  * varied surfaces (bash → `node -e` → CLI), each with a different
21
21
  * signature, so the identical-args streak never trips, while allowing
22
- * tool-heavy turns that are making file-mutation progress. Whichever guard
23
- * trips first blocks.
22
+ * tool-heavy turns that are making progress. Progress means a successful file
23
+ * mutation (edit/write) or a successful shell/exec call (bg_shell,
24
+ * gsd_uat_exec, …) — so a local model running a legitimate iterative
25
+ * debugging loop (restart server, npm install, curl an endpoint) is not
26
+ * blocked as a false loop (#1206). Whichever guard trips first blocks.
27
+ *
28
+ * Thresholds, exempt tools, and enable flags are user-tunable (#1198) via the
29
+ * `tool_call_loop_guard` key in `.gsd/PREFERENCES.md` and `GSD_TOOL_LOOP_*`
30
+ * environment variables, applied through {@link configureToolCallLoopGuard}.
31
+ * Defaults preserve the original hardcoded behavior.
24
32
  */
25
33
 
26
34
  import { createHash } from "node:crypto";
@@ -28,26 +36,189 @@ import { INHERENTLY_REPEATABLE_TOOL_SET } from "./core-session-tools.js";
28
36
  import { hasBrowserContractPrefix } from "../../shared/browser-contract.js";
29
37
  import { canonicalToolName } from "../engine-hook-contract.js";
30
38
 
31
- const MAX_CONSECUTIVE_IDENTICAL_CALLS = 4;
39
+ /** Built-in defaults. Preserved when preferences/env do not override them. */
40
+ const DEFAULT_MAX_CONSECUTIVE_IDENTICAL_CALLS = 4;
41
+ const DEFAULT_PER_TOOL_DEFAULT_CAP = 6;
42
+ const DEFAULT_PER_TOOL_REPEATABLE_CAP = 15;
43
+ const DEFAULT_PER_TOOL_CAP_EXEMPT_TOOLS = ["find", "glob", "grep", "ls", "read", "search_and_read"] as const;
32
44
 
33
45
  /** Interactive/user-facing tools where even 1 duplicate is confusing. */
34
46
  const STRICT_LOOP_TOOLS = new Set(["ask_user_questions"]);
35
47
  const MAX_CONSECUTIVE_STRICT = 1;
36
48
 
49
+ const STATE_MUTATING_TOOL_SET = new Set(["edit", "write", "multi_edit", "notebook_edit"]);
50
+
37
51
  /**
38
- * Per-turn cap on calls to the SAME tool name, regardless of args (#783).
52
+ * Successful shell/exec calls are state progression too (#1206), not just file
53
+ * mutations. A local model debugging a UAT scenario legitimately restarts
54
+ * servers, runs `npm install`, and curls endpoints via bg_shell / gsd_uat_exec
55
+ * with varied args — productive work that never touches a file, so Guard 2's
56
+ * per-tool cap would otherwise misfire as a false loop. Decaying on these
57
+ * successful calls keeps the guard from aborting a progressing turn.
39
58
  *
40
- * General-purpose execution tools are routinely called many times per turn
41
- * (touching multiple files, running several commands), so they get a higher
42
- * ceiling. Everything else workflow one-shot tools (e.g. gsd_complete_milestone)
43
- * and any non-allowlisted tool gets the default cap. The default is generous
44
- * enough to absorb legitimate retries but catches the reported improvisation
45
- * loop (~51 calls) well before a cost spike.
59
+ * Only successful calls reach {@link recordToolCallLoopMutation}: the
60
+ * tool_result hook skips `isError` results, and the bash tool throws on
61
+ * non-zero exit, so a genuinely stuck improvisation loop of failing commands
62
+ * (#783) never decays and still trips the cap. `async_bash` is excluded
63
+ * because it only registers a background job; command success is reported
64
+ * later via `await_job`. `bg_shell` may return `isError: false` for failed
65
+ * `run`/`start` outcomes, so the hook passes `details` for validation.
46
66
  */
47
- const PER_TOOL_DEFAULT_CAP = 6;
48
- const PER_TOOL_REPEATABLE_CAP = 15;
49
- const PER_TOOL_CAP_EXEMPT_TOOLS = new Set(["find", "glob", "grep", "ls", "read", "search_and_read"]);
50
- const STATE_MUTATING_TOOL_SET = new Set(["edit", "write", "multi_edit", "notebook_edit"]);
67
+ const STATE_PROGRESSING_EXEC_TOOL_SET = new Set([
68
+ "bash",
69
+ "bg_shell",
70
+ "shell",
71
+ "powershell",
72
+ "gsd_exec",
73
+ "gsd_uat_exec",
74
+ ]);
75
+
76
+ function isSuccessfulBgShellLoopProgress(details: unknown): boolean {
77
+ if (!details || typeof details !== "object") return false;
78
+ const record = details as Record<string, unknown>;
79
+ switch (record.action) {
80
+ case "run":
81
+ return record.exitCode === 0 && record.timedOut !== true;
82
+ case "start":
83
+ case "restart": {
84
+ const process = record.process;
85
+ if (!process || typeof process !== "object") return false;
86
+ return (process as Record<string, unknown>).alive === true;
87
+ }
88
+ case "wait_for_ready":
89
+ return record.ready === true;
90
+ case "send_and_wait":
91
+ return record.matched === true;
92
+ default:
93
+ return true;
94
+ }
95
+ }
96
+
97
+ /**
98
+ * User-tunable configuration shape for the loop guard (#1198).
99
+ *
100
+ * Mirrors the `tool_call_loop_guard` key in `.gsd/PREFERENCES.md`. All fields
101
+ * are optional; anything omitted falls back to the built-in defaults so that
102
+ * existing installs keep their current behavior.
103
+ */
104
+ export interface ToolCallLoopGuardConfig {
105
+ enabled?: boolean;
106
+ identical_args?: {
107
+ enabled?: boolean;
108
+ max_consecutive_calls?: number;
109
+ };
110
+ repeated_tool?: {
111
+ enabled?: boolean;
112
+ default_cap?: number;
113
+ repeatable_cap?: number;
114
+ exempt_tools?: string[];
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Active, resolved configuration. Set by {@link configureToolCallLoopGuard}
120
+ * from preferences + environment overrides, and deliberately NOT touched by
121
+ * {@link resetToolCallLoopGuard} so a session's tuning survives turn
122
+ * boundaries.
123
+ */
124
+ interface ResolvedGuardConfig {
125
+ /** Master switch for both guards. */
126
+ guardEnabled: boolean;
127
+ identicalEnabled: boolean;
128
+ maxConsecutiveIdentical: number;
129
+ repeatedEnabled: boolean;
130
+ perToolDefaultCap: number;
131
+ perToolRepeatableCap: number;
132
+ /** Tool names exempt from Guard 2 (per-tool-name cap). */
133
+ perToolExempt: Set<string>;
134
+ }
135
+
136
+ function defaultGuardConfig(): ResolvedGuardConfig {
137
+ return {
138
+ guardEnabled: true,
139
+ identicalEnabled: true,
140
+ maxConsecutiveIdentical: DEFAULT_MAX_CONSECUTIVE_IDENTICAL_CALLS,
141
+ repeatedEnabled: true,
142
+ perToolDefaultCap: DEFAULT_PER_TOOL_DEFAULT_CAP,
143
+ perToolRepeatableCap: DEFAULT_PER_TOOL_REPEATABLE_CAP,
144
+ perToolExempt: new Set<string>(DEFAULT_PER_TOOL_CAP_EXEMPT_TOOLS),
145
+ };
146
+ }
147
+
148
+ let config: ResolvedGuardConfig = defaultGuardConfig();
149
+
150
+ /** Parse a positive-integer env var, returning undefined when unset/invalid. */
151
+ function envPositiveInt(name: string): number | undefined {
152
+ const raw = process.env[name];
153
+ if (raw === undefined || raw.trim() === "") return undefined;
154
+ const n = Number(raw);
155
+ return Number.isFinite(n) && n >= 1 ? Math.floor(n) : undefined;
156
+ }
157
+
158
+ /** Parse a boolean env var (`true`/`1` vs `false`/`0`), undefined when unset. */
159
+ function envBool(name: string): boolean | undefined {
160
+ const raw = process.env[name];
161
+ if (raw === undefined || raw.trim() === "") return undefined;
162
+ const v = raw.trim().toLowerCase();
163
+ if (v === "true" || v === "1" || v === "yes" || v === "on") return true;
164
+ if (v === "false" || v === "0" || v === "no" || v === "off") return false;
165
+ return undefined;
166
+ }
167
+
168
+ /** Parse a comma-separated tool-name list env var. */
169
+ function envToolList(name: string): string[] {
170
+ const raw = process.env[name];
171
+ if (!raw) return [];
172
+ return raw.split(",").map((s) => s.trim()).filter(Boolean);
173
+ }
174
+
175
+ /**
176
+ * Resolve preferences + environment overrides into the active configuration.
177
+ * Environment variables win over preferences; preferences win over built-in
178
+ * defaults. User-supplied exempt tools are additive to the built-in exempt
179
+ * set so defaults are always preserved.
180
+ *
181
+ * Applied to both interactive sessions and `/gsd auto` (called from the
182
+ * session_start / session_switch hooks).
183
+ */
184
+ export function configureToolCallLoopGuard(prefs?: ToolCallLoopGuardConfig | null): void {
185
+ const next = defaultGuardConfig();
186
+
187
+ if (prefs) {
188
+ if (typeof prefs.enabled === "boolean") next.guardEnabled = prefs.enabled;
189
+ if (prefs.identical_args) {
190
+ if (typeof prefs.identical_args.enabled === "boolean") next.identicalEnabled = prefs.identical_args.enabled;
191
+ if (typeof prefs.identical_args.max_consecutive_calls === "number" && prefs.identical_args.max_consecutive_calls >= 1) {
192
+ next.maxConsecutiveIdentical = Math.floor(prefs.identical_args.max_consecutive_calls);
193
+ }
194
+ }
195
+ if (prefs.repeated_tool) {
196
+ if (typeof prefs.repeated_tool.enabled === "boolean") next.repeatedEnabled = prefs.repeated_tool.enabled;
197
+ if (typeof prefs.repeated_tool.default_cap === "number" && prefs.repeated_tool.default_cap >= 1) {
198
+ next.perToolDefaultCap = Math.floor(prefs.repeated_tool.default_cap);
199
+ }
200
+ if (typeof prefs.repeated_tool.repeatable_cap === "number" && prefs.repeated_tool.repeatable_cap >= 1) {
201
+ next.perToolRepeatableCap = Math.floor(prefs.repeated_tool.repeatable_cap);
202
+ }
203
+ for (const tool of prefs.repeated_tool.exempt_tools ?? []) {
204
+ if (typeof tool === "string" && tool.trim()) next.perToolExempt.add(tool.trim());
205
+ }
206
+ }
207
+ }
208
+
209
+ // Environment overrides (win over preferences).
210
+ const envEnabled = envBool("GSD_TOOL_LOOP_GUARD_ENABLED");
211
+ if (envEnabled !== undefined) next.guardEnabled = envEnabled;
212
+ const envIdenticalMax = envPositiveInt("GSD_TOOL_LOOP_IDENTICAL_MAX");
213
+ if (envIdenticalMax !== undefined) next.maxConsecutiveIdentical = envIdenticalMax;
214
+ const envDefaultCap = envPositiveInt("GSD_TOOL_LOOP_REPEATED_DEFAULT_CAP");
215
+ if (envDefaultCap !== undefined) next.perToolDefaultCap = envDefaultCap;
216
+ const envRepeatableCap = envPositiveInt("GSD_TOOL_LOOP_REPEATED_REPEATABLE_CAP");
217
+ if (envRepeatableCap !== undefined) next.perToolRepeatableCap = envRepeatableCap;
218
+ for (const tool of envToolList("GSD_TOOL_LOOP_EXEMPT_TOOLS")) next.perToolExempt.add(tool);
219
+
220
+ config = next;
221
+ }
51
222
 
52
223
  let consecutiveCount = 0;
53
224
  let lastSignature = "";
@@ -82,17 +253,20 @@ function hashToolCall(toolName: string, args: Record<string, unknown>): string {
82
253
  * Returns `{ block: true, reason }` when the loop threshold is exceeded.
83
254
  *
84
255
  * Two independent guards run; whichever trips first blocks:
85
- * 1. Identical-signature streak (MAX_CONSECUTIVE_IDENTICAL_CALLS, strict for
256
+ * 1. Identical-signature streak (config.maxConsecutiveIdentical, strict for
86
257
  * ask_user_questions).
87
- * 2. Per-tool-name cap (PER_TOOL_DEFAULT_CAP / PER_TOOL_REPEATABLE_CAP),
258
+ * 2. Per-tool-name cap (config.perToolDefaultCap / config.perToolRepeatableCap),
88
259
  * independent of args, reset after file-mutation progress — catches
89
260
  * improvisation loops (#783).
261
+ *
262
+ * Both guards, their thresholds, and the per-tool exempt set are user-tunable
263
+ * via {@link configureToolCallLoopGuard} (#1198).
90
264
  */
91
265
  export function checkToolCallLoop(
92
266
  toolName: string,
93
267
  args: Record<string, unknown>,
94
268
  ): { block: boolean; reason?: string; count?: number } {
95
- if (!enabled) return { block: false, count: 0 };
269
+ if (!enabled || !config.guardEnabled) return { block: false, count: 0 };
96
270
 
97
271
  const sig = hashToolCall(toolName, args);
98
272
 
@@ -107,14 +281,16 @@ export function checkToolCallLoop(
107
281
  // ── Guard 1: identical-signature streak ──
108
282
  const threshold = STRICT_LOOP_TOOLS.has(toolName)
109
283
  ? MAX_CONSECUTIVE_STRICT
110
- : MAX_CONSECUTIVE_IDENTICAL_CALLS;
284
+ : config.maxConsecutiveIdentical;
111
285
 
112
- if (consecutiveCount > threshold) {
286
+ if (config.identicalEnabled && consecutiveCount > threshold) {
113
287
  return {
114
288
  block: true,
115
289
  reason:
116
290
  `Tool loop detected (identical args): ${toolName} called ${consecutiveCount} times ` +
117
- `with identical arguments. Blocking to prevent infinite loop. ` +
291
+ `with identical arguments (max ${threshold}). Blocking to prevent infinite loop. ` +
292
+ `Raise tool_call_loop_guard.identical_args.max_consecutive_calls in .gsd/PREFERENCES.md ` +
293
+ `(or GSD_TOOL_LOOP_IDENTICAL_MAX) if this is expected. ` +
118
294
  `Do not retry this tool or call other tools this turn — stop and respond to the user in text.`,
119
295
  count: consecutiveCount,
120
296
  };
@@ -139,15 +315,16 @@ export function checkToolCallLoop(
139
315
  // Guard 1's identical-signature streak still catches a genuinely stuck
140
316
  // browser loop.
141
317
  if (
142
- PER_TOOL_CAP_EXEMPT_TOOLS.has(toolName) ||
318
+ !config.repeatedEnabled ||
319
+ config.perToolExempt.has(toolName) ||
143
320
  hasBrowserContractPrefix(canonicalToolName(toolName))
144
321
  ) {
145
322
  return { block: false, count: consecutiveCount };
146
323
  }
147
324
 
148
325
  const perToolCap = INHERENTLY_REPEATABLE_TOOL_SET.has(toolName)
149
- ? PER_TOOL_REPEATABLE_CAP
150
- : PER_TOOL_DEFAULT_CAP;
326
+ ? config.perToolRepeatableCap
327
+ : config.perToolDefaultCap;
151
328
 
152
329
  if (perToolCount > perToolCap) {
153
330
  return {
@@ -156,6 +333,9 @@ export function checkToolCallLoop(
156
333
  `Tool loop detected (repeated tool): ${toolName} called ${perToolCount} times ` +
157
334
  `this turn (cap ${perToolCap}). Blocking to prevent infinite loop. ` +
158
335
  `The tool may be unavailable or failing repeatedly. ` +
336
+ `Raise tool_call_loop_guard.repeated_tool.default_cap/repeatable_cap or add "${toolName}" ` +
337
+ `to tool_call_loop_guard.repeated_tool.exempt_tools in .gsd/PREFERENCES.md ` +
338
+ `(or GSD_TOOL_LOOP_REPEATED_* / GSD_TOOL_LOOP_EXEMPT_TOOLS) if this is expected. ` +
159
339
  `Do not retry this tool or pivot to other tools this turn — stop and respond to the user in text.`,
160
340
  count: perToolCount,
161
341
  };
@@ -164,10 +344,21 @@ export function checkToolCallLoop(
164
344
  return { block: false, count: consecutiveCount };
165
345
  }
166
346
 
167
- /** Record successful mutation progress so Guard 2 can decay on the next count. */
168
- export function recordToolCallLoopMutation(toolName: string): void {
347
+ /**
348
+ * Record successful state progress so Guard 2 can decay on the next count.
349
+ * File mutations (edit/write/…) and successful shell/exec calls (bash,
350
+ * bg_shell, gsd_uat_exec, …) both count as progress (#1092, #1206). The caller
351
+ * only invokes this for non-error results, so failing improvisation loops
352
+ * (#783) never decay and still trip the per-tool cap.
353
+ */
354
+ export function recordToolCallLoopMutation(toolName: string, details?: unknown): void {
169
355
  if (!enabled) return;
170
- if (!STATE_MUTATING_TOOL_SET.has(toolName)) return;
356
+ if (STATE_MUTATING_TOOL_SET.has(toolName)) {
357
+ mutationEpoch++;
358
+ return;
359
+ }
360
+ if (!STATE_PROGRESSING_EXEC_TOOL_SET.has(toolName)) return;
361
+ if (toolName === "bg_shell" && details !== undefined && !isSuccessfulBgShellLoopProgress(details)) return;
171
362
  mutationEpoch++;
172
363
  }
173
364