@opengsd/gsd-pi 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/README.md +10 -10
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/ask-user-questions.js +1 -1
  4. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +114 -36
  5. package/dist/resources/extensions/gsd/activity-log.js +1 -1
  6. package/dist/resources/extensions/gsd/auto/closeout.js +97 -5
  7. package/dist/resources/extensions/gsd/auto/orchestrator.js +20 -13
  8. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +6 -3
  9. package/dist/resources/extensions/gsd/auto/unit-phase.js +5 -9
  10. package/dist/resources/extensions/gsd/auto-artifact-paths.js +14 -5
  11. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -7
  12. package/dist/resources/extensions/gsd/auto-dispatch.js +69 -17
  13. package/dist/resources/extensions/gsd/auto-model-selection.js +28 -1
  14. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
  15. package/dist/resources/extensions/gsd/auto-prompts.js +29 -117
  16. package/dist/resources/extensions/gsd/auto-recovery.js +50 -6
  17. package/dist/resources/extensions/gsd/auto-start.js +57 -33
  18. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +12 -2
  19. package/dist/resources/extensions/gsd/auto-timers.js +9 -2
  20. package/dist/resources/extensions/gsd/auto-worktree-branch-lifecycle.js +189 -0
  21. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +133 -0
  22. package/dist/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.js +35 -0
  23. package/dist/resources/extensions/gsd/auto-worktree-creation.js +130 -0
  24. package/dist/resources/extensions/gsd/auto-worktree-entry.js +118 -0
  25. package/dist/resources/extensions/gsd/auto-worktree-merge-already-merged.js +98 -0
  26. package/dist/resources/extensions/gsd/auto-worktree-merge-branch-head.js +52 -0
  27. package/dist/resources/extensions/gsd/auto-worktree-merge-cleanup.js +87 -0
  28. package/dist/resources/extensions/gsd/auto-worktree-merge-code-changes.js +46 -0
  29. package/dist/resources/extensions/gsd/auto-worktree-merge-db-ready.js +68 -0
  30. package/dist/resources/extensions/gsd/auto-worktree-merge-integration-branch.js +51 -0
  31. package/dist/resources/extensions/gsd/auto-worktree-merge-message.js +106 -0
  32. package/dist/resources/extensions/gsd/auto-worktree-merge-pre-teardown.js +64 -0
  33. package/dist/resources/extensions/gsd/auto-worktree-merge-stash.js +168 -0
  34. package/dist/resources/extensions/gsd/auto-worktree-merge.js +302 -0
  35. package/dist/resources/extensions/gsd/auto-worktree-milestone-shelter.js +119 -0
  36. package/dist/resources/extensions/gsd/auto-worktree-path-resolution.js +5 -0
  37. package/dist/resources/extensions/gsd/auto-worktree-path-utils.js +5 -0
  38. package/dist/resources/extensions/gsd/auto-worktree-resource-version.js +41 -0
  39. package/dist/resources/extensions/gsd/auto-worktree-runtime-cleanup.js +99 -0
  40. package/dist/resources/extensions/gsd/auto-worktree-session-registry.js +57 -0
  41. package/dist/resources/extensions/gsd/auto-worktree-sync.js +249 -0
  42. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +120 -0
  43. package/dist/resources/extensions/gsd/auto-worktree.js +20 -2073
  44. package/dist/resources/extensions/gsd/auto.js +106 -34
  45. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -1
  46. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +20 -2
  47. package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
  48. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +185 -27
  49. package/dist/resources/extensions/gsd/codebase-generator.js +7 -1
  50. package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
  51. package/dist/resources/extensions/gsd/commands-workflow-templates.js +3 -3
  52. package/dist/resources/extensions/gsd/compat/compat-marker.js +44 -0
  53. package/dist/resources/extensions/gsd/config-overlay.js +7 -2
  54. package/dist/resources/extensions/gsd/db/engine.js +33 -0
  55. package/dist/resources/extensions/gsd/db/queries.js +9 -9
  56. package/dist/resources/extensions/gsd/db/writers/cascades.js +20 -2
  57. package/dist/resources/extensions/gsd/db-adapter.js +30 -3
  58. package/dist/resources/extensions/gsd/docs/preferences-reference.md +3 -3
  59. package/dist/resources/extensions/gsd/doctor-engine-checks.js +93 -11
  60. package/dist/resources/extensions/gsd/flat-phase-migration.js +32 -3
  61. package/dist/resources/extensions/gsd/forensics.js +1 -1
  62. package/dist/resources/extensions/gsd/git-conflict-resolve.js +2 -2
  63. package/dist/resources/extensions/gsd/git-service.js +45 -0
  64. package/dist/resources/extensions/gsd/gsd-db.js +23 -11
  65. package/dist/resources/extensions/gsd/guided-flow.js +22 -17
  66. package/dist/resources/extensions/gsd/journal.js +1 -1
  67. package/dist/resources/extensions/gsd/markdown-renderer.js +34 -79
  68. package/dist/resources/extensions/gsd/md-importer.js +89 -23
  69. package/dist/resources/extensions/gsd/metrics.js +2 -2
  70. package/dist/resources/extensions/gsd/migration-auto-check.js +30 -3
  71. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +11 -0
  72. package/dist/resources/extensions/gsd/milestone-settlement.js +1 -1
  73. package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
  74. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -1
  75. package/dist/resources/extensions/gsd/paths.js +87 -52
  76. package/dist/resources/extensions/gsd/post-unit-hooks.js +27 -0
  77. package/dist/resources/extensions/gsd/preferences-models.js +66 -15
  78. package/dist/resources/extensions/gsd/preferences-skills.js +10 -16
  79. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  80. package/dist/resources/extensions/gsd/preferences-validation.js +148 -10
  81. package/dist/resources/extensions/gsd/preferences.js +20 -0
  82. package/dist/resources/extensions/gsd/prompts/system.md +6 -6
  83. package/dist/resources/extensions/gsd/quick.js +12 -3
  84. package/dist/resources/extensions/gsd/rule-registry.js +106 -10
  85. package/dist/resources/extensions/gsd/skill-discovery.js +36 -23
  86. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +2 -1
  87. package/dist/resources/extensions/gsd/state/derive/from-db.js +88 -153
  88. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +1 -10
  89. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +3 -24
  90. package/dist/resources/extensions/gsd/state-reconciliation/index.js +10 -0
  91. package/dist/resources/extensions/gsd/tool-contract.js +14 -0
  92. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -5
  93. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +16 -10
  94. package/dist/resources/extensions/gsd/tools/reopen-slice.js +5 -0
  95. package/dist/resources/extensions/gsd/tools/reopen-task.js +13 -5
  96. package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -8
  97. package/dist/resources/extensions/gsd/uat-dispatch.js +94 -0
  98. package/dist/resources/extensions/gsd/unit-registry.js +12 -2
  99. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +1 -1
  100. package/dist/resources/extensions/gsd/uok/audit-toggle.js +31 -2
  101. package/dist/resources/extensions/gsd/uok/audit.js +3 -0
  102. package/dist/resources/extensions/gsd/uok/gate-runner.js +22 -30
  103. package/dist/resources/extensions/gsd/uok/gitops.js +18 -15
  104. package/dist/resources/extensions/gsd/uok/kernel.js +120 -46
  105. package/dist/resources/extensions/gsd/uok/model-policy.js +17 -14
  106. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -1
  107. package/dist/resources/extensions/gsd/workflow-event-ledger.js +1 -1
  108. package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
  109. package/dist/resources/extensions/gsd/workflow-projections.js +9 -26
  110. package/dist/resources/extensions/gsd/workspace-git-preflight.js +2 -2
  111. package/dist/resources/extensions/gsd/workspace.js +5 -14
  112. package/dist/resources/extensions/gsd/worktree-command.js +1 -1
  113. package/dist/resources/extensions/gsd/worktree-lifecycle.js +14 -9
  114. package/dist/resources/extensions/gsd/worktree-reentry.js +2 -1
  115. package/dist/resources/extensions/shared/gsd-browser-cli.js +29 -0
  116. package/dist/resources/extensions/shared/interview-ui.js +62 -9
  117. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  118. package/dist/web/standalone/.next/BUILD_ID +1 -1
  119. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  120. package/dist/web/standalone/.next/build-manifest.json +2 -2
  121. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  122. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  142. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  146. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  156. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  158. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  164. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  168. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  170. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/index.html +1 -1
  173. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  174. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  176. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  177. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  178. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  179. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  180. package/dist/web/standalone/.next/server/chunks/{1128.js → 1991.js} +1 -1
  181. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  182. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  184. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  185. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  186. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  187. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  188. package/dist/worktree-cli-create.d.ts +10 -0
  189. package/dist/worktree-cli-create.js +11 -0
  190. package/dist/worktree-cli-format.d.ts +12 -0
  191. package/dist/worktree-cli-format.js +38 -0
  192. package/dist/worktree-cli-plan.d.ts +16 -0
  193. package/dist/worktree-cli-plan.js +19 -0
  194. package/dist/worktree-cli-session.d.ts +13 -0
  195. package/dist/worktree-cli-session.js +18 -0
  196. package/dist/worktree-cli-status.d.ts +35 -0
  197. package/dist/worktree-cli-status.js +54 -0
  198. package/dist/worktree-cli.d.ts +1 -16
  199. package/dist/worktree-cli.js +28 -122
  200. package/integrations/hermes/open_gsd_hermes/gsd_client.py +25 -36
  201. package/integrations/hermes/pyproject.toml +1 -1
  202. package/integrations/hermes/tests/test_gsd_client_timeout.py +4 -4
  203. package/package.json +6 -6
  204. package/packages/cloud-mcp-gateway/package.json +2 -2
  205. package/packages/contracts/package.json +1 -1
  206. package/packages/daemon/dist/orchestrator-agent.d.ts +21 -0
  207. package/packages/daemon/dist/orchestrator-agent.d.ts.map +1 -0
  208. package/packages/daemon/dist/orchestrator-agent.js +113 -0
  209. package/packages/daemon/dist/orchestrator-agent.js.map +1 -0
  210. package/packages/daemon/dist/orchestrator-tools.d.ts +12 -0
  211. package/packages/daemon/dist/orchestrator-tools.d.ts.map +1 -0
  212. package/packages/daemon/dist/orchestrator-tools.js +137 -0
  213. package/packages/daemon/dist/orchestrator-tools.js.map +1 -0
  214. package/packages/daemon/dist/orchestrator.d.ts +4 -56
  215. package/packages/daemon/dist/orchestrator.d.ts.map +1 -1
  216. package/packages/daemon/dist/orchestrator.js +13 -303
  217. package/packages/daemon/dist/orchestrator.js.map +1 -1
  218. package/packages/daemon/dist/orchestrator.test.js +11 -1
  219. package/packages/daemon/dist/orchestrator.test.js.map +1 -1
  220. package/packages/daemon/package.json +4 -4
  221. package/packages/gsd-agent-core/dist/export-html/template.js +53 -4
  222. package/packages/gsd-agent-core/package.json +5 -5
  223. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  224. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +3 -2
  225. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  226. package/packages/gsd-agent-modes/package.json +7 -7
  227. package/packages/mcp-server/package.json +4 -4
  228. package/packages/native/package.json +1 -1
  229. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  230. package/packages/pi-agent-core/dist/agent-loop.js +14 -9
  231. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  232. package/packages/pi-agent-core/package.json +1 -1
  233. package/packages/pi-ai/dist/index.d.ts +1 -0
  234. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  235. package/packages/pi-ai/dist/index.js +1 -0
  236. package/packages/pi-ai/dist/index.js.map +1 -1
  237. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  238. package/packages/pi-ai/dist/providers/transform-messages.js +7 -3
  239. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  240. package/packages/pi-ai/dist/tool-result-content.d.ts +3 -0
  241. package/packages/pi-ai/dist/tool-result-content.d.ts.map +1 -0
  242. package/packages/pi-ai/dist/tool-result-content.js +62 -0
  243. package/packages/pi-ai/dist/tool-result-content.js.map +1 -0
  244. package/packages/pi-ai/dist/types.d.ts +8 -20
  245. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  246. package/packages/pi-ai/dist/types.js.map +1 -1
  247. package/packages/pi-ai/package.json +1 -1
  248. package/packages/pi-coding-agent/dist/core/package-manager.d.ts +9 -0
  249. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/package-manager.js +74 -53
  251. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +6 -0
  253. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  254. package/packages/pi-coding-agent/dist/core/resource-loader.js +30 -2
  255. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  256. package/packages/pi-coding-agent/dist/core/skill-directories.d.ts +66 -0
  257. package/packages/pi-coding-agent/dist/core/skill-directories.d.ts.map +1 -0
  258. package/packages/pi-coding-agent/dist/core/skill-directories.js +138 -0
  259. package/packages/pi-coding-agent/dist/core/skill-directories.js.map +1 -0
  260. package/packages/pi-coding-agent/dist/core/skills.d.ts +4 -1
  261. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  262. package/packages/pi-coding-agent/dist/core/skills.js +4 -1
  263. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  264. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  265. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/index.js +1 -0
  267. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  268. package/packages/pi-coding-agent/package.json +7 -7
  269. package/packages/pi-tui/package.json +2 -2
  270. package/packages/rpc-client/package.json +2 -2
  271. package/pkg/dist/core/export-html/template.js +53 -4
  272. package/pkg/package.json +1 -1
  273. package/src/resources/extensions/ask-user-questions.ts +1 -1
  274. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +146 -33
  275. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +25 -0
  276. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +93 -0
  277. package/src/resources/extensions/gsd/activity-log.ts +1 -1
  278. package/src/resources/extensions/gsd/auto/closeout.ts +114 -7
  279. package/src/resources/extensions/gsd/auto/orchestrator.ts +21 -14
  280. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +6 -3
  281. package/src/resources/extensions/gsd/auto/unit-phase.ts +5 -9
  282. package/src/resources/extensions/gsd/auto-artifact-paths.ts +14 -4
  283. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +13 -7
  284. package/src/resources/extensions/gsd/auto-dispatch.ts +77 -16
  285. package/src/resources/extensions/gsd/auto-model-selection.ts +33 -1
  286. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -2
  287. package/src/resources/extensions/gsd/auto-prompts.ts +53 -113
  288. package/src/resources/extensions/gsd/auto-recovery.ts +50 -6
  289. package/src/resources/extensions/gsd/auto-start.ts +62 -31
  290. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -2
  291. package/src/resources/extensions/gsd/auto-timers.ts +9 -2
  292. package/src/resources/extensions/gsd/auto-worktree-branch-lifecycle.ts +237 -0
  293. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +166 -0
  294. package/src/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.ts +37 -0
  295. package/src/resources/extensions/gsd/auto-worktree-creation.ts +171 -0
  296. package/src/resources/extensions/gsd/auto-worktree-entry.ts +154 -0
  297. package/src/resources/extensions/gsd/auto-worktree-merge-already-merged.ts +161 -0
  298. package/src/resources/extensions/gsd/auto-worktree-merge-branch-head.ts +83 -0
  299. package/src/resources/extensions/gsd/auto-worktree-merge-cleanup.ts +132 -0
  300. package/src/resources/extensions/gsd/auto-worktree-merge-code-changes.ts +71 -0
  301. package/src/resources/extensions/gsd/auto-worktree-merge-db-ready.ts +112 -0
  302. package/src/resources/extensions/gsd/auto-worktree-merge-integration-branch.ts +99 -0
  303. package/src/resources/extensions/gsd/auto-worktree-merge-message.ts +166 -0
  304. package/src/resources/extensions/gsd/auto-worktree-merge-pre-teardown.ts +93 -0
  305. package/src/resources/extensions/gsd/auto-worktree-merge-stash.ts +213 -0
  306. package/src/resources/extensions/gsd/auto-worktree-merge.ts +391 -0
  307. package/src/resources/extensions/gsd/auto-worktree-milestone-shelter.ts +159 -0
  308. package/src/resources/extensions/gsd/auto-worktree-path-resolution.ts +6 -0
  309. package/src/resources/extensions/gsd/auto-worktree-path-utils.ts +10 -0
  310. package/src/resources/extensions/gsd/auto-worktree-resource-version.ts +44 -0
  311. package/src/resources/extensions/gsd/auto-worktree-runtime-cleanup.ts +119 -0
  312. package/src/resources/extensions/gsd/auto-worktree-session-registry.ts +71 -0
  313. package/src/resources/extensions/gsd/auto-worktree-sync.ts +370 -0
  314. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +161 -0
  315. package/src/resources/extensions/gsd/auto-worktree.ts +69 -2429
  316. package/src/resources/extensions/gsd/auto.ts +114 -47
  317. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -1
  318. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +20 -2
  319. package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
  320. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +218 -27
  321. package/src/resources/extensions/gsd/codebase-generator.ts +7 -1
  322. package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
  323. package/src/resources/extensions/gsd/commands-workflow-templates.ts +3 -3
  324. package/src/resources/extensions/gsd/compat/compat-marker.ts +47 -0
  325. package/src/resources/extensions/gsd/config-overlay.ts +7 -1
  326. package/src/resources/extensions/gsd/db/engine.ts +36 -0
  327. package/src/resources/extensions/gsd/db/queries.ts +9 -9
  328. package/src/resources/extensions/gsd/db/writers/cascades.ts +23 -1
  329. package/src/resources/extensions/gsd/db-adapter.ts +29 -3
  330. package/src/resources/extensions/gsd/docs/preferences-reference.md +3 -3
  331. package/src/resources/extensions/gsd/doctor-engine-checks.ts +109 -10
  332. package/src/resources/extensions/gsd/flat-phase-migration.ts +34 -3
  333. package/src/resources/extensions/gsd/forensics.ts +1 -1
  334. package/src/resources/extensions/gsd/git-conflict-resolve.ts +2 -2
  335. package/src/resources/extensions/gsd/git-service.ts +53 -0
  336. package/src/resources/extensions/gsd/gsd-db.ts +33 -11
  337. package/src/resources/extensions/gsd/guided-flow.ts +26 -18
  338. package/src/resources/extensions/gsd/journal.ts +1 -1
  339. package/src/resources/extensions/gsd/markdown-renderer.ts +52 -91
  340. package/src/resources/extensions/gsd/md-importer.ts +93 -22
  341. package/src/resources/extensions/gsd/metrics.ts +2 -2
  342. package/src/resources/extensions/gsd/migration-auto-check.ts +32 -3
  343. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +15 -0
  344. package/src/resources/extensions/gsd/milestone-settlement.ts +1 -1
  345. package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
  346. package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -1
  347. package/src/resources/extensions/gsd/paths.ts +108 -51
  348. package/src/resources/extensions/gsd/post-unit-hooks.ts +32 -0
  349. package/src/resources/extensions/gsd/preferences-models.ts +74 -20
  350. package/src/resources/extensions/gsd/preferences-skills.ts +10 -16
  351. package/src/resources/extensions/gsd/preferences-types.ts +54 -1
  352. package/src/resources/extensions/gsd/preferences-validation.ts +146 -9
  353. package/src/resources/extensions/gsd/preferences.ts +20 -0
  354. package/src/resources/extensions/gsd/prompts/system.md +6 -6
  355. package/src/resources/extensions/gsd/quick.ts +11 -3
  356. package/src/resources/extensions/gsd/rule-registry.ts +111 -9
  357. package/src/resources/extensions/gsd/skill-discovery.ts +47 -23
  358. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -1
  359. package/src/resources/extensions/gsd/state/derive/from-db.ts +201 -157
  360. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +1 -9
  361. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +2 -22
  362. package/src/resources/extensions/gsd/state-reconciliation/index.ts +14 -0
  363. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +169 -1
  364. package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +2 -1
  365. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +41 -2
  366. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +48 -1
  367. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +57 -0
  368. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +1 -1
  369. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +29 -1
  370. package/src/resources/extensions/gsd/tests/auto-timeout-recovery-supervisor-inflight-guard.test.ts +159 -0
  371. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +2 -1
  372. package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +1 -1
  373. package/src/resources/extensions/gsd/tests/auto-worktree-merge-already-merged.test.ts +177 -0
  374. package/src/resources/extensions/gsd/tests/auto-worktree-merge-branch-head.test.ts +118 -0
  375. package/src/resources/extensions/gsd/tests/auto-worktree-merge-cleanup.test.ts +115 -0
  376. package/src/resources/extensions/gsd/tests/auto-worktree-merge-code-changes.test.ts +76 -0
  377. package/src/resources/extensions/gsd/tests/auto-worktree-merge-db-ready.test.ts +140 -0
  378. package/src/resources/extensions/gsd/tests/auto-worktree-merge-integration-branch.test.ts +123 -0
  379. package/src/resources/extensions/gsd/tests/auto-worktree-merge-message.test.ts +114 -0
  380. package/src/resources/extensions/gsd/tests/auto-worktree-merge-pre-teardown.test.ts +84 -0
  381. package/src/resources/extensions/gsd/tests/auto-worktree-merge-stash.test.ts +70 -0
  382. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-shelter.test.ts +52 -0
  383. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +6 -6
  384. package/src/resources/extensions/gsd/tests/auto-worktree-resource-version.test.ts +59 -0
  385. package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +3 -1
  386. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  387. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +3 -1
  388. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +85 -0
  389. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +45 -0
  390. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +1 -1
  391. package/src/resources/extensions/gsd/tests/db-adapter.test.ts +39 -0
  392. package/src/resources/extensions/gsd/tests/db-writable-probe.test.ts +66 -0
  393. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -0
  394. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +174 -0
  395. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +1 -1
  396. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +71 -1
  397. package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +46 -1
  398. package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +72 -32
  399. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +40 -0
  400. package/src/resources/extensions/gsd/tests/import-completion-lost-update.test.ts +196 -0
  401. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +4 -6
  402. package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +2 -1
  403. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +3 -3
  404. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +7 -8
  405. package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +2 -5
  406. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +76 -0
  407. package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +1 -1
  408. package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +1 -1
  409. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +2 -1
  410. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +5 -7
  411. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +88 -1
  412. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +2 -4
  413. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -15
  414. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +1 -1
  415. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +1 -1
  416. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +1 -1
  417. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +91 -0
  418. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +2 -1
  419. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +439 -0
  420. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +24 -0
  421. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +1 -1
  422. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -3
  423. package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +1 -1
  424. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +0 -1
  425. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +269 -0
  426. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +8 -1
  427. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +1 -4
  428. package/src/resources/extensions/gsd/tests/preferences.test.ts +19 -0
  429. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +5 -0
  430. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +54 -0
  431. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +49 -1
  432. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +52 -0
  433. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +95 -1
  434. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
  435. package/src/resources/extensions/gsd/tests/sibling-model-fallbacks.test.ts +189 -0
  436. package/src/resources/extensions/gsd/tests/single-field-model-thinking.test.ts +156 -0
  437. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +46 -0
  438. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +6 -1
  439. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -5
  440. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +32 -0
  441. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +2 -1
  442. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +2 -1
  443. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +1 -1
  444. package/src/resources/extensions/gsd/tests/supervisor-model-swap-inflight-guard.test.ts +181 -0
  445. package/src/resources/extensions/gsd/tests/supervisor-model-swap-thinking-clamp.test.ts +122 -0
  446. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +1 -1
  447. package/src/resources/extensions/gsd/tests/system-flat-phase-layout.test.ts +33 -0
  448. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +4 -4
  449. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +2 -1
  450. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +4 -4
  451. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +196 -0
  452. package/src/resources/extensions/gsd/tests/uat-dispatch.test.ts +211 -0
  453. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +1 -1
  454. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +26 -1
  455. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +39 -0
  456. package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +226 -2
  457. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +6 -0
  458. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +213 -2
  459. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -1
  460. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +1 -1
  461. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +1 -3
  462. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +1 -1
  463. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +1 -1
  464. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +1 -1
  465. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +1 -1
  466. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +2 -1
  467. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +5 -2
  468. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +1 -1
  469. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +1 -1
  470. package/src/resources/extensions/gsd/tool-contract.ts +29 -0
  471. package/src/resources/extensions/gsd/tools/complete-milestone.ts +9 -5
  472. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +19 -8
  473. package/src/resources/extensions/gsd/tools/reopen-slice.ts +5 -0
  474. package/src/resources/extensions/gsd/tools/reopen-task.ts +13 -5
  475. package/src/resources/extensions/gsd/tools/validate-milestone.ts +13 -9
  476. package/src/resources/extensions/gsd/types.ts +23 -4
  477. package/src/resources/extensions/gsd/uat-dispatch.ts +176 -0
  478. package/src/resources/extensions/gsd/unit-registry.ts +16 -2
  479. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +1 -1
  480. package/src/resources/extensions/gsd/uok/audit-toggle.ts +32 -2
  481. package/src/resources/extensions/gsd/uok/audit.ts +2 -0
  482. package/src/resources/extensions/gsd/uok/gate-runner.ts +26 -36
  483. package/src/resources/extensions/gsd/uok/gitops.ts +21 -18
  484. package/src/resources/extensions/gsd/uok/kernel.ts +169 -48
  485. package/src/resources/extensions/gsd/uok/model-policy.ts +20 -17
  486. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -1
  487. package/src/resources/extensions/gsd/workflow-event-ledger.ts +1 -1
  488. package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
  489. package/src/resources/extensions/gsd/workflow-projections.ts +9 -24
  490. package/src/resources/extensions/gsd/workspace-git-preflight.ts +2 -2
  491. package/src/resources/extensions/gsd/workspace.ts +5 -21
  492. package/src/resources/extensions/gsd/worktree-command.ts +1 -1
  493. package/src/resources/extensions/gsd/worktree-lifecycle.ts +19 -15
  494. package/src/resources/extensions/gsd/worktree-reentry.ts +2 -1
  495. package/src/resources/extensions/shared/gsd-browser-cli.ts +29 -0
  496. package/src/resources/extensions/shared/interview-ui.ts +58 -11
  497. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +32 -0
  498. /package/dist/web/standalone/.next/static/{bCg3aYrFN1DKZr2dqgE7L → 6xYMOzxVhsQgryneJ5KRc}/_buildManifest.js +0 -0
  499. /package/dist/web/standalone/.next/static/{bCg3aYrFN1DKZr2dqgE7L → 6xYMOzxVhsQgryneJ5KRc}/_ssgManifest.js +0 -0
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Supervisor model swap honors the in-flight-tool guard (#1229 follow-up).
3
+ *
4
+ * The wrap-up soft-timeout timer gates `triggerTurn` on there being no tools
5
+ * in flight — sending a turn mid-tool-call skips tool results and trips
6
+ * provider errors (#3512). The supervisor model swap
7
+ * (`applySupervisorModelIfConfigured`) must honor the identical guard: swapping
8
+ * the session model while tool calls are still open risks the same provider
9
+ * errors, so it must only run when the timer will actually trigger a turn.
10
+ */
11
+
12
+ import test from "node:test";
13
+ import assert from "node:assert/strict";
14
+ import { mock } from "node:test";
15
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
16
+ import { join } from "node:path";
17
+ import { tmpdir } from "node:os";
18
+
19
+ import { startUnitSupervision, type SupervisionContext } from "../auto-timers.ts";
20
+ import { clearGSDPreferencesCache } from "../preferences.ts";
21
+ import {
22
+ markToolStart,
23
+ markToolEnd,
24
+ clearInFlightTools,
25
+ } from "../auto-tool-tracking.ts";
26
+
27
+ const SUPERVISOR_PREFS = [
28
+ "auto_supervisor:",
29
+ " soft_timeout_minutes: 1",
30
+ " idle_timeout_minutes: 100",
31
+ " hard_timeout_minutes: 100",
32
+ " model:",
33
+ " model: supervisor-primary",
34
+ " fallbacks: [supervisor-fb]",
35
+ ];
36
+
37
+ interface Harness {
38
+ home: string;
39
+ base: string;
40
+ ctx: any;
41
+ pi: any;
42
+ s: any;
43
+ sctx: SupervisionContext;
44
+ setModelCalls: unknown[][];
45
+ sendMessageCalls: unknown[][];
46
+ }
47
+
48
+ function makeHarness(): Harness {
49
+ const home = mkdtempSync(join(tmpdir(), "gsd-supervisor-guard-home-"));
50
+ const base = mkdtempSync(join(tmpdir(), "gsd-supervisor-guard-base-"));
51
+ process.env.GSD_HOME = home;
52
+ writeFileSync(join(home, "preferences.md"), ["---", ...SUPERVISOR_PREFS, "---", ""].join("\n"));
53
+ clearGSDPreferencesCache();
54
+
55
+ const setModelCalls: unknown[][] = [];
56
+ const sendMessageCalls: unknown[][] = [];
57
+
58
+ const ctx = {
59
+ ui: { notify: () => {} },
60
+ model: { provider: "anthropic" },
61
+ modelRegistry: {
62
+ getAvailable: () => [
63
+ { id: "supervisor-primary", provider: "anthropic" },
64
+ { id: "supervisor-fb", provider: "anthropic" },
65
+ ],
66
+ },
67
+ } as any;
68
+
69
+ const pi = {
70
+ sendMessage: (...args: unknown[]) => {
71
+ sendMessageCalls.push(args);
72
+ },
73
+ setModel: async (...args: unknown[]) => {
74
+ setModelCalls.push(args);
75
+ return true;
76
+ },
77
+ getThinkingLevel: () => "off",
78
+ setThinkingLevel: () => {},
79
+ } as any;
80
+
81
+ const s = {
82
+ active: true,
83
+ verbose: false,
84
+ basePath: base,
85
+ currentUnit: { type: "task", id: "T01", startedAt: 1234 },
86
+ cmdCtx: undefined,
87
+ wrapupWarningHandle: null,
88
+ idleWatchdogHandle: null,
89
+ unitTimeoutHandle: null,
90
+ continueHereHandle: null,
91
+ } as any;
92
+
93
+ const sctx: SupervisionContext = {
94
+ s,
95
+ ctx,
96
+ pi,
97
+ unitType: "task",
98
+ unitId: "T01",
99
+ prefs: undefined,
100
+ buildSnapshotOpts: () => ({}) as any,
101
+ buildRecoveryContext: () => ({}) as any,
102
+ pauseAuto: async () => {},
103
+ };
104
+
105
+ return { home, base, ctx, pi, s, sctx, setModelCalls, sendMessageCalls };
106
+ }
107
+
108
+ function cleanup(h: Harness): void {
109
+ clearInFlightTools();
110
+ clearGSDPreferencesCache();
111
+ delete process.env.GSD_HOME;
112
+ rmSync(h.home, { recursive: true, force: true });
113
+ rmSync(h.base, { recursive: true, force: true });
114
+ }
115
+
116
+ /** Neutralize every timer except the soft-timeout wrap-up so only it fires. */
117
+ function isolateSoftTimeout(s: any): void {
118
+ if (s.idleWatchdogHandle) clearInterval(s.idleWatchdogHandle);
119
+ if (s.unitTimeoutHandle) clearTimeout(s.unitTimeoutHandle);
120
+ if (s.continueHereHandle) clearInterval(s.continueHereHandle);
121
+ }
122
+
123
+ /** Flush the soft-timeout callback's chained awaits. */
124
+ async function flush(): Promise<void> {
125
+ for (let i = 0; i < 10; i++) await Promise.resolve();
126
+ }
127
+
128
+ test("soft-timeout skips the supervisor model swap while a tool is in flight", async () => {
129
+ const h = makeHarness();
130
+ mock.timers.enable({ apis: ["setTimeout", "setInterval", "Date"], now: 0 });
131
+ try {
132
+ startUnitSupervision(h.sctx);
133
+ isolateSoftTimeout(h.s);
134
+
135
+ // A tool is still executing when the soft timeout fires.
136
+ markToolStart("call-1", true, "some_tool");
137
+
138
+ mock.timers.tick(60_000);
139
+ await flush();
140
+
141
+ assert.equal(
142
+ h.setModelCalls.length,
143
+ 0,
144
+ "model must NOT swap while a tool is in flight",
145
+ );
146
+ assert.equal(h.sendMessageCalls.length, 1, "wrap-up message still sent (queued)");
147
+ const opts = h.sendMessageCalls[0][1] as { triggerTurn?: boolean };
148
+ assert.equal(opts.triggerTurn, false, "turn is not triggered mid-tool-call");
149
+
150
+ markToolEnd("call-1");
151
+ } finally {
152
+ mock.timers.reset();
153
+ cleanup(h);
154
+ }
155
+ });
156
+
157
+ test("soft-timeout applies the supervisor model swap when no tools are in flight", async () => {
158
+ const h = makeHarness();
159
+ mock.timers.enable({ apis: ["setTimeout", "setInterval", "Date"], now: 0 });
160
+ try {
161
+ startUnitSupervision(h.sctx);
162
+ isolateSoftTimeout(h.s);
163
+
164
+ // No tools in flight — the timer will trigger a turn, so the model swaps.
165
+ mock.timers.tick(60_000);
166
+ await flush();
167
+
168
+ assert.equal(h.setModelCalls.length, 1, "model swaps to the supervisor model");
169
+ assert.deepEqual(
170
+ h.setModelCalls[0][0],
171
+ { id: "supervisor-primary", provider: "anthropic" },
172
+ "swaps to the configured supervisor primary",
173
+ );
174
+ assert.equal(h.sendMessageCalls.length, 1);
175
+ const opts = h.sendMessageCalls[0][1] as { triggerTurn?: boolean };
176
+ assert.equal(opts.triggerTurn, true, "turn is triggered when no tools are open");
177
+ } finally {
178
+ mock.timers.reset();
179
+ cleanup(h);
180
+ }
181
+ });
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Supervisor model swap reclamps the reasoning level (#1229 follow-up).
3
+ *
4
+ * Hook overrides in `unit-phase.ts` reapply `applyThinkingLevelForModel` after a
5
+ * model swap so the session's reasoning effort is re-clamped to what the newly
6
+ * selected model supports (ADR-026). `applySupervisorModelIfConfigured` swaps
7
+ * the session model for supervisor interventions (wrap-up, context-budget,
8
+ * timeout recovery) and must do the same — otherwise a level that was valid for
9
+ * the prior model can reach the provider on the steered turn.
10
+ */
11
+
12
+ import test from "node:test";
13
+ import assert from "node:assert/strict";
14
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
15
+ import { join } from "node:path";
16
+ import { tmpdir } from "node:os";
17
+
18
+ import { applySupervisorModelIfConfigured } from "../auto-model-selection.ts";
19
+ import { clearGSDPreferencesCache } from "../preferences.ts";
20
+
21
+ const SUPERVISOR_PREFS = [
22
+ "auto_supervisor:",
23
+ " model:",
24
+ " model: supervisor-primary",
25
+ " fallbacks: [supervisor-fb]",
26
+ ];
27
+
28
+ interface Harness {
29
+ home: string;
30
+ base: string;
31
+ ctx: any;
32
+ pi: any;
33
+ setModelCalls: unknown[][];
34
+ setThinkingCalls: unknown[];
35
+ order: string[];
36
+ }
37
+
38
+ function makeHarness(): Harness {
39
+ const home = mkdtempSync(join(tmpdir(), "gsd-supervisor-clamp-home-"));
40
+ const base = mkdtempSync(join(tmpdir(), "gsd-supervisor-clamp-base-"));
41
+ process.env.GSD_HOME = home;
42
+ writeFileSync(join(home, "preferences.md"), ["---", ...SUPERVISOR_PREFS, "---", ""].join("\n"));
43
+ clearGSDPreferencesCache();
44
+
45
+ const setModelCalls: unknown[][] = [];
46
+ const setThinkingCalls: unknown[] = [];
47
+ const order: string[] = [];
48
+
49
+ const ctx = {
50
+ ui: { notify: () => {} },
51
+ model: { provider: "anthropic" },
52
+ modelRegistry: {
53
+ getAvailable: () => [
54
+ { id: "supervisor-primary", provider: "anthropic" },
55
+ { id: "supervisor-fb", provider: "anthropic" },
56
+ ],
57
+ },
58
+ } as any;
59
+
60
+ const pi = {
61
+ setModel: async (...args: unknown[]) => {
62
+ setModelCalls.push(args);
63
+ order.push("setModel");
64
+ return true;
65
+ },
66
+ getThinkingLevel: () => "high",
67
+ setThinkingLevel: (level: unknown) => {
68
+ setThinkingCalls.push(level);
69
+ order.push("setThinkingLevel");
70
+ },
71
+ } as any;
72
+
73
+ return { home, base, ctx, pi, setModelCalls, setThinkingCalls, order };
74
+ }
75
+
76
+ function cleanup(h: Harness): void {
77
+ clearGSDPreferencesCache();
78
+ delete process.env.GSD_HOME;
79
+ rmSync(h.home, { recursive: true, force: true });
80
+ rmSync(h.base, { recursive: true, force: true });
81
+ }
82
+
83
+ test("supervisor swap reapplies the thinking level after selecting the model", async () => {
84
+ const h = makeHarness();
85
+ try {
86
+ await applySupervisorModelIfConfigured(h.ctx, h.pi, h.base);
87
+
88
+ assert.equal(h.setModelCalls.length, 1, "model swaps to the supervisor model");
89
+ assert.deepEqual(
90
+ h.setModelCalls[0][0],
91
+ { id: "supervisor-primary", provider: "anthropic" },
92
+ "swaps to the configured supervisor primary",
93
+ );
94
+ assert.equal(
95
+ h.setThinkingCalls.length,
96
+ 1,
97
+ "thinking level is reclamped exactly once after the swap",
98
+ );
99
+ assert.deepEqual(
100
+ h.order,
101
+ ["setModel", "setThinkingLevel"],
102
+ "reclamp happens after setModel, matching the hook-override pattern",
103
+ );
104
+ } finally {
105
+ cleanup(h);
106
+ }
107
+ });
108
+
109
+ test("supervisor swap does not touch the thinking level when no model is configured", async () => {
110
+ const h = makeHarness();
111
+ // Overwrite prefs with no auto_supervisor.model.
112
+ writeFileSync(join(h.home, "preferences.md"), ["---", "auto_supervisor:", " soft_timeout_minutes: 1", "---", ""].join("\n"));
113
+ clearGSDPreferencesCache();
114
+ try {
115
+ await applySupervisorModelIfConfigured(h.ctx, h.pi, h.base);
116
+
117
+ assert.equal(h.setModelCalls.length, 0, "no swap without a configured supervisor model");
118
+ assert.equal(h.setThinkingCalls.length, 0, "thinking level untouched when nothing swaps");
119
+ } finally {
120
+ cleanup(h);
121
+ }
122
+ });
@@ -8,7 +8,7 @@ import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:
8
8
  import { join } from "node:path";
9
9
  import { tmpdir } from "node:os";
10
10
 
11
- import { syncWorktreeStateBack } from "../auto-worktree.ts";
11
+ import { syncWorktreeStateBack } from "../auto-worktree-sync.ts";
12
12
 
13
13
  describe("syncWorktreeStateBack does not copy worktree milestone projections", () => {
14
14
  it("copies root diagnostics but leaves milestone markdown directories behind", () => {
@@ -0,0 +1,33 @@
1
+ // gsd-pi — Regression tests: system.md documents the flat-phase layout, not legacy milestone/slice/task paths
2
+
3
+ import test from "node:test";
4
+ import assert from "node:assert/strict";
5
+ import { readFileSync } from "node:fs";
6
+ import { join } from "node:path";
7
+
8
+ const promptsDir = join(process.cwd(), "src/resources/extensions/gsd/prompts");
9
+
10
+ function readPrompt(name: string): string {
11
+ return readFileSync(join(promptsDir, `${name}.md`), "utf-8");
12
+ }
13
+
14
+ test("system.md does not advertise legacy milestone/slice/task artifact paths", () => {
15
+ const prompt = readPrompt("system");
16
+ for (const legacy of [".gsd/milestones", "milestones/M001", "slices/S01", "tasks/T01-PLAN.md"]) {
17
+ assert.ok(
18
+ !prompt.includes(legacy),
19
+ `system.md must not reference the legacy path fragment "${legacy}" after flat-phase migration`,
20
+ );
21
+ }
22
+ });
23
+
24
+ test("system.md documents the flat-phase directory structure", () => {
25
+ const prompt = readPrompt("system");
26
+ assert.match(prompt, /phases\/\{MM\}-\{slug\}/, "system.md must document phases/{MM}-{slug}/ directories");
27
+ assert.match(prompt, /\{MM\}-\{SS\}-PLAN\.md/, "system.md must document {MM}-{SS}-PLAN.md slice plans");
28
+ assert.match(
29
+ prompt,
30
+ /do not expect `tasks\/T##-PLAN\.md`/,
31
+ "system.md must state task plan content lives inside the slice plan, not tasks/T##-PLAN.md",
32
+ );
33
+ });
@@ -36,13 +36,13 @@ import { join } from "node:path";
36
36
  import { tmpdir } from "node:os";
37
37
  import { execFileSync } from "node:child_process";
38
38
 
39
+ import { createAutoWorktree } from "../auto-worktree-creation.ts";
39
40
  import {
40
- createAutoWorktree,
41
- teardownAutoWorktree,
42
- getAutoWorktreeOriginalBase,
43
41
  getActiveAutoWorktreeContext,
42
+ getAutoWorktreeOriginalBase,
44
43
  _resetAutoWorktreeOriginalBaseForTests,
45
- } from "../auto-worktree.ts";
44
+ } from "../auto-worktree-session-registry.ts";
45
+ import { teardownAutoWorktree } from "../auto-worktree-teardown.ts";
46
46
 
47
47
  // ─── Helpers ─────────────────────────────────────────────────────────────────
48
48
 
@@ -22,7 +22,8 @@ import { join } from "node:path";
22
22
  import { tmpdir } from "node:os";
23
23
  import { execFileSync } from "node:child_process";
24
24
 
25
- import { teardownAutoWorktree, _resetAutoWorktreeOriginalBaseForTests } from "../auto-worktree.ts";
25
+ import { _resetAutoWorktreeOriginalBaseForTests } from "../auto-worktree-session-registry.ts";
26
+ import { teardownAutoWorktree } from "../auto-worktree-teardown.ts";
26
27
 
27
28
  function git(args: string[], cwd: string): void {
28
29
  execFileSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
@@ -38,13 +38,13 @@ import { join } from "node:path";
38
38
  import { tmpdir } from "node:os";
39
39
  import { execFileSync } from "node:child_process";
40
40
 
41
+ import { createAutoWorktree } from "../auto-worktree-creation.ts";
41
42
  import {
42
- createAutoWorktree,
43
- teardownAutoWorktree,
44
- getAutoWorktreeOriginalBase,
45
43
  getActiveAutoWorktreeContext,
44
+ getAutoWorktreeOriginalBase,
46
45
  _resetAutoWorktreeOriginalBaseForTests,
47
- } from "../auto-worktree.ts";
46
+ } from "../auto-worktree-session-registry.ts";
47
+ import { teardownAutoWorktree } from "../auto-worktree-teardown.ts";
48
48
 
49
49
  // ─── Helpers ─────────────────────────────────────────────────────────────────
50
50
 
@@ -7,6 +7,7 @@ import { test } from 'node:test';
7
7
  import assert from 'node:assert/strict';
8
8
  import {
9
9
  checkToolCallLoop,
10
+ configureToolCallLoopGuard,
10
11
  recordToolCallLoopMutation,
11
12
  resetToolCallLoopGuard,
12
13
  disableToolCallLoopGuard,
@@ -251,6 +252,99 @@ console.log('\n── Loop guard: mutation progress decays per-tool counts (#109
251
252
  }
252
253
  }
253
254
 
255
+ // ═══════════════════════════════════════════════════════════════════════════
256
+ // Successful shell/exec progress decays per-tool counts (#1206)
257
+ // ═══════════════════════════════════════════════════════════════════════════
258
+
259
+ console.log('\n── Loop guard: successful shell/exec progress decays per-tool counts (#1206) ──');
260
+
261
+ {
262
+ // A local model debugging a UAT scenario runs many varied bg_shell /
263
+ // gsd_uat_exec calls (restart server, npm install, curl an endpoint). Each
264
+ // successful call is state progression, so Guard 2 must decay and never
265
+ // block the productive turn — even past the repeatable cap.
266
+ for (const execTool of ['bg_shell', 'gsd_uat_exec', 'bash', 'gsd_exec']) {
267
+ resetToolCallLoopGuard();
268
+
269
+ for (let i = 1; i <= 20; i++) {
270
+ const result = checkToolCallLoop(execTool, { command: `step ${i}` });
271
+ assert.ok(result.block === false, `${execTool} call ${i} after exec progress should be allowed`);
272
+ assert.deepStrictEqual(getToolCallCountForTool(execTool), 1, `${execTool} count should decay before call ${i}`);
273
+
274
+ // A successful (non-error) exec call records progress, like a file mutation.
275
+ recordToolCallLoopMutation(execTool);
276
+ }
277
+ }
278
+ }
279
+
280
+ // ═══════════════════════════════════════════════════════════════════════════
281
+ // Failing exec loops still trip the per-tool cap (#783 vs #1206)
282
+ // ═══════════════════════════════════════════════════════════════════════════
283
+
284
+ console.log('\n── Loop guard: failing exec loop (no progress recorded) still trips the cap (#783) ──');
285
+
286
+ {
287
+ resetToolCallLoopGuard();
288
+
289
+ // The improvisation loop from #783: the model retries a missing tool through
290
+ // varied bash commands. Those fail (non-zero exit → isError), so the caller
291
+ // never records progress and the per-tool cap must still trip.
292
+ for (let i = 1; i <= 15; i++) {
293
+ const result = checkToolCallLoop('bash', { command: `try-missing-tool ${i}` });
294
+ assert.ok(result.block === false, `failing bash call ${i} should be allowed up to the cap`);
295
+ // No recordToolCallLoopMutation — the command errored.
296
+ }
297
+ const blocked = checkToolCallLoop('bash', { command: 'try-missing-tool 16' });
298
+ assert.ok(blocked.block === true, '16th failing bash call should be blocked by the per-tool cap');
299
+ assert.ok(blocked.reason?.includes('repeated tool'), 'reason should identify the per-tool guard');
300
+ }
301
+
302
+ // ═══════════════════════════════════════════════════════════════════════════
303
+ // bg_shell/async_bash false-success must not decay the per-tool cap (#783)
304
+ // ═══════════════════════════════════════════════════════════════════════════
305
+
306
+ console.log('\n── Loop guard: bg_shell failed run/start does not decay the cap (#783) ──');
307
+
308
+ {
309
+ resetToolCallLoopGuard();
310
+
311
+ for (let i = 1; i <= 15; i++) {
312
+ const result = checkToolCallLoop('bg_shell', { action: 'run', command: `try-missing-tool ${i}` });
313
+ assert.ok(result.block === false, `failing bg_shell run ${i} should be allowed up to the cap`);
314
+ recordToolCallLoopMutation('bg_shell', { action: 'run', exitCode: 1, timedOut: false });
315
+ }
316
+ const blocked = checkToolCallLoop('bg_shell', { action: 'run', command: 'try-missing-tool 16' });
317
+ assert.ok(blocked.block === true, '16th failing bg_shell run should be blocked by the per-tool cap');
318
+ }
319
+
320
+ {
321
+ resetToolCallLoopGuard();
322
+
323
+ for (let i = 1; i <= 15; i++) {
324
+ checkToolCallLoop('bg_shell', { action: 'start', command: `bad-server ${i}` });
325
+ recordToolCallLoopMutation('bg_shell', {
326
+ action: 'start',
327
+ process: { alive: false, exitCode: 1 },
328
+ });
329
+ }
330
+ const blocked = checkToolCallLoop('bg_shell', { action: 'start', command: 'bad-server 16' });
331
+ assert.ok(blocked.block === true, '16th dead bg_shell start should be blocked by the per-tool cap');
332
+ }
333
+
334
+ console.log('\n── Loop guard: async_bash job registration does not decay the cap (#783) ──');
335
+
336
+ {
337
+ resetToolCallLoopGuard();
338
+
339
+ for (let i = 1; i <= 6; i++) {
340
+ const result = checkToolCallLoop('async_bash', { command: `try-missing-tool ${i}` });
341
+ assert.ok(result.block === false, `async_bash call ${i} should be allowed up to the cap`);
342
+ recordToolCallLoopMutation('async_bash');
343
+ }
344
+ const blocked = checkToolCallLoop('async_bash', { command: 'try-missing-tool 7' });
345
+ assert.ok(blocked.block === true, '7th async_bash call should be blocked by the per-tool cap');
346
+ }
347
+
254
348
  // ═══════════════════════════════════════════════════════════════════════════
255
349
  // Distinct read-only navigation calls are context gathering, not repeated-tool loops.
256
350
  // ═══════════════════════════════════════════════════════════════════════════
@@ -448,3 +542,105 @@ console.log('\n── Loop guard: browser exemption does not widen to other tool
448
542
  }
449
543
 
450
544
  // ═══════════════════════════════════════════════════════════════════════════
545
+ // Configurable thresholds (#1198)
546
+ // ═══════════════════════════════════════════════════════════════════════════
547
+
548
+ console.log('\n── Loop guard: master switch disables both guards (#1198) ──');
549
+
550
+ {
551
+ configureToolCallLoopGuard({ enabled: false });
552
+ resetToolCallLoopGuard();
553
+ // Neither identical-args nor per-tool cap should ever trip while disabled.
554
+ for (let i = 1; i <= 30; i++) {
555
+ const result = checkToolCallLoop('gsd_complete_milestone', { same: 'args' });
556
+ assert.ok(result.block === false, `disabled guard should allow call ${i}`);
557
+ }
558
+ // Restore defaults for subsequent tests.
559
+ configureToolCallLoopGuard(null);
560
+ }
561
+
562
+ console.log('\n── Loop guard: repeated_tool disabled keeps identical-args protection (#1198) ──');
563
+
564
+ {
565
+ configureToolCallLoopGuard({ repeated_tool: { enabled: false } });
566
+ resetToolCallLoopGuard();
567
+ // Per-tool cap is off: many varied-arg calls are allowed.
568
+ for (let i = 1; i <= 20; i++) {
569
+ const result = checkToolCallLoop('gsd_exec', { cmd: `run-${i}` });
570
+ assert.ok(result.block === false, `repeated_tool disabled should allow varied call ${i}`);
571
+ }
572
+ // Identical-args guard is still active.
573
+ resetToolCallLoopGuard();
574
+ for (let i = 1; i <= 4; i++) {
575
+ assert.ok(checkToolCallLoop('gsd_exec', { cmd: 'same' }).block === false);
576
+ }
577
+ const blocked = checkToolCallLoop('gsd_exec', { cmd: 'same' });
578
+ assert.ok(blocked.block === true, 'identical-args guard should still trip when repeated_tool is off');
579
+ assert.ok(blocked.reason?.includes('identical args'));
580
+ configureToolCallLoopGuard(null);
581
+ }
582
+
583
+ console.log('\n── Loop guard: raised caps allow more repeated calls (#1198) ──');
584
+
585
+ {
586
+ configureToolCallLoopGuard({ repeated_tool: { default_cap: 10 } });
587
+ resetToolCallLoopGuard();
588
+ for (let i = 1; i <= 10; i++) {
589
+ const result = checkToolCallLoop('gsd_complete_milestone', { arg: `v${i}` });
590
+ assert.ok(result.block === false, `raised-cap call ${i} should be allowed`);
591
+ }
592
+ const blocked = checkToolCallLoop('gsd_complete_milestone', { arg: 'v11' });
593
+ assert.ok(blocked.block === true, '11th call should trip the raised cap of 10');
594
+ assert.ok(blocked.reason?.includes('cap 10'), 'block message should mention the active cap');
595
+ assert.ok(blocked.reason?.includes('tool_call_loop_guard'), 'block message should mention the config key');
596
+ configureToolCallLoopGuard(null);
597
+ }
598
+
599
+ console.log('\n── Loop guard: user-added exempt tools bypass the per-tool cap (#1198) ──');
600
+
601
+ {
602
+ configureToolCallLoopGuard({ repeated_tool: { exempt_tools: ['ctx_execute'] } });
603
+ resetToolCallLoopGuard();
604
+ for (let i = 1; i <= 30; i++) {
605
+ const result = checkToolCallLoop('ctx_execute', { arg: `v${i}` });
606
+ assert.ok(result.block === false, `exempt tool call ${i} should be allowed`);
607
+ }
608
+ // Built-in exempt defaults are preserved alongside the user-added tool.
609
+ resetToolCallLoopGuard();
610
+ for (let i = 1; i <= 30; i++) {
611
+ assert.ok(checkToolCallLoop('read', { path: `f${i}` }).block === false, 'built-in exempt read should remain exempt');
612
+ }
613
+ configureToolCallLoopGuard(null);
614
+ }
615
+
616
+ console.log('\n── Loop guard: identical-args max is configurable (#1198) ──');
617
+
618
+ {
619
+ configureToolCallLoopGuard({ identical_args: { max_consecutive_calls: 2 } });
620
+ resetToolCallLoopGuard();
621
+ assert.ok(checkToolCallLoop('web_search', { q: 'x' }).block === false, 'call 1 allowed');
622
+ assert.ok(checkToolCallLoop('web_search', { q: 'x' }).block === false, 'call 2 allowed');
623
+ const blocked = checkToolCallLoop('web_search', { q: 'x' });
624
+ assert.ok(blocked.block === true, '3rd identical call should trip lowered max of 2');
625
+ assert.ok(blocked.reason?.includes('max 2'), 'block message should mention active max');
626
+ configureToolCallLoopGuard(null);
627
+ }
628
+
629
+ console.log('\n── Loop guard: env overrides win over preferences (#1198) ──');
630
+
631
+ {
632
+ process.env.GSD_TOOL_LOOP_REPEATED_DEFAULT_CAP = '2';
633
+ configureToolCallLoopGuard({ repeated_tool: { default_cap: 6 } });
634
+ resetToolCallLoopGuard();
635
+ assert.ok(checkToolCallLoop('gsd_complete_milestone', { a: '1' }).block === false, 'call 1 allowed');
636
+ assert.ok(checkToolCallLoop('gsd_complete_milestone', { a: '2' }).block === false, 'call 2 allowed');
637
+ const blocked = checkToolCallLoop('gsd_complete_milestone', { a: '3' });
638
+ assert.ok(blocked.block === true, 'env override cap of 2 should win over preference cap of 6');
639
+ delete process.env.GSD_TOOL_LOOP_REPEATED_DEFAULT_CAP;
640
+ configureToolCallLoopGuard(null);
641
+ }
642
+
643
+ // ═══════════════════════════════════════════════════════════════════════════
644
+ // Reset restores default guard state after configuration tests
645
+ // ═══════════════════════════════════════════════════════════════════════════
646
+ resetToolCallLoopGuard();