@opengsd/gsd-pi 1.2.0-dev.e8563f58 → 1.2.0-dev.fbdca60b

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 (432) hide show
  1. package/dist/cli-model-override.d.ts +15 -0
  2. package/dist/cli-model-override.js +21 -0
  3. package/dist/cli.js +1 -18
  4. package/dist/loader.js +6 -4
  5. package/dist/register-agent-bundles.d.ts +11 -2
  6. package/dist/register-agent-bundles.js +18 -4
  7. package/dist/resource-loader.d.ts +10 -5
  8. package/dist/resource-loader.js +121 -6
  9. package/dist/resources/.managed-resources-content-hash +1 -1
  10. package/dist/resources/extensions/ask-user-questions.js +3 -2
  11. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
  12. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
  13. package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
  14. package/dist/resources/extensions/gsd/auto/dispatch-history.js +21 -6
  15. package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
  16. package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
  17. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  18. package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
  19. package/dist/resources/extensions/gsd/auto/orchestrator.js +85 -15
  20. package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
  21. package/dist/resources/extensions/gsd/auto/phases.js +17 -2329
  22. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
  23. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  24. package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
  25. package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
  26. package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
  27. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +3 -2
  28. package/dist/resources/extensions/gsd/auto-dispatch.js +11 -2
  29. package/dist/resources/extensions/gsd/auto-post-unit.js +18 -6
  30. package/dist/resources/extensions/gsd/auto-start.js +23 -3
  31. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  32. package/dist/resources/extensions/gsd/auto-verification.js +14 -2
  33. package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
  34. package/dist/resources/extensions/gsd/auto.js +45 -2
  35. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
  36. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  37. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
  38. package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
  39. package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
  40. package/dist/resources/extensions/gsd/db/engine.js +24 -6
  41. package/dist/resources/extensions/gsd/db/queries.js +30 -0
  42. package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
  43. package/dist/resources/extensions/gsd/db-transaction.js +27 -23
  44. package/dist/resources/extensions/gsd/db-writer.js +8 -17
  45. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  46. package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
  47. package/dist/resources/extensions/gsd/gsd-db.js +15 -20
  48. package/dist/resources/extensions/gsd/guided-flow.js +93 -4
  49. package/dist/resources/extensions/gsd/health-widget.js +87 -28
  50. package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
  51. package/dist/resources/extensions/gsd/memory-relations.js +1 -1
  52. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  53. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  54. package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
  55. package/dist/resources/extensions/gsd/notifications.js +12 -7
  56. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  57. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  58. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
  59. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  60. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  61. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  62. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  63. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  64. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  66. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  68. package/dist/resources/extensions/gsd/prompts/run-uat.md +3 -1
  69. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  72. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  73. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  74. package/dist/resources/extensions/gsd/skill-activation.js +3 -6
  75. package/dist/resources/extensions/gsd/state.js +6 -2
  76. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  77. package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
  78. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  79. package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
  80. package/dist/resources/extensions/gsd/tools/complete-task.js +65 -2
  81. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
  82. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  83. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  84. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  85. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
  86. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  87. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  88. package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
  89. package/dist/resources/extensions/gsd/unit-registry.js +34 -4
  90. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  91. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  92. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  93. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  94. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
  95. package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
  96. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  97. package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
  98. package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
  99. package/dist/resources/extensions/gsd/worktree.js +8 -1
  100. package/dist/resources/extensions/mcp-client/manager.js +6 -1
  101. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  102. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  103. package/dist/runtime-checks.d.ts +10 -0
  104. package/dist/runtime-checks.js +27 -0
  105. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  106. package/dist/web/standalone/.next/BUILD_ID +1 -1
  107. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  108. package/dist/web/standalone/.next/build-manifest.json +2 -2
  109. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  110. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  130. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  131. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  132. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  134. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  136. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  138. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  140. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  142. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  146. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  156. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  158. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/index.html +1 -1
  161. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  162. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  163. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  164. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  165. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  166. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  167. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  168. package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
  169. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  170. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  172. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  173. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  174. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  175. package/package.json +3 -3
  176. package/packages/cloud-mcp-gateway/package.json +2 -2
  177. package/packages/contracts/package.json +1 -1
  178. package/packages/daemon/package.json +4 -4
  179. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  180. package/packages/gsd-agent-core/dist/sdk.js +6 -4
  181. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  182. package/packages/gsd-agent-core/package.json +5 -5
  183. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  186. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  187. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  188. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +50 -6
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +2 -0
  192. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
  194. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
  196. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  197. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +17 -0
  198. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  199. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
  201. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  202. package/packages/gsd-agent-modes/package.json +7 -7
  203. package/packages/mcp-server/README.md +12 -3
  204. package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
  205. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
  206. package/packages/mcp-server/dist/cli-runner.js +137 -0
  207. package/packages/mcp-server/dist/cli-runner.js.map +1 -0
  208. package/packages/mcp-server/dist/cli.js +2 -53
  209. package/packages/mcp-server/dist/cli.js.map +1 -1
  210. package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
  211. package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
  212. package/packages/mcp-server/dist/pid-registry.js +459 -0
  213. package/packages/mcp-server/dist/pid-registry.js.map +1 -0
  214. package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
  215. package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
  216. package/packages/mcp-server/dist/probe-mode.js +10 -0
  217. package/packages/mcp-server/dist/probe-mode.js.map +1 -0
  218. package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
  219. package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
  220. package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
  221. package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
  222. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  223. package/packages/mcp-server/dist/workflow-tools.js +62 -43
  224. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  225. package/packages/mcp-server/package.json +5 -5
  226. package/packages/native/package.json +1 -1
  227. package/packages/pi-agent-core/dist/agent-loop.js +43 -2
  228. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  229. package/packages/pi-agent-core/package.json +1 -1
  230. package/packages/pi-ai/package.json +1 -1
  231. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  232. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  234. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  236. package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
  237. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  238. package/packages/pi-coding-agent/package.json +7 -7
  239. package/packages/pi-tui/README.md +15 -0
  240. package/packages/pi-tui/dist/index.d.ts +2 -2
  241. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  242. package/packages/pi-tui/dist/index.js +2 -2
  243. package/packages/pi-tui/dist/index.js.map +1 -1
  244. package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
  245. package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
  246. package/packages/pi-tui/dist/terminal-image.js +54 -2
  247. package/packages/pi-tui/dist/terminal-image.js.map +1 -1
  248. package/packages/pi-tui/dist/terminal.d.ts +12 -0
  249. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  250. package/packages/pi-tui/dist/terminal.js +70 -25
  251. package/packages/pi-tui/dist/terminal.js.map +1 -1
  252. package/packages/pi-tui/dist/tui.d.ts +15 -0
  253. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  254. package/packages/pi-tui/dist/tui.js +106 -21
  255. package/packages/pi-tui/dist/tui.js.map +1 -1
  256. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  257. package/packages/pi-tui/dist/utils.js +110 -36
  258. package/packages/pi-tui/dist/utils.js.map +1 -1
  259. package/packages/pi-tui/package.json +2 -2
  260. package/packages/rpc-client/package.json +2 -2
  261. package/pkg/dist/theme/theme.d.ts.map +1 -1
  262. package/pkg/dist/theme/theme.js +45 -17
  263. package/pkg/dist/theme/theme.js.map +1 -1
  264. package/pkg/package.json +1 -1
  265. package/src/resources/extensions/ask-user-questions.ts +7 -2
  266. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
  267. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
  268. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
  269. package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
  270. package/src/resources/extensions/gsd/auto/dispatch-history.ts +22 -6
  271. package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
  272. package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
  273. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  274. package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
  275. package/src/resources/extensions/gsd/auto/orchestrator.ts +95 -15
  276. package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
  277. package/src/resources/extensions/gsd/auto/phases.ts +58 -3022
  278. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
  279. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  280. package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
  281. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
  282. package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
  283. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +10 -16
  284. package/src/resources/extensions/gsd/auto-dispatch.ts +11 -10
  285. package/src/resources/extensions/gsd/auto-post-unit.ts +21 -6
  286. package/src/resources/extensions/gsd/auto-start.ts +24 -4
  287. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  288. package/src/resources/extensions/gsd/auto-verification.ts +18 -2
  289. package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
  290. package/src/resources/extensions/gsd/auto.ts +56 -2
  291. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
  292. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  293. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
  294. package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
  295. package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
  296. package/src/resources/extensions/gsd/db/engine.ts +26 -6
  297. package/src/resources/extensions/gsd/db/queries.ts +29 -0
  298. package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
  299. package/src/resources/extensions/gsd/db-transaction.ts +37 -20
  300. package/src/resources/extensions/gsd/db-writer.ts +11 -19
  301. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  302. package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
  303. package/src/resources/extensions/gsd/gsd-db.ts +15 -19
  304. package/src/resources/extensions/gsd/guided-flow.ts +145 -24
  305. package/src/resources/extensions/gsd/health-widget.ts +91 -27
  306. package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
  307. package/src/resources/extensions/gsd/memory-relations.ts +1 -1
  308. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  309. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  310. package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
  311. package/src/resources/extensions/gsd/notifications.ts +13 -6
  312. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  313. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  314. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
  315. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  316. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  317. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  318. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  319. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  320. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  321. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  322. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  323. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  324. package/src/resources/extensions/gsd/prompts/run-uat.md +3 -1
  325. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  326. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  327. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  328. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  329. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  330. package/src/resources/extensions/gsd/skill-activation.ts +3 -6
  331. package/src/resources/extensions/gsd/state.ts +7 -1
  332. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
  333. package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
  334. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
  335. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +6 -1
  336. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +76 -12
  337. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
  338. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
  339. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
  340. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  341. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
  342. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
  343. package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
  344. package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
  345. package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
  346. package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
  347. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +2 -1
  348. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +62 -0
  349. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  350. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +55 -0
  351. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
  352. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
  353. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
  354. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +19 -0
  355. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
  356. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
  357. package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
  358. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +18 -0
  359. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
  360. package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
  361. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
  362. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
  363. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
  364. package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
  365. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
  366. package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
  367. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
  368. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +5 -0
  369. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
  370. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  371. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
  372. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  373. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
  374. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
  375. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
  376. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  377. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +26 -2
  378. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
  379. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
  380. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
  381. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
  382. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  383. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
  384. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
  385. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  386. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  387. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  388. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  389. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  390. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  391. package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
  392. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
  393. package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
  394. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  395. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
  396. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
  397. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
  398. package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
  399. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
  400. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  401. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  402. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  403. package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
  404. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  405. package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
  406. package/src/resources/extensions/gsd/tools/complete-task.ts +90 -2
  407. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
  408. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  409. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  410. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  411. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
  412. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  413. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  414. package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
  415. package/src/resources/extensions/gsd/unit-registry.ts +34 -4
  416. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  417. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  418. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  419. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  420. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
  421. package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
  422. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  423. package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
  424. package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
  425. package/src/resources/extensions/gsd/worktree.ts +7 -1
  426. package/src/resources/extensions/mcp-client/manager.ts +7 -1
  427. package/src/resources/skills/create-skill/SKILL.md +3 -0
  428. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  429. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  430. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  431. /package/dist/web/standalone/.next/static/{LDHRKiRBIVZmiuMjrL1Vy → 2T9IOdiiM3o3gZ4UbPi8E}/_buildManifest.js +0 -0
  432. /package/dist/web/standalone/.next/static/{LDHRKiRBIVZmiuMjrL1Vy → 2T9IOdiiM3o3gZ4UbPi8E}/_ssgManifest.js +0 -0
