gsd-pi 2.80.0-dev.fbe7c8c6f → 2.81.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 (786) hide show
  1. package/README.md +35 -59
  2. package/dist/claude-cli-check.d.ts +30 -0
  3. package/dist/claude-cli-check.js +18 -7
  4. package/dist/cli.js +0 -19
  5. package/dist/headless-query.d.ts +10 -0
  6. package/dist/headless-query.js +6 -4
  7. package/dist/loader-entrypoint.d.ts +8 -0
  8. package/dist/loader-entrypoint.js +27 -0
  9. package/dist/loader.js +2 -11
  10. package/dist/mcp-server.d.ts +1 -0
  11. package/dist/mcp-server.js +6 -3
  12. package/dist/resources/.managed-resources-content-hash +1 -1
  13. package/dist/resources/extensions/claude-code-cli/readiness.js +18 -7
  14. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +40 -3
  15. package/dist/resources/extensions/github-sync/sync.js +4 -1
  16. package/dist/resources/extensions/gsd/auto/contracts.js +2 -0
  17. package/dist/resources/extensions/gsd/auto/loop.js +103 -9
  18. package/dist/resources/extensions/gsd/auto/orchestrator.js +48 -4
  19. package/dist/resources/extensions/gsd/auto/phases.js +282 -132
  20. package/dist/resources/extensions/gsd/auto/resolve.js +29 -0
  21. package/dist/resources/extensions/gsd/auto/run-unit.js +22 -30
  22. package/dist/resources/extensions/gsd/auto/session.js +9 -1
  23. package/dist/resources/extensions/gsd/auto/unit-runner-events.js +7 -0
  24. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
  25. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
  26. package/dist/resources/extensions/gsd/auto-dashboard.js +18 -0
  27. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
  28. package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
  29. package/dist/resources/extensions/gsd/auto-post-unit.js +112 -78
  30. package/dist/resources/extensions/gsd/auto-prompts.js +103 -16
  31. package/dist/resources/extensions/gsd/auto-recovery.js +43 -1
  32. package/dist/resources/extensions/gsd/auto-start.js +252 -14
  33. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  34. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  35. package/dist/resources/extensions/gsd/auto-worktree.js +229 -336
  36. package/dist/resources/extensions/gsd/auto.js +264 -86
  37. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +122 -11
  38. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +44 -37
  39. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -10
  40. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +30 -20
  41. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +4 -1
  42. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +6 -4
  43. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +5 -3
  44. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +1 -1
  45. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +330 -54
  46. package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +4 -0
  47. package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
  48. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +19 -2
  49. package/dist/resources/extensions/gsd/clean-root-preflight.js +24 -6
  50. package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
  51. package/dist/resources/extensions/gsd/commands-config.js +1 -1
  52. package/dist/resources/extensions/gsd/commands-eval-review.js +2 -2
  53. package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
  54. package/dist/resources/extensions/gsd/context-budget.js +37 -2
  55. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  56. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  57. package/dist/resources/extensions/gsd/db/unit-dispatches.js +92 -0
  58. package/dist/resources/extensions/gsd/db-base-schema.js +4 -2
  59. package/dist/resources/extensions/gsd/db-migration-steps.js +6 -0
  60. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
  61. package/dist/resources/extensions/gsd/git-service.js +73 -5
  62. package/dist/resources/extensions/gsd/gsd-db.js +46 -13
  63. package/dist/resources/extensions/gsd/guided-flow.js +119 -42
  64. package/dist/resources/extensions/gsd/health-widget.js +3 -0
  65. package/dist/resources/extensions/gsd/init-wizard.js +4 -1
  66. package/dist/resources/extensions/gsd/memory-store.js +69 -12
  67. package/dist/resources/extensions/gsd/migrate/command.js +40 -1
  68. package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
  69. package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
  70. package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
  71. package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
  72. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  73. package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
  74. package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
  75. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +22 -17
  76. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  77. package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
  78. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  79. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  80. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  81. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  82. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  83. package/dist/resources/extensions/gsd/quick.js +34 -2
  84. package/dist/resources/extensions/gsd/recovery-classification.js +94 -0
  85. package/dist/resources/extensions/gsd/slice-cadence.js +45 -2
  86. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +15 -9
  87. package/dist/resources/extensions/gsd/state-reconciliation.js +27 -0
  88. package/dist/resources/extensions/gsd/tool-contract.js +50 -0
  89. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -7
  90. package/dist/resources/extensions/gsd/tools/complete-task.js +1 -1
  91. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  92. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  93. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  94. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
  95. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  96. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  97. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  98. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
  99. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  100. package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
  101. package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
  102. package/dist/resources/extensions/gsd/worktree-lifecycle.js +958 -0
  103. package/dist/resources/extensions/gsd/worktree-safety.js +119 -0
  104. package/dist/resources/extensions/gsd/worktree-state-projection.js +317 -0
  105. package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
  106. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  107. package/dist/web/standalone/.next/BUILD_ID +1 -1
  108. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  109. package/dist/web/standalone/.next/build-manifest.json +4 -4
  110. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  111. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  112. package/dist/web/standalone/.next/required-server-files.json +3 -3
  113. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  114. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  124. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  152. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  172. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  188. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  204. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  208. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/app/index.html +1 -1
  218. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  219. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  220. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  221. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  222. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  223. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  224. package/dist/web/standalone/.next/server/app/page.js +2 -2
  225. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  227. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  228. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  229. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  230. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  231. package/dist/web/standalone/.next/server/middleware.js +3 -3
  232. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  233. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  234. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  235. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  236. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  237. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +10 -0
  238. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  239. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  240. package/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +1 -0
  241. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  242. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  243. package/dist/web/standalone/.next/static/chunks/{webpack-0481f1221120a7c6.js → webpack-de742b64187e13fe.js} +1 -1
  244. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  245. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  246. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  247. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  248. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  249. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  250. package/dist/web/standalone/server.js +1 -1
  251. package/dist/welcome-screen.d.ts +2 -0
  252. package/dist/welcome-screen.js +9 -7
  253. package/package.json +3 -3
  254. package/packages/daemon/package.json +2 -2
  255. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  256. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  257. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  258. package/packages/mcp-server/package.json +2 -2
  259. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  260. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  261. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  262. package/packages/native/package.json +1 -1
  263. package/packages/native/tsconfig.tsbuildinfo +1 -1
  264. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  265. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  266. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  267. package/packages/pi-agent-core/dist/agent.d.ts +9 -2
  268. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  269. package/packages/pi-agent-core/dist/agent.js +43 -11
  270. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  271. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  272. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  273. package/packages/pi-agent-core/dist/index.js +2 -0
  274. package/packages/pi-agent-core/dist/index.js.map +1 -1
  275. package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
  276. package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
  277. package/packages/pi-agent-core/dist/token-audit.js +221 -0
  278. package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
  279. package/packages/pi-agent-core/dist/types.d.ts +31 -0
  280. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  281. package/packages/pi-agent-core/dist/types.js.map +1 -1
  282. package/packages/pi-agent-core/package.json +1 -1
  283. package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
  284. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  285. package/packages/pi-agent-core/src/agent.ts +52 -11
  286. package/packages/pi-agent-core/src/index.ts +2 -0
  287. package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
  288. package/packages/pi-agent-core/src/token-audit.ts +287 -0
  289. package/packages/pi-agent-core/src/types.ts +26 -10
  290. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  291. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +35 -13
  292. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  293. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +21 -11
  294. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -1
  295. package/packages/pi-ai/dist/providers/anthropic.d.ts +7 -0
  296. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  297. package/packages/pi-ai/dist/providers/anthropic.js +9 -7
  298. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  299. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +23 -14
  300. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -1
  301. package/packages/pi-ai/dist/types.d.ts +2 -0
  302. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  303. package/packages/pi-ai/dist/types.js.map +1 -1
  304. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +48 -21
  305. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
  306. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +22 -21
  307. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -1
  308. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +22 -21
  309. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -1
  310. package/packages/pi-ai/package.json +1 -1
  311. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +39 -25
  312. package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -22
  313. package/packages/pi-ai/src/providers/anthropic.ts +22 -9
  314. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +34 -21
  315. package/packages/pi-ai/src/types.ts +3 -0
  316. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +56 -22
  317. package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +24 -28
  318. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +24 -28
  319. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  320. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +36 -1
  321. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  322. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +30 -1
  323. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +21 -2
  325. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  326. package/packages/pi-coding-agent/dist/core/agent-session.js +94 -16
  327. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  328. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +6 -2
  329. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  330. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  331. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  333. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  335. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  336. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  337. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  338. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  339. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  341. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  342. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  343. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  345. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  347. package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
  348. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  349. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +3 -0
  350. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  351. package/packages/pi-coding-agent/dist/core/extensions/runner.js +6 -6
  352. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +5 -3
  354. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +60 -4
  356. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  357. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  358. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
  359. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
  360. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
  361. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
  362. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
  363. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
  364. package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
  365. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  366. package/packages/pi-coding-agent/dist/core/sdk.js +81 -4
  367. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  368. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
  369. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  370. package/packages/pi-coding-agent/dist/core/settings-manager.js +25 -0
  371. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  372. package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
  373. package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
  374. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
  375. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  376. package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
  377. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  378. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js +22 -56
  379. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -1
  380. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +1 -0
  381. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  382. package/packages/pi-coding-agent/dist/core/tools/bash.js +3 -1
  383. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts +2 -0
  385. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/tools/edit.js +12 -1
  387. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  388. package/packages/pi-coding-agent/dist/core/tools/find.d.ts +2 -0
  389. package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  390. package/packages/pi-coding-agent/dist/core/tools/find.js +14 -6
  391. package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  392. package/packages/pi-coding-agent/dist/core/tools/grep.d.ts +2 -0
  393. package/packages/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
  394. package/packages/pi-coding-agent/dist/core/tools/grep.js +12 -3
  395. package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  396. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts +2 -0
  397. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  398. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -1
  399. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  400. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -1
  401. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  402. package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
  403. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  404. package/packages/pi-coding-agent/dist/core/tools/ls.d.ts +2 -0
  405. package/packages/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
  406. package/packages/pi-coding-agent/dist/core/tools/ls.js +10 -3
  407. package/packages/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
  408. package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -0
  409. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  410. package/packages/pi-coding-agent/dist/core/tools/read.js +3 -1
  411. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  412. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +7 -62
  413. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -1
  414. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts +2 -0
  415. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts.map +1 -0
  416. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js +115 -0
  417. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js.map +1 -0
  418. package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts +19 -0
  419. package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts.map +1 -0
  420. package/packages/pi-coding-agent/dist/core/tools/tool-target.js +20 -0
  421. package/packages/pi-coding-agent/dist/core/tools/tool-target.js.map +1 -0
  422. package/packages/pi-coding-agent/dist/core/tools/write.d.ts +4 -0
  423. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  424. package/packages/pi-coding-agent/dist/core/tools/write.js +9 -1
  425. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  426. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +89 -2
  427. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  428. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +25 -1
  429. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  430. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +6 -0
  431. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  432. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +155 -7
  433. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  434. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  435. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +31 -6
  436. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  437. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +71 -0
  438. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  439. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  440. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  441. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +25 -3
  442. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  443. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
  444. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  445. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  446. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  447. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +28 -0
  448. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  449. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  450. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  451. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  452. package/packages/pi-coding-agent/package.json +1 -1
  453. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +40 -1
  454. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +40 -1
  455. package/packages/pi-coding-agent/src/core/agent-session.ts +102 -16
  456. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +6 -2
  457. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  458. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  459. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  460. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  461. package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
  462. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +5 -3
  463. package/packages/pi-coding-agent/src/core/extensions/runner.ts +8 -5
  464. package/packages/pi-coding-agent/src/core/extensions/types.ts +63 -2
  465. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
  466. package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
  467. package/packages/pi-coding-agent/src/core/sdk.ts +92 -4
  468. package/packages/pi-coding-agent/src/core/settings-manager.ts +39 -1
  469. package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
  470. package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
  471. package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +22 -66
  472. package/packages/pi-coding-agent/src/core/tools/bash.ts +4 -1
  473. package/packages/pi-coding-agent/src/core/tools/edit.ts +13 -1
  474. package/packages/pi-coding-agent/src/core/tools/find.ts +15 -6
  475. package/packages/pi-coding-agent/src/core/tools/grep.ts +13 -3
  476. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +4 -1
  477. package/packages/pi-coding-agent/src/core/tools/index.ts +8 -0
  478. package/packages/pi-coding-agent/src/core/tools/ls.ts +11 -3
  479. package/packages/pi-coding-agent/src/core/tools/read.ts +4 -1
  480. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +11 -72
  481. package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
  482. package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
  483. package/packages/pi-coding-agent/src/core/tools/write.ts +14 -2
  484. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +119 -2
  485. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +31 -1
  486. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +180 -7
  487. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +75 -0
  488. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +39 -8
  489. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +27 -3
  490. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +1 -1
  491. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +31 -0
  492. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  493. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  494. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  495. package/packages/pi-tui/dist/tui.js +18 -8
  496. package/packages/pi-tui/dist/tui.js.map +1 -1
  497. package/packages/pi-tui/package.json +1 -1
  498. package/packages/pi-tui/src/tui.ts +20 -8
  499. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  500. package/packages/rpc-client/README.md +7 -0
  501. package/packages/rpc-client/package.json +1 -1
  502. package/pkg/package.json +1 -1
  503. package/src/resources/extensions/claude-code-cli/readiness.ts +25 -7
  504. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +42 -3
  505. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +67 -0
  506. package/src/resources/extensions/github-sync/sync.ts +8 -1
  507. package/src/resources/extensions/github-sync/tests/sync-source.test.ts +6 -18
  508. package/src/resources/extensions/gsd/auto/contracts.ts +19 -2
  509. package/src/resources/extensions/gsd/auto/loop-deps.ts +10 -11
  510. package/src/resources/extensions/gsd/auto/loop.ts +134 -16
  511. package/src/resources/extensions/gsd/auto/orchestrator.ts +52 -4
  512. package/src/resources/extensions/gsd/auto/phases.ts +393 -200
  513. package/src/resources/extensions/gsd/auto/resolve.ts +42 -1
  514. package/src/resources/extensions/gsd/auto/run-unit.ts +28 -30
  515. package/src/resources/extensions/gsd/auto/session.ts +9 -1
  516. package/src/resources/extensions/gsd/auto/types.ts +3 -0
  517. package/src/resources/extensions/gsd/auto/unit-runner-events.ts +15 -0
  518. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
  519. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
  520. package/src/resources/extensions/gsd/auto-dashboard.ts +20 -0
  521. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
  522. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -0
  523. package/src/resources/extensions/gsd/auto-post-unit.ts +124 -80
  524. package/src/resources/extensions/gsd/auto-prompts.ts +112 -15
  525. package/src/resources/extensions/gsd/auto-recovery.ts +54 -0
  526. package/src/resources/extensions/gsd/auto-start.ts +319 -19
  527. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  528. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  529. package/src/resources/extensions/gsd/auto-worktree.ts +259 -360
  530. package/src/resources/extensions/gsd/auto.ts +324 -88
  531. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +147 -11
  532. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +45 -37
  533. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +36 -10
  534. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +32 -19
  535. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +5 -1
  536. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +7 -4
  537. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +6 -3
  538. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +1 -1
  539. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +379 -54
  540. package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +4 -0
  541. package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
  542. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -2
  543. package/src/resources/extensions/gsd/clean-root-preflight.ts +32 -7
  544. package/src/resources/extensions/gsd/commands/handlers/ops.ts +4 -2
  545. package/src/resources/extensions/gsd/commands-config.ts +1 -1
  546. package/src/resources/extensions/gsd/commands-eval-review.ts +2 -2
  547. package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
  548. package/src/resources/extensions/gsd/context-budget.ts +44 -2
  549. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  550. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  551. package/src/resources/extensions/gsd/db/unit-dispatches.ts +107 -0
  552. package/src/resources/extensions/gsd/db-base-schema.ts +4 -2
  553. package/src/resources/extensions/gsd/db-migration-steps.ts +8 -0
  554. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
  555. package/src/resources/extensions/gsd/git-service.ts +87 -10
  556. package/src/resources/extensions/gsd/gsd-db.ts +50 -13
  557. package/src/resources/extensions/gsd/guided-flow.ts +148 -49
  558. package/src/resources/extensions/gsd/health-widget.ts +3 -0
  559. package/src/resources/extensions/gsd/init-wizard.ts +5 -1
  560. package/src/resources/extensions/gsd/memory-store.ts +77 -12
  561. package/src/resources/extensions/gsd/migrate/command.ts +47 -1
  562. package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
  563. package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
  564. package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
  565. package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
  566. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  567. package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
  568. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  569. package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
  570. package/src/resources/extensions/gsd/prompts/complete-milestone.md +22 -17
  571. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  572. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  573. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  574. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  575. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  576. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  577. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  578. package/src/resources/extensions/gsd/quick.ts +37 -2
  579. package/src/resources/extensions/gsd/recovery-classification.ts +122 -0
  580. package/src/resources/extensions/gsd/slice-cadence.ts +49 -2
  581. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +23 -9
  582. package/src/resources/extensions/gsd/state-reconciliation.ts +57 -0
  583. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +59 -89
  584. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +47 -172
  585. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +0 -35
  586. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +35 -9
  587. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +543 -40
  588. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +80 -59
  589. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +119 -2
  590. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +3 -47
  591. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +76 -18
  592. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +175 -11
  593. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +54 -95
  594. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +67 -26
  595. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +14 -1
  596. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +32 -30
  597. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +32 -128
  598. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +20 -54
  599. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +20 -30
  600. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +17 -29
  601. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +142 -0
  602. package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +21 -39
  603. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +15 -24
  604. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +44 -29
  605. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +39 -51
  606. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +159 -213
  607. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +15 -32
  608. package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +0 -41
  609. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +15 -6
  610. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +34 -27
  611. package/src/resources/extensions/gsd/tests/cmux.test.ts +51 -53
  612. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +39 -61
  613. package/src/resources/extensions/gsd/tests/commands-config.test.ts +26 -19
  614. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
  615. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
  616. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
  617. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
  618. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +29 -33
  619. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +45 -108
  620. package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
  621. package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
  622. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +90 -31
  623. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  624. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +18 -10
  625. package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
  626. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +4 -68
  627. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +6 -11
  628. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +14 -65
  629. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +44 -37
  630. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +58 -40
  631. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +25 -15
  632. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
  633. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +35 -17
  634. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +16 -21
  635. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +15 -82
  636. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  637. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  638. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
  639. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
  640. package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +151 -0
  641. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +2 -20
  642. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +18 -26
  643. package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +9 -12
  644. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +40 -0
  645. package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +4 -2
  646. package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +31 -20
  647. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +66 -0
  648. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +0 -47
  649. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +60 -202
  650. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +13 -56
  651. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +248 -10
  652. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
  653. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
  654. package/src/resources/extensions/gsd/tests/lazy-pi-tui-import.test.ts +44 -6
  655. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  656. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +21 -35
  657. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +37 -7
  658. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
  659. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
  660. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +267 -0
  661. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +88 -98
  662. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +70 -278
  663. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
  664. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +37 -30
  665. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +32 -28
  666. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +44 -9
  667. package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +144 -0
  668. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
  669. package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
  670. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +24 -37
  671. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +9 -24
  672. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +95 -75
  673. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  674. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  675. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +36 -22
  676. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +36 -30
  677. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
  678. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +74 -4
  679. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +20 -22
  680. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +130 -32
  681. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +18 -36
  682. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +35 -73
  683. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +76 -138
  684. package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
  685. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  686. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +70 -106
  687. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +59 -161
  688. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +33 -29
  689. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +22 -196
  690. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +23 -93
  691. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  692. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +50 -79
  693. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +27 -13
  694. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +151 -251
  695. package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +41 -29
  696. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +58 -69
  697. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +32 -164
  698. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +57 -41
  699. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +91 -0
  700. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  701. package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
  702. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +14 -9
  703. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
  704. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +222 -0
  705. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +44 -42
  706. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  707. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +56 -24
  708. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +51 -11
  709. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +23 -0
  710. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +66 -50
  711. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +68 -107
  712. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +115 -42
  713. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +21 -77
  714. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +25 -116
  715. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +21 -57
  716. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +29 -76
  717. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +33 -24
  718. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +39 -30
  719. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  720. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +55 -0
  721. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -4
  722. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +35 -40
  723. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +48 -46
  724. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +14 -102
  725. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +78 -232
  726. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +32 -35
  727. package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
  728. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
  729. package/src/resources/extensions/gsd/tests/token-profile.test.ts +84 -309
  730. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
  731. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +134 -341
  732. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +210 -0
  733. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  734. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +8 -25
  735. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +80 -1
  736. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
  737. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -99
  738. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +43 -36
  739. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -444
  740. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
  741. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +44 -189
  742. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -57
  743. package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
  744. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
  745. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
  746. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +21 -44
  747. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +27 -26
  748. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +14 -13
  749. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +50 -31
  750. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +434 -0
  751. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -18
  752. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
  753. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
  754. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +373 -76
  755. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +327 -0
  756. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +120 -0
  757. package/src/resources/extensions/gsd/tests/write-gate.test.ts +40 -1
  758. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -13
  759. package/src/resources/extensions/gsd/tool-contract.ts +82 -0
  760. package/src/resources/extensions/gsd/tools/complete-milestone.ts +14 -15
  761. package/src/resources/extensions/gsd/tools/complete-task.ts +1 -1
  762. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  763. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  764. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  765. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
  766. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  767. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  768. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  769. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
  770. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  771. package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
  772. package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
  773. package/src/resources/extensions/gsd/worktree-lifecycle.ts +1255 -0
  774. package/src/resources/extensions/gsd/worktree-safety.ts +282 -0
  775. package/src/resources/extensions/gsd/worktree-state-projection.ts +404 -0
  776. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +86 -40
  777. package/src/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
  778. package/dist/resources/extensions/gsd/worktree-resolver.js +0 -733
  779. package/dist/web/standalone/.next/static/chunks/8336.631939fb583761fa.js +0 -10
  780. package/dist/web/standalone/.next/static/chunks/app/page-fab3ebb85b006001.js +0 -1
  781. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  782. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  783. package/src/resources/extensions/gsd/tests/sync-layer-scope.test.ts +0 -434
  784. package/src/resources/extensions/gsd/worktree-resolver.ts +0 -909
  785. /package/dist/web/standalone/.next/static/{yTuahMMuJzVnsov5PreWl → drLMkgfHQ8lzS229_HWYR}/_buildManifest.js +0 -0
  786. /package/dist/web/standalone/.next/static/{yTuahMMuJzVnsov5PreWl → drLMkgfHQ8lzS229_HWYR}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  import test, { mock } from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { mkdtempSync } from "node:fs";