@@ -55,4 +55,4 @@ The slice directory already exists at `{{slicePath}}/`. Do NOT mkdir.
55
55
 
56
56
  **You MUST call `gsd_summary_save` with the research content before finishing.**
57
57
 
58
- When done, say: "Slice {{sliceId}} researched."
58
+ When done, say: "Slice {{sliceId}} researched." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -30,4 +30,4 @@ An override was issued by the user that changes a fundamental decision or approa
30
30
 
31
31
  **You MUST update the relevant documents AND mark overrides as resolved in `{{overridesPath}}` before finishing.**
32
32
 
33
- When done, say: "Override applied across all documents."
33
+ When done, say: "Override applied across all documents." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -10,6 +10,8 @@ If any inlined plan, summary, verification command, or prior artifact names an a
10
10
 
11
11
  All relevant context has been preloaded below. Start working immediately without re-reading these files.
12
12
 
13
+ If a `.gsd/**` or `.gsd/**/*` glob returns no matches, treat that as a possible symlink-backed traversal limitation; do not infer that the GSD harness is missing. Use the preloaded UAT context and direct `.gsd/...` file paths named in this prompt instead.
14
+
13
15
  {{inlinedContext}}
14
16
 
15
17
  {{skillActivation}}
@@ -100,4 +102,4 @@ checks: [{
100
102
 
101
103
  **You MUST call `gsd_uat_result_save` before finishing. Do not write the assessment file directly, and do not call `gsd_summary_save` as a substitute.**
102
104
 
103
- When done, say: "UAT {{sliceId}} complete."
105
+ When done, say: "UAT {{sliceId}} complete." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -65,4 +65,4 @@ Classify each capture as one of:
65
65
 
66
66
  **Important:** Do NOT execute any resolutions. Only classify and update CAPTURES.md. Resolution execution happens separately (in auto-mode dispatch or manually by the user).
67
67
 
68
- When done, say: "Triage complete."
68
+ When done, say: "Triage complete." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -87,4 +87,4 @@ If verdict is `needs-remediation`:
87
87
 
88
88
  **File system safety:** When scanning milestone directories, use `ls` or `find` first. Never pass a directory path such as `tasks/` or `slices/` directly to `read`; it only accepts files.
89
89
 
90
- When done, say: "Milestone {{milestoneId}} validation complete — verdict: <verdict>."
90
+ When done, say: "Milestone {{milestoneId}} validation complete — verdict: <verdict>." Say this exactly once — if you already said it in a prior message, do not repeat it.
@@ -25,4 +25,5 @@ Follow the workflow defined below. Execute each phase in order, completing one b
25
25
  3. **Atomic commits.** Commit working code after each meaningful change. Use conventional commit format: `<type>(<scope>): <description>`.
26
26
  4. **Verify before shipping.** Run the project's test suite and build before marking the workflow complete.
27
27
  5. **Decision gates, not ceremony.** After each phase, summarize what changed. For low/medium complexity, ask for confirmation only when the next phase depends on a real user choice or external approval. For high complexity, confirm before proceeding to each new phase.
28
- 6. **Stay focused.** This is a {{complexity}}-complexity workflow. Match your ceremony level to the task don't over-engineer or under-deliver.
28
+ 6. **Persist workflow state.** If the artifact directory contains `STATE.json`, update it after each phase: mark the finished phase `completed`, mark the next phase `active`, set `currentPhase` to the active phase index, and refresh `updatedAt`. When every phase is completed, set `completedAt` to the completion timestamp.
29
+ 7. **Stay focused.** This is a {{complexity}}-complexity workflow. Match your ceremony level to the task — don't over-engineer or under-deliver.
@@ -154,6 +154,29 @@ function parseTableSlices(section: string): RoadmapSliceEntry[] {
154
154
  return slices;
155
155
  }
156
156
 
157
+ function looksLikeTable(section: string): boolean {
158
+ const lines = section.split("\n");
159
+
160
+ // Checkbox format takes precedence — embedded demo tables must not switch mode (#721).
161
+ if (lines.some(line => /^\s*-\s+\[[ xX]\]/.test(line))) {
162
+ return false;
163
+ }
164
+
165
+ const pipeLines = lines.filter(line => /^\s*\|/.test(line));
166
+ if (pipeLines.length < 2) return false;
167
+
168
+ const hasSeparatorRow = pipeLines.some((line, index) => {
169
+ if (index === 0) return false;
170
+ const cells = line.split("|").map(c => c.trim()).filter(Boolean);
171
+ return /^\s*\|[\s:-]+\|/.test(line) && cells.length >= 2 && cells.every(c => /^[\s:-]+$/.test(c));
172
+ });
173
+
174
+ if (hasSeparatorRow) return true;
175
+
176
+ // Tables without a separator row still expose slice IDs in data rows.
177
+ return pipeLines.some(line => /\bS\d+\b/.test(line));
178
+ }
179
+
157
180
  export function parseRoadmapSlices(content: string): RoadmapSliceEntry[] {
158
181
  const slicesSection = extractSlicesSection(content);
159
182
  if (!slicesSection) {
@@ -165,9 +188,11 @@ export function parseRoadmapSlices(content: string): RoadmapSliceEntry[] {
165
188
 
166
189
  // Try table format first — if the section contains pipe-delimited rows with
167
190
  // slice IDs, parse them as a table (#1736).
168
- const tableSlices = parseTableSlices(slicesSection);
169
- if (tableSlices.length > 0) {
170
- return tableSlices;
191
+ if (looksLikeTable(slicesSection)) {
192
+ const tableSlices = parseTableSlices(slicesSection);
193
+ if (tableSlices.length > 0) {
194
+ return tableSlices;
195
+ }
171
196
  }
172
197
 
173
198
  // Standard checkbox format
@@ -387,7 +387,7 @@ export function acquireSessionLock(basePath: string): SessionLockResult {
387
387
  // #3218: Provide actionable workaround when lock recovery fails
388
388
  const lockDirPath = lockTarget + ".lock";
389
389
  const reason = existingPid
390
- ? `Another auto-mode session (PID ${existingPid}) appears to be running.\nStop it with \`kill ${existingPid}\` before starting a new session.`
390
+ ? `Another auto-mode session (PID ${existingPid}) appears to be running.\nRun \`/gsd stop\` for graceful shutdown, or choose "Force start" from \`/gsd auto\` to terminate it.`
391
391
  : `Another auto-mode session lock is stuck on this project.\nRun: rm -rf "${lockDirPath}" && rm -f "${lp}"`;
392
392
 
393
393
  return { acquired: false, reason, existingPid };
@@ -134,11 +134,8 @@ const SAFE_SKILL_NAME = /^[a-z0-9][a-z0-9-]*$/;
134
134
  function formatSkillActivationBlock(skillNames: string[]): string {
135
135
  const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
136
136
  if (safe.length === 0) return "";
137
- // Use explicit parameter syntax so LLMs pass { skill: "..." } instead of { name: "..." }.
138
- // The function-call-like syntax `Skill('name')` led LLMs to infer a positional
139
- // parameter name, causing tool validation failures — see #2224.
140
- const calls = safe.map(name => `Call Skill({ skill: '${name}' })`).join('. ');
141
- return `<skill_activation>${calls}.</skill_activation>`;
137
+ const reads = safe.map(name => `Read the installed '${name}' skill file from <available_skills>`).join(". ");
138
+ return `<skill_activation>${reads}.</skill_activation>`;
142
139
  }
143
140
 
144
141
  /**
@@ -157,7 +154,7 @@ function formatSkillRecommendationsBlock(unitType: string | undefined, skillName
157
154
  if (!unitType) return "";
158
155
  const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
159
156
  if (safe.length === 0) return "";
160
- return `<skill_recommendations unit="${unitType}">For this unit type, also consider invoking: ${safe.join(", ")}. Use Skill({ skill: 'name' }) when relevant — these are recommendations, not requirements.</skill_recommendations>`;
157
+ return `<skill_recommendations unit="${unitType}">For this unit type, also consider reading these installed skill files from <available_skills>: ${safe.join(", ")}. These are recommendations, not requirements.</skill_recommendations>`;
161
158
  }
162
159
 
163
160
  export function buildSkillActivationBlock(params: {
@@ -60,6 +60,7 @@ import {
60
60
  getAllMilestones,
61
61
  getMilestone,
62
62
  getMilestoneSlices,
63
+ getSlicesByMilestoneIds,
63
64
  getSliceTasks,
64
65
  getReplanHistory,
65
66
  getSlice,
@@ -477,13 +478,18 @@ async function buildRegistryAndFindActive(
477
478
  let activeMilestoneHasDraft = false;
478
479
  let firstDeferredQueuedShell: { id: string; title: string; deps: string[]; hasDraftContext: boolean } | null = null;
479
480
 
481
+ const activeMilestoneIds = milestones
482
+ .filter((m) => !parkedMilestoneIds.has(m.id))
483
+ .map((m) => m.id);
484
+ const slicesByMilestone = getSlicesByMilestoneIds(activeMilestoneIds);
485
+
480
486
  for (const m of milestones) {
481
487
  if (parkedMilestoneIds.has(m.id)) {
482
488
  registry.push({ id: m.id, title: stripMilestonePrefix(m.title) || m.id, status: 'parked' });
483
489
  continue;
484
490
  }
485
491
 
486
- const slices = getMilestoneSlices(m.id);
492
+ const slices = slicesByMilestone.get(m.id) ?? [];
487
493
 
488
494
  // DB-authoritative completeness (#4179): only trust completeMilestoneIds,
489
495
  // which is itself derived from DB status. SUMMARY-file presence alone must
@@ -2,7 +2,7 @@ import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
3
 
4
4
  import { _buildAbortedPauseContext, isUserInitiatedAbortMessage } from "../bootstrap/agent-end-recovery.js";
5
- import { _buildCancelledUnitStopReason, _isPauseOriginCancelledResult } from "../auto/phases.js";
5
+ import { _buildCancelledUnitStopReason, _isPauseOriginCancelledResult } from "../auto/phase-helpers.js";
6
6
 
7
7
  test("aborted agent_end maps errorMessage into structured aborted pause context", () => {
8
8
  const withMessage = _buildAbortedPauseContext({ errorMessage: "provider aborted request" });
@@ -1,7 +1,7 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
3
 
4
- import { runPreDispatch } from "../auto/phases.ts";
4
+ import { runPreDispatch } from "../auto/pre-dispatch.ts";
5
5
 
6
6
  test("blocked remediation warning uses /gsd dispatch reassess and hides internal tool name", async () => {
7
7
  const notifications: Array<{ message: string; level?: string }> = [];
@@ -3,6 +3,7 @@
3
3
 
4
4
  import test, { mock } from "node:test";
5
5
  import assert from "node:assert/strict";
6
+ import { execSync } from "node:child_process";
6
7
  import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
7
8
  import { tmpdir } from "node:os";
8
9
  import { join } from "node:path";
@@ -24,7 +25,9 @@ import { runUnit, shouldDeferUnitFailsafeTimeout } from "../auto/run-unit.js";
24
25
  import { scheduleAutoWakeup, _resetAutoWakeupsForTest } from "../auto/schedule-wakeup.js";
25
26
  import { writeUnitRuntimeRecord, readUnitRuntimeRecord } from "../unit-runtime.js";
26
27
  import { autoLoop as rawAutoLoop } from "../auto/loop.js";
27
- import { runPreDispatch, runDispatch, runUnitPhase } from "../auto/phases.js";
28
+ import { runPreDispatch } from "../auto/pre-dispatch.js";
29
+ import { runDispatch } from "../auto/dispatch.js";
30
+ import { runUnitPhase, resetSessionTimeoutState } from "../auto/unit-phase.js";
28
31
  import { detectStuck } from "../auto/detect-stuck.js";
29
32
  import type { UnitResult, AgentEndEvent, LoopState } from "../auto/types.js";
30
33
  import type { LoopDeps } from "../auto/loop-deps.js";
@@ -531,7 +534,7 @@ test("runUnit failsafe defers cancellation while timeout recovery is making fres
531
534
  const ctx = makeMockCtx();
532
535
  const pi = makeMockPi();
533
536
  const s = makeMockSession();
534
- s.basePath = mkdtempSync(join(tmpdir(), "gsd-rununit-recovery-"));
537
+ s.basePath = makeLoopTestBase("gsd-rununit-recovery-");
535
538
  s.currentUnit = { type: "task", id: "T01", startedAt: 1234 };
536
539
 
537
540
  const resultPromise = runUnit(ctx, pi, s, "task", "T01", "prompt");
@@ -1366,12 +1369,19 @@ function makeMockDeps(
1366
1369
  * runUnit mock (dispatch counters, milestone state, etc.).
1367
1370
  */
1368
1371
  function makeLoopSession(overrides?: Partial<Record<string, unknown>>) {
1372
+ const basePath = mkdtempSync(join(tmpdir(), "gsd-auto-loop-"));
1373
+ // Plan 001 enforces worktree safety for all isolation modes. Loop-mechanics
1374
+ // tests run with getIsolationMode: () => "none", so the project root itself
1375
+ // must be a valid git working tree for source-writing Units to dispatch.
1376
+ execSync("git init --initial-branch=main", { cwd: basePath, stdio: "ignore" });
1377
+ execSync("git config user.email test@test.com", { cwd: basePath, stdio: "ignore" });
1378
+ execSync("git config user.name Test", { cwd: basePath, stdio: "ignore" });
1369
1379
  return {
1370
1380
  active: true,
1371
1381
  verbose: false,
1372
1382
  stepMode: false,
1373
1383
  paused: false,
1374
- basePath: mkdtempSync(join(tmpdir(), "gsd-auto-loop-")),
1384
+ basePath,
1375
1385
  originalBasePath: "",
1376
1386
  currentMilestoneId: "M001",
1377
1387
  currentUnit: null,
@@ -1419,6 +1429,15 @@ function makeLoopSession(overrides?: Partial<Record<string, unknown>>) {
1419
1429
  } as any;
1420
1430
  }
1421
1431
 
1432
+ /** Create a temp project root suitable for loop-mechanics tests. */
1433
+ function makeLoopTestBase(prefix: string): string {
1434
+ const base = mkdtempSync(join(tmpdir(), prefix));
1435
+ execSync("git init --initial-branch=main", { cwd: base, stdio: "ignore" });
1436
+ execSync("git config user.email test@test.com", { cwd: base, stdio: "ignore" });
1437
+ execSync("git config user.name Test", { cwd: base, stdio: "ignore" });
1438
+ return base;
1439
+ }
1440
+
1422
1441
  test("autoLoop exits when s.active is set to false", async (t) => {
1423
1442
  _resetPendingResolve();
1424
1443
 
@@ -1506,7 +1525,7 @@ test("autoLoop preserves stuck recovery counter when dispatch recovery continues
1506
1525
 
1507
1526
  const ctx = makeMockCtx();
1508
1527
  const pi = makeMockPi();
1509
- const basePath = realpathSync(mkdtempSync(join(tmpdir(), "gsd-stuck-counter-reset-")));
1528
+ const basePath = realpathSync(makeLoopTestBase("gsd-stuck-counter-reset-"));
1510
1529
  mkdirSync(join(basePath, ".gsd"), { recursive: true });
1511
1530
  mkdirSync(join(basePath, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
1512
1531
  writeFileSync(
@@ -1581,7 +1600,7 @@ test("autoLoop skips provider dispatch when execute-task is already complete in
1581
1600
  ctx.ui.setStatus = () => {};
1582
1601
  ctx.ui.setWidget = () => {};
1583
1602
  const pi = makeMockPi();
1584
- const basePath = realpathSync(mkdtempSync(join(tmpdir(), "gsd-already-complete-dispatch-")));
1603
+ const basePath = realpathSync(makeLoopTestBase("gsd-already-complete-dispatch-"));
1585
1604
  mkdirSync(join(basePath, ".gsd"), { recursive: true });
1586
1605
 
1587
1606
  try {
@@ -3992,7 +4011,7 @@ test("resolveAgentEndCancelled with errorContext passes it through to resolved p
3992
4011
  test("runUnitPhase pauses transient aborted cancellations instead of hard-stopping", async (t) => {
3993
4012
  _resetPendingResolve();
3994
4013
 
3995
- const basePath = mkdtempSync(join(tmpdir(), "gsd-aborted-cancel-"));
4014
+ const basePath = makeLoopTestBase("gsd-aborted-cancel-");
3996
4015
  t.after(() => {
3997
4016
  rmSync(basePath, { recursive: true, force: true });
3998
4017
  });
@@ -4064,10 +4083,157 @@ test("runUnitPhase pauses transient aborted cancellations instead of hard-stoppi
4064
4083
  assert.equal(deps.callLog.includes("stopAuto"), false);
4065
4084
  });
4066
4085
 
4086
+ test("resetSessionTimeoutState gives a new auto session a fresh session-creation timeout budget", async (t) => {
4087
+ _resetPendingResolve();
4088
+
4089
+ // runUnitPhase schedules an auto-resume setTimeout on transient session
4090
+ // timeouts. Capture and clear those timers so the test process can exit
4091
+ // promptly while still exercising the real production path.
4092
+ const originalSetTimeout = globalThis.setTimeout;
4093
+ const timerHandles: ReturnType<typeof originalSetTimeout>[] = [];
4094
+ globalThis.setTimeout = ((callback: any, delay?: number, ...args: any[]) => {
4095
+ const handle = originalSetTimeout(callback, delay ?? 0, ...args);
4096
+ timerHandles.push(handle);
4097
+ return handle;
4098
+ }) as any;
4099
+
4100
+ const basePath = makeLoopTestBase("gsd-session-timeout-reset-");
4101
+ execSync("git init", { cwd: basePath });
4102
+ execSync('git -c user.email=test@test.com -c user.name=Test commit --allow-empty -m init', { cwd: basePath });
4103
+
4104
+ t.after(() => {
4105
+ for (const handle of timerHandles) clearTimeout(handle);
4106
+ globalThis.setTimeout = originalSetTimeout;
4107
+ rmSync(basePath, { recursive: true, force: true });
4108
+ });
4109
+
4110
+ const ctx = {
4111
+ ...makeMockCtx(),
4112
+ ui: {
4113
+ notify: () => {},
4114
+ setStatus: () => {},
4115
+ setWorkingMessage: () => {},
4116
+ },
4117
+ sessionManager: {
4118
+ getEntries: () => [],
4119
+ },
4120
+ modelRegistry: {
4121
+ getProviderAuthMode: () => undefined,
4122
+ isProviderRequestReady: () => true,
4123
+ },
4124
+ } as any;
4125
+ const notifications: Array<{ message: string; level?: string }> = [];
4126
+ ctx.ui.notify = (message: string, level?: string) => {
4127
+ notifications.push({ message, level });
4128
+ };
4129
+ const pi = makeMockPi();
4130
+ const s = makeLoopSession({
4131
+ basePath,
4132
+ canonicalProjectRoot: basePath,
4133
+ originalBasePath: basePath,
4134
+ });
4135
+ const deps = makeMockDeps();
4136
+
4137
+ async function runTimeoutUnit(iteration: number): Promise<string | undefined> {
4138
+ notifications.length = 0;
4139
+ const callsBefore = pi.calls.length;
4140
+ let seq = 0;
4141
+ const phasePromise = runUnitPhase(
4142
+ { ctx, pi, s, deps, prefs: undefined, iteration, flowId: `flow-${iteration}`, nextSeq: () => ++seq },
4143
+ {
4144
+ unitType: "plan-slice",
4145
+ unitId: "M001/S01",
4146
+ prompt: "plan the slice",
4147
+ finalPrompt: "plan the slice",
4148
+ pauseAfterUatDispatch: false,
4149
+ state: {
4150
+ phase: "planning",
4151
+ activeMilestone: { id: "M001", title: "Milestone" },
4152
+ activeSlice: { id: "S01", title: "Slice" },
4153
+ activeTask: null,
4154
+ registry: [{ id: "M001", title: "Milestone", status: "active" }],
4155
+ recentDecisions: [],
4156
+ blockers: [],
4157
+ nextAction: "",
4158
+ progress: { milestones: { done: 0, total: 1 } },
4159
+ requirements: { active: 0, validated: 0, deferred: 0, outOfScope: 0, blocked: 0, total: 0 },
4160
+ } as any,
4161
+ mid: "M001",
4162
+ midTitle: "Milestone",
4163
+ isRetry: false,
4164
+ previousTier: undefined,
4165
+ },
4166
+ makeLoopState(),
4167
+ );
4168
+
4169
+ // Wait until runUnit has dispatched the prompt, then resolve the unit
4170
+ // as a session-creation timeout. This avoids the 120s real timeout and
4171
+ // the mock-timer interaction that runUnitPhase's pre-flight setup makes
4172
+ // fragile.
4173
+ await new Promise<void>((resolve) => {
4174
+ const check = () => {
4175
+ if (pi.calls.length > callsBefore) return resolve();
4176
+ setTimeout(check, 5);
4177
+ };
4178
+ check();
4179
+ });
4180
+ resolveAgentEndCancelled({
4181
+ message: "Session creation timed out",
4182
+ category: "timeout",
4183
+ isTransient: true,
4184
+ });
4185
+
4186
+ const result = await phasePromise;
4187
+ return (result as any).reason;
4188
+ }
4189
+
4190
+ // Start from a known state in case a previous test left the counter raised.
4191
+ resetSessionTimeoutState();
4192
+
4193
+ // Exhaust the per-process timeout budget in the first "session".
4194
+ for (let i = 1; i <= 4; i++) {
4195
+ const reason = await runTimeoutUnit(i);
4196
+ assert.equal(reason, "session-timeout");
4197
+ }
4198
+ const lastBudgetNotification = notifications.find((n) =>
4199
+ n.message.includes("Session creation timed out")
4200
+ );
4201
+ assert.ok(lastBudgetNotification, "expected a session-creation timeout notification");
4202
+ assert.match(
4203
+ lastBudgetNotification.message,
4204
+ /Pausing for manual review/,
4205
+ "fourth consecutive timeout should exhaust the auto-resume budget",
4206
+ );
4207
+
4208
+ // Simulate a new auto-mode session starting. autoLoop() must reset the
4209
+ // module-level counter so the next timeout is treated as the first in the
4210
+ // new session rather than inheriting the exhausted budget.
4211
+ const freshSession = makeLoopSession({
4212
+ basePath,
4213
+ canonicalProjectRoot: basePath,
4214
+ originalBasePath: basePath,
4215
+ active: false,
4216
+ });
4217
+ freshSession.orchestration = createLoopTestOrchestration(ctx, pi, freshSession, deps);
4218
+ await rawAutoLoop(ctx, pi, freshSession, deps);
4219
+
4220
+ const reasonAfterReset = await runTimeoutUnit(5);
4221
+ assert.equal(reasonAfterReset, "session-timeout");
4222
+ const notificationAfterReset = notifications.find((n) =>
4223
+ n.message.includes("Auto-resuming")
4224
+ );
4225
+ assert.ok(notificationAfterReset, "expected an auto-resume notification after reset");
4226
+ assert.match(
4227
+ notificationAfterReset.message,
4228
+ /Auto-resuming/,
4229
+ "after autoLoop entry the timeout budget should be fresh so the first timeout auto-resumes",
4230
+ );
4231
+ });
4232
+
4067
4233
  test("runUnitPhase treats setup-race cancellations as pause-induced when session is already paused", async (t) => {
4068
4234
  _resetPendingResolve();
4069
4235
 
4070
- const basePath = mkdtempSync(join(tmpdir(), "gsd-paused-setup-race-"));
4236
+ const basePath = makeLoopTestBase("gsd-paused-setup-race-");
4071
4237
  t.after(() => {
4072
4238
  rmSync(basePath, { recursive: true, force: true });
4073
4239
  });
@@ -4142,7 +4308,7 @@ test("runUnitPhase treats setup-race cancellations as pause-induced when session
4142
4308
  test("runUnitPhase remembers aborted milestone closeout for same-unit resume", async (t) => {
4143
4309
  _resetPendingResolve();
4144
4310
 
4145
- const basePath = mkdtempSync(join(tmpdir(), "gsd-aborted-closeout-"));
4311
+ const basePath = makeLoopTestBase("gsd-aborted-closeout-");
4146
4312
  t.after(() => {
4147
4313
  rmSync(basePath, { recursive: true, force: true });
4148
4314
  });
@@ -4222,7 +4388,7 @@ test("runUnitPhase remembers aborted milestone closeout for same-unit resume", a
4222
4388
  test("runUnitPhase schedules default auto-resume for transient provider cancellations", async (t) => {
4223
4389
  _resetPendingResolve();
4224
4390
 
4225
- const basePath = mkdtempSync(join(tmpdir(), "gsd-provider-resume-"));
4391
+ const basePath = makeLoopTestBase("gsd-provider-resume-");
4226
4392
  t.after(() => {
4227
4393
  _resetPendingResolve();
4228
4394
  rmSync(basePath, { recursive: true, force: true });
@@ -4319,7 +4485,7 @@ test("runUnitPhase schedules default auto-resume for transient provider cancella
4319
4485
  test("runUnitPhase pauses ghost completions before closeout and finalize side effects", async (t) => {
4320
4486
  _resetPendingResolve();
4321
4487
 
4322
- const basePath = mkdtempSync(join(tmpdir(), "gsd-ghost-completion-"));
4488
+ const basePath = makeLoopTestBase("gsd-ghost-completion-");
4323
4489
  t.after(() => {
4324
4490
  _resetPendingResolve();
4325
4491
  rmSync(basePath, { recursive: true, force: true });
@@ -4421,7 +4587,7 @@ test("runUnitPhase pauses ghost completions before closeout and finalize side ef
4421
4587
  test("runUnitPhase records failed routing outcome when expected artifact is missing", async (t) => {
4422
4588
  _resetPendingResolve();
4423
4589
 
4424
- const basePath = mkdtempSync(join(tmpdir(), "gsd-routing-artifact-missing-"));
4590
+ const basePath = makeLoopTestBase("gsd-routing-artifact-missing-");
4425
4591
  t.after(() => {
4426
4592
  _resetPendingResolve();
4427
4593
  rmSync(basePath, { recursive: true, force: true });
@@ -4504,7 +4670,7 @@ test("runUnitPhase records failed routing outcome when expected artifact is miss
4504
4670
  test("runUnitPhase execute-task retry prompt instructs gsd_task_complete instead of manual summary writes", async (t) => {
4505
4671
  _resetPendingResolve();
4506
4672
 
4507
- const basePath = mkdtempSync(join(tmpdir(), "gsd-execute-task-retry-prompt-"));
4673
+ const basePath = makeLoopTestBase("gsd-execute-task-retry-prompt-");
4508
4674
  t.after(() => {
4509
4675
  _resetPendingResolve();
4510
4676
  rmSync(basePath, { recursive: true, force: true });
@@ -4585,7 +4751,7 @@ test("runUnitPhase execute-task retry prompt instructs gsd_task_complete instead
4585
4751
  test("runUnitPhase non-execute-task retry prompt keeps generic required-file guidance", async (t) => {
4586
4752
  _resetPendingResolve();
4587
4753
 
4588
- const basePath = mkdtempSync(join(tmpdir(), "gsd-non-execute-retry-prompt-"));
4754
+ const basePath = makeLoopTestBase("gsd-non-execute-retry-prompt-");
4589
4755
  t.after(() => {
4590
4756
  _resetPendingResolve();
4591
4757
  rmSync(basePath, { recursive: true, force: true });
@@ -4933,7 +5099,7 @@ test("autoLoop rejects execute-task with 0 tool calls as hallucinated (#1833)",
4933
5099
  test("runUnitPhase retries 0-tool units with ordinary network-related assistant text", async (t) => {
4934
5100
  _resetPendingResolve();
4935
5101
 
4936
- const basePath = mkdtempSync(join(tmpdir(), "gsd-zero-tool-network-text-"));
5102
+ const basePath = makeLoopTestBase("gsd-zero-tool-network-text-");
4937
5103
  t.after(() => {
4938
5104
  rmSync(basePath, { recursive: true, force: true });
4939
5105
  });
@@ -5028,7 +5194,7 @@ test("runUnitPhase retries 0-tool units with ordinary network-related assistant
5028
5194
  test("runUnitPhase pauses auto-mode when zero-tool-call retry is exhausted", async (t) => {
5029
5195
  _resetPendingResolve();
5030
5196
 
5031
- const basePath = mkdtempSync(join(tmpdir(), "gsd-zero-tool-exhausted-"));
5197
+ const basePath = makeLoopTestBase("gsd-zero-tool-exhausted-");
5032
5198
  t.after(() => {
5033
5199
  rmSync(basePath, { recursive: true, force: true });
5034
5200
  });
@@ -5313,7 +5479,7 @@ test("autoLoop rejects complete-slice with 0 tool calls as context-exhausted (#2
5313
5479
  test("autoLoop pauses on zero-tool-call rate-limit assistant messages instead of immediate retry", async (t) => {
5314
5480
  _resetPendingResolve();
5315
5481
 
5316
- const basePath = mkdtempSync(join(tmpdir(), "gsd-zero-tool-rate-limit-"));
5482
+ const basePath = makeLoopTestBase("gsd-zero-tool-rate-limit-");
5317
5483
  t.after(() => {
5318
5484
  _resetPendingResolve();
5319
5485
  rmSync(basePath, { recursive: true, force: true });
@@ -5529,6 +5695,15 @@ test("dispatch Worktree Safety honors degraded branch fallback instead of demand
5529
5695
  // branch in the project root. The safety gate must validate against that
5530
5696
  // effective branch mode, not the configured worktree mode.
5531
5697
  const projectRoot = mkdtempSync(join(tmpdir(), "gsd-wt-safety-degraded-"));
5698
+ execSync("git init --initial-branch=main", { cwd: projectRoot, stdio: "ignore" });
5699
+ execSync("git config user.email test@test.com", { cwd: projectRoot, stdio: "ignore" });
5700
+ execSync("git config user.name Test", { cwd: projectRoot, stdio: "ignore" });
5701
+ // The lifecycle fallback checks out the milestone branch in the project
5702
+ // root, so the safety gate's branch verification expects that branch here
5703
+ // too. expectedBranch comes from deps.autoWorktreeBranch (mocked to
5704
+ // "auto/M001"), so the fixture repo must be on that same branch.
5705
+ execSync("git commit --allow-empty -m init", { cwd: projectRoot, stdio: "ignore" });
5706
+ execSync("git checkout -b auto/M001", { cwd: projectRoot, stdio: "ignore" });
5532
5707
  t.after(() => rmSync(projectRoot, { recursive: true, force: true }));
5533
5708
 
5534
5709
  const s = makeLoopSession({
@@ -5591,6 +5766,15 @@ test("dispatch Worktree Safety honors stranded branch recovery instead of demand
5591
5766
  // NOT degraded — the adoption is intentional. The safety gate must validate
5592
5767
  // against the effective branch mode, not the configured worktree mode.
5593
5768
  const projectRoot = mkdtempSync(join(tmpdir(), "gsd-wt-safety-stranded-"));
5769
+ execSync("git init --initial-branch=main", { cwd: projectRoot, stdio: "ignore" });
5770
+ execSync("git config user.email test@test.com", { cwd: projectRoot, stdio: "ignore" });
5771
+ execSync("git config user.name Test", { cwd: projectRoot, stdio: "ignore" });
5772
+ // Stranded recovery adopts the milestone branch in the project root, so the
5773
+ // safety gate's branch verification expects that branch here too.
5774
+ // expectedBranch comes from deps.autoWorktreeBranch (mocked to "auto/M001"),
5775
+ // so the fixture repo must be on that same branch.
5776
+ execSync("git commit --allow-empty -m init", { cwd: projectRoot, stdio: "ignore" });
5777
+ execSync("git checkout -b auto/M001", { cwd: projectRoot, stdio: "ignore" });
5594
5778
  t.after(() => rmSync(projectRoot, { recursive: true, force: true }));
5595
5779
 
5596
5780
  const s = makeLoopSession({
@@ -5648,7 +5832,7 @@ test("runDispatch runs stuck detection while artifact verification retry is pend
5648
5832
  const notifications: string[] = [];
5649
5833
  ctx.ui.notify = (msg: string) => { notifications.push(msg); };
5650
5834
 
5651
- const basePath = mkdtempSync(join(tmpdir(), "gsd-5719-retry-stuck-"));
5835
+ const basePath = makeLoopTestBase("gsd-5719-retry-stuck-");
5652
5836
  t.after(() => rmSync(basePath, { recursive: true, force: true }));
5653
5837
 
5654
5838
  const s = makeLoopSession({
@@ -5716,7 +5900,7 @@ test("runDispatch falls back to main when dispatch guard cannot read main branch
5716
5900
 
5717
5901
  const ctx = makeMockCtx();
5718
5902
  const pi = makeMockPi();
5719
- const basePath = mkdtempSync(join(tmpdir(), "gsd-5530-main-branch-fallback-"));
5903
+ const basePath = makeLoopTestBase("gsd-5530-main-branch-fallback-");
5720
5904
  t.after(() => rmSync(basePath, { recursive: true, force: true }));
5721
5905
 
5722
5906
  let guardBranch: string | null = null;
@@ -6243,7 +6427,7 @@ test("pre-dispatch replace resolves final unit before dispatch health and stuck
6243
6427
  );
6244
6428
  });
6245
6429
 
6246
- test("autoLoop warns but proceeds for greenfield project (no project files) (#1833)", async () => {
6430
+ test("autoLoop warns but proceeds for greenfield project (no project files) (#1833)", async (t) => {
6247
6431
  _resetPendingResolve();
6248
6432
 
6249
6433
  const ctx = makeMockCtx();
@@ -6252,7 +6436,9 @@ test("autoLoop warns but proceeds for greenfield project (no project files) (#18
6252
6436
  const pi = makeMockPi();
6253
6437
 
6254
6438
  const notifications: string[] = [];
6255
- const s = makeLoopSession({ basePath: "/tmp/empty-worktree" });
6439
+ const basePath = makeLoopTestBase("gsd-greenfield-");
6440
+ t.after(() => rmSync(basePath, { recursive: true, force: true }));
6441
+ const s = makeLoopSession({ basePath });
6256
6442
 
6257
6443
  ctx.ui.notify = (msg: string) => {
6258
6444
  notifications.push(msg);
@@ -6275,8 +6461,6 @@ test("autoLoop warns but proceeds for greenfield project (no project files) (#18
6275
6461
  blockers: [],
6276
6462
  } as any;
6277
6463
  },
6278
- // Has .git but no package.json or src/
6279
- existsSync: (p: string) => p.endsWith(".git"),
6280
6464
  });
6281
6465
 
6282
6466
  await autoLoop(ctx, pi, s, deps);
@@ -872,7 +872,12 @@ test("selectAndApplyModel clamps explicit no-model thinking via ctx.model when r
872
872
 
873
873
  await selectAndApplyModel(
874
874
  {
875
- modelRegistry: { getAvailable: () => [] }, // registry lookup fails
875
+ // Empty registry results force the clamp source to fall back to ctx.model.
876
+ modelRegistry: {
877
+ getAvailable: () => [],
878
+ getAll: () => [],
879
+ isProviderRequestReady: () => true,
880
+ },
876
881
  sessionManager: { getSessionId: () => "test-session" },
877
882
  ui: { notify: () => {} },
878
883
  model: ctxModel,