3
+ import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
4
4
  import { tmpdir } from "node:os";
5
5
  import { join } from "node:path";
6
6
 
@@ -10,13 +10,20 @@ import {
10
10
  _resetPendingResolve,
11
11
  _hasPendingResolveForTest,
12
12
  _setActiveSession,
13
+ _setSessionSwitchInFlight,
14
+ _markSessionSwitchAbortGraceWindow,
15
+ _clearSessionSwitchAbortGraceWindow,
16
+ _consumePendingSwitchCancellation,
13
17
  isSessionSwitchInFlight,
18
+ isSessionSwitchAbortGraceActive,
14
19
  } from "../auto/resolve.js";
15
20
  import { runUnit } from "../auto/run-unit.js";
16
21
  import { autoLoop } from "../auto/loop.js";
22
+ import { runDispatch } from "../auto/phases.js";
17
23
  import { detectStuck } from "../auto/detect-stuck.js";
18
24
  import type { UnitResult, AgentEndEvent } from "../auto/types.js";
19
25
  import type { LoopDeps } from "../auto/loop-deps.js";
26
+ import { WorktreeStateProjection } from "../worktree-state-projection.js";
20
27
  import { ModelPolicyDispatchBlockedError } from "../auto-model-selection.js";
21
28
  import type { SessionLockStatus } from "../session-lock.js";
22
29
 
@@ -64,7 +71,7 @@ function makeMockSession(opts?: {
64
71
  verbose: false,
65
72
  basePath: process.cwd(),
66
73
  cmdCtx: {
67
- newSession: (options?: { abortSignal?: AbortSignal }) => {
74
+ newSession: (options?: { abortSignal?: AbortSignal; workspaceRoot?: string }) => {
68
75
  opts?.onNewSessionStart?.(session);
69
76
  if (opts?.newSessionThrows) {
70
77
  return Promise.reject(new Error(opts.newSessionThrows));
@@ -76,7 +83,7 @@ function makeMockSession(opts?: {
76
83
  setTimeout(() => {
77
84
  // Simulate AgentSession.newSession() checking abortSignal after
78
85
  // its internal async work (abort()) completes — this is where the
79
- // real code captures process.cwd() and rebuilds the tool runtime.
86
+ // real code selects a workspace root and rebuilds the tool runtime.
80
87
  // If the signal is aborted, the real code discards the session.
81
88
  opts?.onSignalCheck?.(options?.abortSignal?.aborted ?? false);
82
89
  opts?.onNewSessionSettle?.(session);
@@ -206,6 +213,28 @@ test("runUnit returns cancelled when session creation fails", async () => {
206
213
  assert.equal(pi.calls.length, 0);
207
214
  });
208
215
 
216
+ test("runUnit clears queued switch cancellation when session creation fails", async () => {
217
+ _resetPendingResolve();
218
+
219
+ const ctx = makeMockCtx();
220
+ const pi = makeMockPi();
221
+ const s = makeMockSession({
222
+ newSessionThrows: "connection refused",
223
+ onNewSessionStart: () => {
224
+ resolveAgentEndCancelled({
225
+ message: "Claude Code process aborted by user",
226
+ category: "aborted",
227
+ isTransient: false,
228
+ });
229
+ },
230
+ });
231
+
232
+ const result = await runUnit(ctx, pi, s, "task", "T01", "prompt");
233
+
234
+ assert.equal(result.status, "cancelled");
235
+ assert.equal(_consumePendingSwitchCancellation(), null);
236
+ });
237
+
209
238
  test("runUnit returns cancelled when session creation times out", async () => {
210
239
  _resetPendingResolve();
211
240
 
@@ -221,6 +250,34 @@ test("runUnit returns cancelled when session creation times out", async () => {
221
250
  assert.equal(pi.calls.length, 0);
222
251
  });
223
252
 
253
+ test("runUnit consumes a cancellation queued during session switch before dispatch", async () => {
254
+ _resetPendingResolve();
255
+
256
+ const ctx = makeMockCtx();
257
+ const pi = makeMockPi();
258
+ let cancellationQueued = false;
259
+ const s = makeMockSession({
260
+ newSessionDelayMs: 10,
261
+ onNewSessionStart: () => {
262
+ setTimeout(() => {
263
+ cancellationQueued = !resolveAgentEndCancelled({
264
+ message: "Claude Code process aborted by user",
265
+ category: "aborted",
266
+ isTransient: false,
267
+ });
268
+ }, 0);
269
+ },
270
+ });
271
+
272
+ const result = await runUnit(ctx, pi, s, "plan-slice", "M009/S01", "prompt");
273
+
274
+ assert.equal(cancellationQueued, true);
275
+ assert.equal(result.status, "cancelled");
276
+ assert.equal(result.errorContext?.category, "aborted");
277
+ assert.equal(result.errorContext?.message, "Claude Code process aborted by user");
278
+ assert.equal(pi.calls.length, 0, "queued switch cancellation must prevent prompt dispatch");
279
+ });
280
+
224
281
  test("runUnit keeps the session-switch guard across a late newSession settlement", async () => {
225
282
  _resetPendingResolve();
226
283
  mock.timers.enable();
@@ -496,10 +553,9 @@ test("runUnit proceeds when isProviderRequestReady throws (defensive) (#4555)",
496
553
  assert.equal(pi.calls.length, 0);
497
554
  });
498
555
 
499
- test("late-resolving newSession() after timeout receives aborted signal so tool runtime is not configured with root cwd (#3731)", async () => {
500
- // When newSession() times out in runUnit(), auto-mode restores cwd to project
501
- // root. If newSession() later resolves, it must NOT use process.cwd() to
502
- // configure the tool runtime (which would give it root cwd, not worktree cwd).
556
+ test("late-resolving newSession() after timeout receives aborted signal so tool runtime is not configured with stale workspace root (#3731)", async () => {
557
+ // When newSession() times out in runUnit(), a late resolution must not
558
+ // configure the tool runtime against a stale workspace root.
503
559
  //
504
560
  // The fix: runUnit creates an AbortController, aborts it on timeout, and passes
505
561
  // the signal to newSession(). AgentSession.newSession() checks the signal after
@@ -514,8 +570,8 @@ test("late-resolving newSession() after timeout receives aborted signal so tool
514
570
 
515
571
  // newSession mock simulates AgentSession.newSession() behavior:
516
572
  // after an internal delay (representing await this.abort()), it checks the
517
- // abortSignal that's where the real code would capture process.cwd() and
518
- // call _buildRuntime. If aborted, the real code must discard the session.
573
+ // abortSignal before selecting the workspace root and calling _buildRuntime.
574
+ // If aborted, the real code must discard the session.
519
575
  const s = makeMockSession({
520
576
  newSessionDelayMs: 200_000, // longer than NEW_SESSION_TIMEOUT_MS (120s)
521
577
  onSignalCheck: (aborted) => {
@@ -548,7 +604,7 @@ test("late-resolving newSession() after timeout receives aborted signal so tool
548
604
  abortedWhenLateSessionSettled,
549
605
  true,
550
606
  "runUnit must pass an aborted AbortSignal to newSession() when it resolves after the session-creation timeout (#3731). " +
551
- "Without this, AgentSession.newSession() captures root process.cwd() and rebuilds the tool runtime with wrong cwd.",
607
+ "Without this, AgentSession.newSession() can rebuild the tool runtime with a stale workspace root.",
552
608
  );
553
609
  } finally {
554
610
  mock.timers.reset();
@@ -613,7 +669,6 @@ function makeMockDeps(
613
669
  preferences: { uok: { plan_v2: { enabled: false } } },
614
670
  }),
615
671
  preDispatchHealthGate: async () => ({ proceed: true, fixesApplied: [] }),
616
- syncProjectRootToWorktree: () => {},
617
672
  checkResourcesStale: () => null,
618
673
  validateSessionLock: () => ({ valid: true } as SessionLockStatus),
619
674
  updateSessionLock: () => {
@@ -637,7 +692,11 @@ function makeMockDeps(
637
692
  resolveMilestoneFile: () => null,
638
693
  reconcileMergeState: () => "clean",
639
694
  preflightCleanRoot: () => ({ stashPushed: false, summary: "" }),
640
- postflightPopStash: () => {},
695
+ postflightPopStash: () => ({
696
+ restored: true,
697
+ needsManualRecovery: false,
698
+ message: "restored",
699
+ }),
641
700
  getLedger: () => null,
642
701
  getProjectTotals: () => ({ cost: 0 }),
643
702
  formatCost: (c: number) => `$${c.toFixed(2)}`,
@@ -673,21 +732,15 @@ function makeMockDeps(
673
732
  readFileSync: () => "",
674
733
  atomicWriteSync: () => {},
675
734
  GitServiceImpl: class {} as any,
676
- resolver: {
677
- get workPath() {
678
- return "/tmp/project";
679
- },
680
- get projectRoot() {
681
- return "/tmp/project";
682
- },
683
- get lockPath() {
684
- return "/tmp/project";
685
- },
686
- enterMilestone: () => {},
687
- exitMilestone: () => {},
688
- mergeAndExit: () => {},
689
- mergeAndEnterNext: () => {},
735
+ lifecycle: {
736
+ enterMilestone: () => ({ ok: true, mode: "worktree", path: "/tmp/project" }),
737
+ exitMilestone: (_mid: string, opts: { merge: boolean }) => ({
738
+ ok: true,
739
+ merged: opts.merge,
740
+ codeFilesChanged: false,
741
+ }),
690
742
  } as any,
743
+ worktreeProjection: new WorktreeStateProjection(),
691
744
  postUnitPreVerification: async () => {
692
745
  callLog.push("postUnitPreVerification");
693
746
  return "continue" as const;
@@ -805,6 +858,139 @@ test("autoLoop exits on terminal complete state", async (t) => {
805
858
  );
806
859
  });
807
860
 
861
+ test("autoLoop stops before success notification when postflight stash restore needs recovery", async () => {
862
+ _resetPendingResolve();
863
+
864
+ const notifications: Array<{ msg: string; level: string }> = [];
865
+ const ctx = makeMockCtx();
866
+ ctx.ui.setStatus = () => {};
867
+ ctx.ui.notify = (msg: string, level: string) => {
868
+ notifications.push({ msg, level });
869
+ };
870
+ const pi = makeMockPi();
871
+ const s = makeLoopSession();
872
+ let stopReason = "";
873
+
874
+ const deps = makeMockDeps({
875
+ deriveState: async () => {
876
+ deps.callLog.push("deriveState");
877
+ return {
878
+ phase: "complete",
879
+ activeMilestone: { id: "M001", title: "Test", status: "complete" },
880
+ activeSlice: null,
881
+ activeTask: null,
882
+ registry: [{ id: "M001", status: "complete" }],
883
+ blockers: [],
884
+ } as any;
885
+ },
886
+ preflightCleanRoot: () => ({
887
+ stashPushed: true,
888
+ stashMarker: "gsd-preflight-stash:M001:test",
889
+ summary: "stashed",
890
+ }),
891
+ postflightPopStash: () => ({
892
+ restored: false,
893
+ needsManualRecovery: true,
894
+ message: "git stash pop stash@{0} failed after merge of milestone M001",
895
+ stashRef: "stash@{0}",
896
+ }),
897
+ sendDesktopNotification: () => {
898
+ deps.callLog.push("sendDesktopNotification");
899
+ },
900
+ logCmuxEvent: () => {
901
+ deps.callLog.push("logCmuxEvent");
902
+ },
903
+ stopAuto: async (_ctx, _pi, reason) => {
904
+ deps.callLog.push("stopAuto");
905
+ stopReason = reason ?? "";
906
+ },
907
+ });
908
+
909
+ await autoLoop(ctx, pi, s, deps);
910
+
911
+ assert.equal(stopReason, "Post-merge stash restore failed for milestone M001");
912
+ assert.ok(
913
+ notifications.some(
914
+ (n) => n.level === "error" && n.msg.includes("Post-merge stash restore failed for milestone M001"),
915
+ ),
916
+ "failed postflight restore must be surfaced as an error",
917
+ );
918
+ assert.ok(
919
+ !deps.callLog.includes("sendDesktopNotification"),
920
+ "must not emit milestone success desktop notification after stash restore failure",
921
+ );
922
+ assert.ok(
923
+ !deps.callLog.includes("logCmuxEvent"),
924
+ "must not emit milestone success cmux event after stash restore failure",
925
+ );
926
+ });
927
+
928
+ test("autoLoop marks transition merge complete before postflight recovery stop", async () => {
929
+ _resetPendingResolve();
930
+
931
+ const ctx = makeMockCtx();
932
+ ctx.ui.setStatus = () => {};
933
+ ctx.ui.notify = () => {};
934
+ const pi = makeMockPi();
935
+ const s = makeLoopSession();
936
+ let mergeCalls = 0;
937
+ let stopReason = "";
938
+
939
+ const deps = makeMockDeps({
940
+ deriveState: async () => {
941
+ deps.callLog.push("deriveState");
942
+ return {
943
+ phase: "executing",
944
+ activeMilestone: { id: "M002", title: "Next", status: "active" },
945
+ activeSlice: null,
946
+ activeTask: null,
947
+ registry: [
948
+ { id: "M001", title: "Done", status: "complete" },
949
+ { id: "M002", title: "Next", status: "active" },
950
+ ],
951
+ blockers: [],
952
+ } as any;
953
+ },
954
+ preflightCleanRoot: () => ({
955
+ stashPushed: true,
956
+ stashMarker: "gsd-preflight-stash:M001:test",
957
+ summary: "stashed",
958
+ }),
959
+ postflightPopStash: () => ({
960
+ restored: false,
961
+ needsManualRecovery: true,
962
+ message: "git stash pop stash@{0} failed after merge of milestone M001",
963
+ stashRef: "stash@{0}",
964
+ }),
965
+ lifecycle: {
966
+ enterMilestone: () => {
967
+ assert.fail("must not enter the next milestone after postflight recovery fails");
968
+ },
969
+ exitMilestone: (_mid: string, opts: { merge: boolean }) => {
970
+ if (opts.merge) mergeCalls += 1;
971
+ return { ok: true, merged: opts.merge, codeFilesChanged: false };
972
+ },
973
+ } as any,
974
+ stopAuto: async (_ctx, _pi, reason) => {
975
+ deps.callLog.push("stopAuto");
976
+ stopReason = reason ?? "";
977
+ if (!s.milestoneMergedInPhases) {
978
+ deps.lifecycle.exitMilestone(
979
+ "M001",
980
+ { merge: true },
981
+ { notify: ctx.ui.notify.bind(ctx.ui) },
982
+ );
983
+ }
984
+ },
985
+ });
986
+
987
+ await autoLoop(ctx, pi, s, deps);
988
+
989
+ assert.equal(stopReason, "Post-merge stash restore failed for milestone M001");
990
+ assert.equal(s.milestoneMergedInPhases, true);
991
+ assert.equal(mergeCalls, 1, "postflight recovery stop must not re-run an already completed transition merge");
992
+ });
993
+
808
994
  test("autoLoop pauses when provider readiness cancels before dispatch", async () => {
809
995
  _resetPendingResolve();
810
996
 
@@ -966,7 +1152,7 @@ test("autoLoop dequeues sidecar item before session-lock break (mid-session, #53
966
1152
  deps.callLog.push("postUnitPostVerification");
967
1153
  s.sidecarQueue.push({
968
1154
  kind: "hook" as const,
969
- unitType: "hook/review",
1155
+ unitType: "run-uat",
970
1156
  unitId: "M001/S01/T01/review",
971
1157
  prompt: "review the code",
972
1158
  });
@@ -1453,7 +1639,7 @@ test("autoLoop drains sidecar queue after postUnitPostVerification enqueues item
1453
1639
  // First call (main unit): enqueue a sidecar item
1454
1640
  s.sidecarQueue.push({
1455
1641
  kind: "hook" as const,
1456
- unitType: "hook/review",
1642
+ unitType: "run-uat",
1457
1643
  unitId: "M001/S01/T01/review",
1458
1644
  prompt: "review the code",
1459
1645
  });
@@ -1475,11 +1661,17 @@ test("autoLoop drains sidecar queue after postUnitPostVerification enqueues item
1475
1661
  const loopPromise = autoLoop(ctx, pi, s, deps);
1476
1662
 
1477
1663
  // Wait for main unit's runUnit to be awaiting
1478
- await new Promise((r) => setTimeout(r, 50));
1664
+ for (let i = 0; !_hasPendingResolveForTest() && i < 100; i++) {
1665
+ await new Promise((r) => setTimeout(r, 5));
1666
+ }
1667
+ assert.equal(_hasPendingResolveForTest(), true, "main unit should be awaiting agent_end");
1479
1668
  resolveAgentEnd(makeEvent()); // resolve main unit
1480
1669
 
1481
1670
  // Wait for the sidecar unit's runUnit to be awaiting
1482
- await new Promise((r) => setTimeout(r, 50));
1671
+ for (let i = 0; !_hasPendingResolveForTest() && postVerCallCount < 2 && i < 100; i++) {
1672
+ await new Promise((r) => setTimeout(r, 5));
1673
+ }
1674
+ assert.equal(_hasPendingResolveForTest(), true, "sidecar unit should be awaiting agent_end");
1483
1675
  resolveAgentEnd(makeEvent()); // resolve sidecar unit
1484
1676
 
1485
1677
  await loopPromise;
@@ -1898,7 +2090,7 @@ test("autoLoop lifecycle: advances through research → plan → execute → ver
1898
2090
  { unitType: "research-slice", unitId: "M001/S01", prompt: "research" },
1899
2091
  { unitType: "plan-slice", unitId: "M001/S01", prompt: "plan" },
1900
2092
  { unitType: "execute-task", unitId: "M001/S01/T01", prompt: "execute" },
1901
- { unitType: "verify-slice", unitId: "M001/S01", prompt: "verify" },
2093
+ { unitType: "run-uat", unitId: "M001/S01", prompt: "verify" },
1902
2094
  { unitType: "complete-slice", unitId: "M001/S01", prompt: "complete" },
1903
2095
  ];
1904
2096
 
@@ -1968,8 +2160,8 @@ test("autoLoop lifecycle: advances through research → plan → execute → ver
1968
2160
  `should have dispatched execute-task, got: ${dispatchedUnitTypes.join(", ")}`,
1969
2161
  );
1970
2162
  assert.ok(
1971
- dispatchedUnitTypes.includes("verify-slice"),
1972
- `should have dispatched verify-slice, got: ${dispatchedUnitTypes.join(", ")}`,
2163
+ dispatchedUnitTypes.includes("run-uat"),
2164
+ `should have dispatched run-uat, got: ${dispatchedUnitTypes.join(", ")}`,
1973
2165
  );
1974
2166
  assert.ok(
1975
2167
  dispatchedUnitTypes.includes("complete-slice"),
@@ -2001,7 +2193,7 @@ test("autoLoop lifecycle: advances through research → plan → execute → ver
2001
2193
  "research-slice",
2002
2194
  "plan-slice",
2003
2195
  "execute-task",
2004
- "verify-slice",
2196
+ "run-uat",
2005
2197
  "complete-slice",
2006
2198
  ],
2007
2199
  "dispatched unit types should follow the full lifecycle sequence",
@@ -2089,6 +2281,37 @@ test("resolveAgentEndCancelled without args produces no errorContext field", asy
2089
2281
  assert.equal(resolved.errorContext, undefined, "errorContext must not be present when no args passed");
2090
2282
  });
2091
2283
 
2284
+ test("resolveAgentEndCancelled queues cancellation that arrives during session switch", () => {
2285
+ _resetPendingResolve();
2286
+
2287
+ _setSessionSwitchInFlight(true);
2288
+ const resolved = resolveAgentEndCancelled({
2289
+ message: "Claude Code process aborted by user",
2290
+ category: "aborted",
2291
+ isTransient: false,
2292
+ });
2293
+
2294
+ assert.equal(resolved, false);
2295
+ const pending = _consumePendingSwitchCancellation();
2296
+ assert.ok(pending?.errorContext, "queued cancellation should preserve errorContext");
2297
+ assert.equal(pending.errorContext.category, "aborted");
2298
+ assert.equal(pending.errorContext.message, "Claude Code process aborted by user");
2299
+ assert.equal(_consumePendingSwitchCancellation(), null);
2300
+ _resetPendingResolve();
2301
+ });
2302
+
2303
+ test("session-switch abort grace window is short-lived and resettable", () => {
2304
+ _resetPendingResolve();
2305
+
2306
+ _markSessionSwitchAbortGraceWindow(1_000);
2307
+
2308
+ assert.equal(isSessionSwitchAbortGraceActive(Date.now()), true);
2309
+ assert.equal(isSessionSwitchAbortGraceActive(Date.now() + 10_000), false);
2310
+
2311
+ _clearSessionSwitchAbortGraceWindow();
2312
+ assert.equal(isSessionSwitchAbortGraceActive(), false);
2313
+ });
2314
+
2092
2315
  // ─── #1571: artifact verification retry ──────────────────────────────────────
2093
2316
 
2094
2317
  test("autoLoop re-iterates when postUnitPreVerification returns retry (#1571)", async () => {
@@ -2465,7 +2688,7 @@ test("autoLoop rejects complete-slice with 0 tool calls as context-exhausted (#2
2465
2688
 
2466
2689
  // ─── Worktree health check (#1833) ────────────────────────────────────────
2467
2690
 
2468
- test("autoLoop stops when worktree has no .git for execute-task (#1833)", async () => {
2691
+ test("autoLoop stops when Worktree Safety finds no .git marker for execute-task (#1833)", async (t) => {
2469
2692
  _resetPendingResolve();
2470
2693
 
2471
2694
  const ctx = makeMockCtx();
@@ -2476,7 +2699,16 @@ test("autoLoop stops when worktree has no .git for execute-task (#1833)", async
2476
2699
  const notifications: string[] = [];
2477
2700
  ctx.ui.notify = (msg: string) => { notifications.push(msg); };
2478
2701
 
2479
- const s = makeLoopSession({ basePath: "/tmp/broken-worktree" });
2702
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-wt-safety-loop-"));
2703
+ const worktreeRoot = join(projectRoot, ".gsd", "worktrees", "M001");
2704
+ mkdirSync(worktreeRoot, { recursive: true });
2705
+ t.after(() => rmSync(projectRoot, { recursive: true, force: true }));
2706
+
2707
+ const s = makeLoopSession({
2708
+ basePath: worktreeRoot,
2709
+ originalBasePath: projectRoot,
2710
+ canonicalProjectRoot: projectRoot,
2711
+ });
2480
2712
 
2481
2713
  const deps = makeMockDeps({
2482
2714
  deriveState: async () => {
@@ -2490,8 +2722,7 @@ test("autoLoop stops when worktree has no .git for execute-task (#1833)", async
2490
2722
  blockers: [],
2491
2723
  } as any;
2492
2724
  },
2493
- // .git does not exist in the broken worktree
2494
- existsSync: (p: string) => !p.endsWith(".git"),
2725
+ getIsolationMode: () => "worktree",
2495
2726
  });
2496
2727
 
2497
2728
  await autoLoop(ctx, pi, s, deps);
@@ -2501,11 +2732,283 @@ test("autoLoop stops when worktree has no .git for execute-task (#1833)", async
2501
2732
  "should stop auto-mode when worktree is invalid",
2502
2733
  );
2503
2734
  const healthNotification = notifications.find(
2504
- (n) => n.includes("Worktree health check failed") && n.includes("no .git"),
2735
+ (n) => n.includes("Worktree Safety failed") && n.includes("worktree-git-marker-missing"),
2505
2736
  );
2506
2737
  assert.ok(
2507
2738
  healthNotification,
2508
- "should notify about missing .git in worktree",
2739
+ "should notify about missing worktree .git marker",
2740
+ );
2741
+ });
2742
+
2743
+ test("dispatch Worktree Safety wins before stuck detection for execute-task without .git", async (t) => {
2744
+ _resetPendingResolve();
2745
+
2746
+ const ctx = makeMockCtx();
2747
+ const pi = makeMockPi();
2748
+ const notifications: string[] = [];
2749
+ ctx.ui.notify = (msg: string) => { notifications.push(msg); };
2750
+
2751
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-wt-safety-dispatch-"));
2752
+ const worktreeRoot = join(projectRoot, ".gsd", "worktrees", "M001");
2753
+ mkdirSync(worktreeRoot, { recursive: true });
2754
+ t.after(() => rmSync(projectRoot, { recursive: true, force: true }));
2755
+
2756
+ const s = makeLoopSession({
2757
+ basePath: worktreeRoot,
2758
+ originalBasePath: projectRoot,
2759
+ canonicalProjectRoot: projectRoot,
2760
+ });
2761
+ const deps = makeMockDeps({
2762
+ getIsolationMode: () => "worktree",
2763
+ });
2764
+ const result = await runDispatch(
2765
+ {
2766
+ ctx,
2767
+ pi,
2768
+ s,
2769
+ deps,
2770
+ prefs: undefined,
2771
+ iteration: 1,
2772
+ flowId: "test-flow",
2773
+ nextSeq: () => 1,
2774
+ },
2775
+ {
2776
+ state: {
2777
+ phase: "executing",
2778
+ activeMilestone: { id: "M001", title: "Test", status: "active" },
2779
+ activeSlice: { id: "S01", title: "Slice 1" },
2780
+ activeTask: { id: "T01" },
2781
+ registry: [{ id: "M001", status: "active" }],
2782
+ blockers: [],
2783
+ } as any,
2784
+ mid: "M001",
2785
+ midTitle: "Test",
2786
+ },
2787
+ {
2788
+ recentUnits: [
2789
+ { key: "execute-task/M001/S01/T01" },
2790
+ { key: "execute-task/M001/S01/T01" },
2791
+ ],
2792
+ stuckRecoveryAttempts: 1,
2793
+ consecutiveFinalizeTimeouts: 0,
2794
+ },
2795
+ );
2796
+
2797
+ assert.equal(result.action, "break");
2798
+ assert.equal(result.reason, "worktree-git-marker-missing");
2799
+ assert.ok(deps.callLog.includes("stopAuto"), "should stop through Worktree Safety");
2800
+ assert.ok(
2801
+ notifications.some((n) => n.includes("Worktree Safety failed") && n.includes("worktree-git-marker-missing")),
2802
+ "should notify about missing worktree .git marker",
2803
+ );
2804
+ assert.ok(
2805
+ !notifications.some((n) => n.includes("Stuck on execute-task")),
2806
+ "stuck-loop message must not mask the worktree health failure",
2807
+ );
2808
+ });
2809
+
2810
+ test("dispatch Worktree Safety stops unknown unit types with missing Tool Contract", async (t) => {
2811
+ _resetPendingResolve();
2812
+
2813
+ const ctx = makeMockCtx();
2814
+ const pi = makeMockPi();
2815
+ const notifications: string[] = [];
2816
+ ctx.ui.notify = (msg: string) => { notifications.push(msg); };
2817
+
2818
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-wt-safety-missing-contract-"));
2819
+ const worktreeRoot = join(projectRoot, ".gsd", "worktrees", "M001");
2820
+ mkdirSync(worktreeRoot, { recursive: true });
2821
+ t.after(() => rmSync(projectRoot, { recursive: true, force: true }));
2822
+
2823
+ const s = makeLoopSession({
2824
+ basePath: worktreeRoot,
2825
+ originalBasePath: projectRoot,
2826
+ canonicalProjectRoot: projectRoot,
2827
+ });
2828
+ const deps = makeMockDeps({
2829
+ getIsolationMode: () => "worktree",
2830
+ resolveDispatch: async () => {
2831
+ deps.callLog.push("resolveDispatch");
2832
+ return {
2833
+ action: "dispatch" as const,
2834
+ unitType: "new-source-writing-unit-without-manifest",
2835
+ unitId: "M001/S01/T01",
2836
+ prompt: "do the thing",
2837
+ };
2838
+ },
2839
+ });
2840
+
2841
+ const result = await runDispatch(
2842
+ {
2843
+ ctx,
2844
+ pi,
2845
+ s,
2846
+ deps,
2847
+ prefs: undefined,
2848
+ iteration: 1,
2849
+ flowId: "test-flow",
2850
+ nextSeq: () => 1,
2851
+ },
2852
+ {
2853
+ state: {
2854
+ phase: "executing",
2855
+ activeMilestone: { id: "M001", title: "Test", status: "active" },
2856
+ activeSlice: { id: "S01", title: "Slice 1" },
2857
+ activeTask: { id: "T01" },
2858
+ registry: [{ id: "M001", status: "active" }],
2859
+ blockers: [],
2860
+ } as any,
2861
+ mid: "M001",
2862
+ midTitle: "Test",
2863
+ },
2864
+ {
2865
+ recentUnits: [],
2866
+ stuckRecoveryAttempts: 0,
2867
+ consecutiveFinalizeTimeouts: 0,
2868
+ },
2869
+ );
2870
+
2871
+ assert.equal(result.action, "break");
2872
+ assert.equal(result.reason, "missing-tool-contract");
2873
+ assert.ok(deps.callLog.includes("stopAuto"), "should stop when the Tool Contract is missing");
2874
+ assert.ok(
2875
+ notifications.some((n) => n.includes("missing Tool Contract for new-source-writing-unit-without-manifest")),
2876
+ "should notify with an actionable missing Tool Contract reason",
2877
+ );
2878
+ });
2879
+
2880
+ test("pre-dispatch skip resolves before dispatch health and stuck accounting", async () => {
2881
+ _resetPendingResolve();
2882
+
2883
+ const ctx = makeMockCtx();
2884
+ const pi = makeMockPi();
2885
+ const notifications: string[] = [];
2886
+ ctx.ui.notify = (msg: string) => { notifications.push(msg); };
2887
+
2888
+ const s = makeLoopSession({ basePath: "/tmp/broken-worktree" });
2889
+ const deps = makeMockDeps({
2890
+ existsSync: (p: string) => !p.endsWith(".git"),
2891
+ runPreDispatchHooks: () => ({ firedHooks: ["skip-execute"], action: "skip" }),
2892
+ });
2893
+ const loopState = {
2894
+ recentUnits: [
2895
+ { key: "execute-task/M001/S01/T01" },
2896
+ { key: "execute-task/M001/S01/T01" },
2897
+ ],
2898
+ stuckRecoveryAttempts: 1,
2899
+ consecutiveFinalizeTimeouts: 0,
2900
+ };
2901
+
2902
+ const result = await runDispatch(
2903
+ {
2904
+ ctx,
2905
+ pi,
2906
+ s,
2907
+ deps,
2908
+ prefs: undefined,
2909
+ iteration: 1,
2910
+ flowId: "test-flow",
2911
+ nextSeq: () => 1,
2912
+ },
2913
+ {
2914
+ state: {
2915
+ phase: "executing",
2916
+ activeMilestone: { id: "M001", title: "Test", status: "active" },
2917
+ activeSlice: { id: "S01", title: "Slice 1" },
2918
+ activeTask: { id: "T01" },
2919
+ registry: [{ id: "M001", status: "active" }],
2920
+ blockers: [],
2921
+ } as any,
2922
+ mid: "M001",
2923
+ midTitle: "Test",
2924
+ },
2925
+ loopState,
2926
+ );
2927
+
2928
+ assert.equal(result.action, "continue");
2929
+ assert.ok(!deps.callLog.includes("stopAuto"), "skip hook should not stop on worktree health");
2930
+ assert.equal(loopState.recentUnits.length, 2, "skip hook should not update stuck accounting");
2931
+ assert.ok(
2932
+ notifications.some((n) => n.includes("Skipping execute-task M001/S01/T01")),
2933
+ "should notify about the skip hook",
2934
+ );
2935
+ assert.ok(
2936
+ !notifications.some((n) => n.includes("Worktree health check failed") || n.includes("Stuck on execute-task")),
2937
+ "health and stuck notifications must not run before skip hook resolution",
2938
+ );
2939
+ });
2940
+
2941
+ test("pre-dispatch replace resolves final unit before dispatch health and stuck accounting", async () => {
2942
+ _resetPendingResolve();
2943
+
2944
+ const ctx = makeMockCtx();
2945
+ const pi = makeMockPi();
2946
+ const notifications: string[] = [];
2947
+ ctx.ui.notify = (msg: string) => { notifications.push(msg); };
2948
+
2949
+ const s = makeLoopSession({ basePath: "/tmp/broken-worktree" });
2950
+ const deps = makeMockDeps({
2951
+ existsSync: (p: string) => !p.endsWith(".git"),
2952
+ runPreDispatchHooks: () => ({
2953
+ firedHooks: ["review"],
2954
+ action: "replace",
2955
+ unitType: "run-uat",
2956
+ prompt: "review before executing",
2957
+ model: "review-model",
2958
+ }),
2959
+ });
2960
+ const loopState = {
2961
+ recentUnits: [
2962
+ { key: "execute-task/M001/S01/T01" },
2963
+ { key: "execute-task/M001/S01/T01" },
2964
+ ],
2965
+ stuckRecoveryAttempts: 1,
2966
+ consecutiveFinalizeTimeouts: 0,
2967
+ };
2968
+
2969
+ const result = await runDispatch(
2970
+ {
2971
+ ctx,
2972
+ pi,
2973
+ s,
2974
+ deps,
2975
+ prefs: undefined,
2976
+ iteration: 1,
2977
+ flowId: "test-flow",
2978
+ nextSeq: () => 1,
2979
+ },
2980
+ {
2981
+ state: {
2982
+ phase: "executing",
2983
+ activeMilestone: { id: "M001", title: "Test", status: "active" },
2984
+ activeSlice: { id: "S01", title: "Slice 1" },
2985
+ activeTask: { id: "T01" },
2986
+ registry: [{ id: "M001", status: "active" }],
2987
+ blockers: [],
2988
+ } as any,
2989
+ mid: "M001",
2990
+ midTitle: "Test",
2991
+ },
2992
+ loopState,
2993
+ );
2994
+
2995
+ assert.equal(result.action, "next");
2996
+ assert.equal(result.data?.unitType, "run-uat");
2997
+ assert.equal(result.data?.finalPrompt, "review before executing");
2998
+ assert.equal(result.data?.hookModelOverride, "review-model");
2999
+ assert.ok(!deps.callLog.includes("stopAuto"), "replace hook should not stop on execute-task health");
3000
+ assert.deepEqual(
3001
+ loopState.recentUnits.map((u) => u.key),
3002
+ [
3003
+ "execute-task/M001/S01/T01",
3004
+ "execute-task/M001/S01/T01",
3005
+ "run-uat/M001/S01/T01",
3006
+ ],
3007
+ "stuck accounting should record the final replaced unit",
3008
+ );
3009
+ assert.ok(
3010
+ !notifications.some((n) => n.includes("Worktree health check failed") || n.includes("Stuck on execute-task")),
3011
+ "health and stuck notifications must use the final replaced unit",
2509
3012
  );
2510
3013
  });
2511
3014