@opengsd/gsd-pi 1.2.0-dev.84c56d87 → 1.2.0-dev.8e6112e9

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 (631) 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/headless-events.js +7 -5
  5. package/dist/loader.js +6 -4
  6. package/dist/mcp-server.js +2 -1
  7. package/dist/register-agent-bundles.d.ts +11 -2
  8. package/dist/register-agent-bundles.js +18 -4
  9. package/dist/resource-loader.d.ts +10 -5
  10. package/dist/resource-loader.js +121 -6
  11. package/dist/resources/.managed-resources-content-hash +1 -1
  12. package/dist/resources/GSD-WORKFLOW.md +5 -4
  13. package/dist/resources/extensions/ask-user-questions.js +3 -2
  14. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  15. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  16. package/dist/resources/extensions/async-jobs/index.js +65 -0
  17. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  18. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  19. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  20. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  21. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  22. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  23. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
  24. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
  25. package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
  26. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  27. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  28. package/dist/resources/extensions/gsd/auto/dispatch-history.js +120 -0
  29. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  30. package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
  31. package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
  32. package/dist/resources/extensions/gsd/auto/loop.js +7 -1
  33. package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
  34. package/dist/resources/extensions/gsd/auto/orchestrator.js +174 -69
  35. package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
  36. package/dist/resources/extensions/gsd/auto/phases.js +17 -2329
  37. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
  38. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  39. package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
  40. package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
  41. package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
  42. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
  43. package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
  44. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
  45. package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
  46. package/dist/resources/extensions/gsd/auto-prompts.js +78 -19
  47. package/dist/resources/extensions/gsd/auto-start.js +35 -15
  48. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  49. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
  50. package/dist/resources/extensions/gsd/auto-verification.js +23 -30
  51. package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
  52. package/dist/resources/extensions/gsd/auto.js +52 -2
  53. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  54. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
  55. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +60 -13
  56. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  57. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +145 -50
  58. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
  59. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  60. package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
  61. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  62. package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
  63. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
  64. package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
  65. package/dist/resources/extensions/gsd/consent-question.js +353 -0
  66. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  67. package/dist/resources/extensions/gsd/constants.js +0 -2
  68. package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
  69. package/dist/resources/extensions/gsd/db/engine.js +5 -3
  70. package/dist/resources/extensions/gsd/db/queries.js +56 -0
  71. package/dist/resources/extensions/gsd/db-writer.js +8 -17
  72. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  73. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  74. package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
  75. package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
  76. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  77. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  78. package/dist/resources/extensions/gsd/files.js +33 -19
  79. package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
  80. package/dist/resources/extensions/gsd/gsd-db.js +11 -8
  81. package/dist/resources/extensions/gsd/guidance.js +60 -0
  82. package/dist/resources/extensions/gsd/guided-flow.js +93 -4
  83. package/dist/resources/extensions/gsd/health-widget.js +87 -28
  84. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  85. package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
  86. package/dist/resources/extensions/gsd/memory-relations.js +1 -1
  87. package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
  88. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  89. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  90. package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
  91. package/dist/resources/extensions/gsd/notifications.js +12 -7
  92. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  93. package/dist/resources/extensions/gsd/preferences-models.js +2 -2
  94. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  95. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  96. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
  97. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  98. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  99. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  100. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  101. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  102. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  103. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  104. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  105. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  106. package/dist/resources/extensions/gsd/prompts/run-uat.md +9 -5
  107. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  108. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  109. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  110. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  111. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  112. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  113. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  114. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  115. package/dist/resources/extensions/gsd/skill-activation.js +3 -6
  116. package/dist/resources/extensions/gsd/state.js +11 -2
  117. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  118. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  119. package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
  120. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  121. package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
  122. package/dist/resources/extensions/gsd/tools/complete-task.js +65 -2
  123. package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -0
  124. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
  125. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  126. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  127. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  128. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
  129. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  130. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  131. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
  132. package/dist/resources/extensions/gsd/uat-policy.js +40 -15
  133. package/dist/resources/extensions/gsd/unit-context-composer.js +65 -0
  134. package/dist/resources/extensions/gsd/unit-registry.js +34 -4
  135. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  136. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  137. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  138. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  139. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  140. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
  141. package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
  142. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  143. package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
  144. package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
  145. package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
  146. package/dist/resources/extensions/gsd/worktree.js +8 -1
  147. package/dist/resources/extensions/mcp-client/manager.js +6 -1
  148. package/dist/resources/extensions/shared/gsd-browser-cli.js +45 -3
  149. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  150. package/dist/resources/shared/package-manager-detection.js +1 -1
  151. package/dist/resources/shared/package.json +3 -0
  152. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  153. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  154. package/dist/runtime-checks.d.ts +10 -0
  155. package/dist/runtime-checks.js +27 -0
  156. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  157. package/dist/update-check.d.ts +2 -0
  158. package/dist/update-check.js +24 -1
  159. package/dist/update-cmd.js +20 -3
  160. package/dist/web/standalone/.next/BUILD_ID +1 -1
  161. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  162. package/dist/web/standalone/.next/build-manifest.json +3 -3
  163. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  164. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  165. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  166. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  167. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  168. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  169. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  170. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  171. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  172. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  173. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  174. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  176. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  177. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  178. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  179. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  180. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  181. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/index.html +1 -1
  184. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  185. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  186. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  187. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  188. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  189. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  190. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  191. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  192. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  195. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  196. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  197. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  198. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  199. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  200. package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
  201. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
  202. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  203. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  204. package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
  205. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
  206. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
  207. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
  208. package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
  209. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  210. package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
  211. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  212. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
  213. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  214. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  215. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  216. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
  217. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
  218. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  219. package/package.json +3 -3
  220. package/packages/cloud-mcp-gateway/package.json +2 -2
  221. package/packages/contracts/dist/rpc.d.ts +1 -0
  222. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  223. package/packages/contracts/dist/rpc.js.map +1 -1
  224. package/packages/contracts/package.json +1 -1
  225. package/packages/daemon/package.json +4 -4
  226. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  227. package/packages/gsd-agent-core/dist/sdk.js +6 -4
  228. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  229. package/packages/gsd-agent-core/package.json +5 -5
  230. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  231. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  232. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  233. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  234. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +13 -0
  235. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  236. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +55 -6
  237. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  238. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +2 -0
  239. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  240. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
  241. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  242. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  243. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  244. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  245. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  246. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  247. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  248. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  249. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  250. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  251. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
  252. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  253. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +12 -0
  254. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  255. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  256. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  257. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  258. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  259. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
  260. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  261. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  262. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  263. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  264. package/packages/gsd-agent-modes/package.json +7 -7
  265. package/packages/mcp-server/README.md +12 -3
  266. package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
  267. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
  268. package/packages/mcp-server/dist/cli-runner.js +137 -0
  269. package/packages/mcp-server/dist/cli-runner.js.map +1 -0
  270. package/packages/mcp-server/dist/cli.js +2 -53
  271. package/packages/mcp-server/dist/cli.js.map +1 -1
  272. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  273. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  274. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  275. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  276. package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
  277. package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
  278. package/packages/mcp-server/dist/pid-registry.js +452 -0
  279. package/packages/mcp-server/dist/pid-registry.js.map +1 -0
  280. package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
  281. package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
  282. package/packages/mcp-server/dist/probe-mode.js +10 -0
  283. package/packages/mcp-server/dist/probe-mode.js.map +1 -0
  284. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  285. package/packages/mcp-server/dist/server.js +4 -0
  286. package/packages/mcp-server/dist/server.js.map +1 -1
  287. package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
  288. package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
  289. package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
  290. package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
  291. package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
  292. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  293. package/packages/mcp-server/dist/workflow-tools.js +161 -81
  294. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  295. package/packages/mcp-server/package.json +5 -4
  296. package/packages/native/package.json +1 -1
  297. package/packages/pi-agent-core/dist/agent-loop.js +43 -2
  298. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  299. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  300. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  301. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  302. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  303. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  304. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  305. package/packages/pi-agent-core/dist/index.js +3 -0
  306. package/packages/pi-agent-core/dist/index.js.map +1 -1
  307. package/packages/pi-agent-core/package.json +1 -1
  308. package/packages/pi-ai/README.md +1 -0
  309. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  310. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  311. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  312. package/packages/pi-ai/dist/index.d.ts +2 -0
  313. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  314. package/packages/pi-ai/dist/index.js +2 -0
  315. package/packages/pi-ai/dist/index.js.map +1 -1
  316. package/packages/pi-ai/dist/models.generated.d.ts +419 -221
  317. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  318. package/packages/pi-ai/dist/models.generated.js +460 -261
  319. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  320. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  321. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  322. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  323. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  324. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  325. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  326. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  327. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  328. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  329. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  330. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  331. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  332. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  333. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  334. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  335. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  336. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  337. package/packages/pi-ai/package.json +3 -2
  338. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  339. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  340. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  341. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  344. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  345. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  346. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  347. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  348. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  349. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  350. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  351. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  352. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  353. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  354. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/index.js +1 -1
  356. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  357. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  358. package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
  359. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  360. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  361. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  363. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  364. package/packages/pi-coding-agent/package.json +7 -7
  365. package/packages/pi-tui/dist/index.d.ts +1 -1
  366. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  367. package/packages/pi-tui/dist/index.js +1 -1
  368. package/packages/pi-tui/dist/index.js.map +1 -1
  369. package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
  370. package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
  371. package/packages/pi-tui/dist/terminal-image.js +54 -2
  372. package/packages/pi-tui/dist/terminal-image.js.map +1 -1
  373. package/packages/pi-tui/dist/tui.d.ts +8 -0
  374. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  375. package/packages/pi-tui/dist/tui.js +63 -18
  376. package/packages/pi-tui/dist/tui.js.map +1 -1
  377. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  378. package/packages/pi-tui/dist/utils.js +110 -36
  379. package/packages/pi-tui/dist/utils.js.map +1 -1
  380. package/packages/pi-tui/package.json +2 -2
  381. package/packages/rpc-client/package.json +2 -2
  382. package/pkg/dist/theme/theme.d.ts.map +1 -1
  383. package/pkg/dist/theme/theme.js +45 -17
  384. package/pkg/dist/theme/theme.js.map +1 -1
  385. package/pkg/package.json +1 -1
  386. package/src/resources/GSD-WORKFLOW.md +5 -4
  387. package/src/resources/extensions/ask-user-questions.ts +7 -2
  388. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  389. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  390. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  391. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  392. package/src/resources/extensions/async-jobs/index.ts +79 -0
  393. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  394. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  395. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  396. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  397. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  398. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  399. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  400. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
  401. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
  402. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
  403. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
  404. package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
  405. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  406. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  407. package/src/resources/extensions/gsd/auto/dispatch-history.ts +168 -0
  408. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  409. package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
  410. package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
  411. package/src/resources/extensions/gsd/auto/loop.ts +7 -1
  412. package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
  413. package/src/resources/extensions/gsd/auto/orchestrator.ts +193 -71
  414. package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
  415. package/src/resources/extensions/gsd/auto/phases.ts +58 -3022
  416. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
  417. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  418. package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
  419. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
  420. package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
  421. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
  422. package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
  423. package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
  424. package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
  425. package/src/resources/extensions/gsd/auto-prompts.ts +115 -35
  426. package/src/resources/extensions/gsd/auto-start.ts +36 -18
  427. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  428. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
  429. package/src/resources/extensions/gsd/auto-verification.ts +26 -28
  430. package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
  431. package/src/resources/extensions/gsd/auto.ts +64 -2
  432. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  433. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
  434. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +79 -12
  435. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  436. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +163 -55
  437. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
  438. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  439. package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
  440. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  441. package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
  442. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
  443. package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
  444. package/src/resources/extensions/gsd/consent-question.ts +431 -0
  445. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  446. package/src/resources/extensions/gsd/constants.ts +0 -3
  447. package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
  448. package/src/resources/extensions/gsd/db/engine.ts +5 -3
  449. package/src/resources/extensions/gsd/db/queries.ts +66 -0
  450. package/src/resources/extensions/gsd/db-writer.ts +11 -19
  451. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  452. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  453. package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
  454. package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
  455. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  456. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  457. package/src/resources/extensions/gsd/files.ts +33 -12
  458. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  459. package/src/resources/extensions/gsd/gsd-db.ts +13 -10
  460. package/src/resources/extensions/gsd/guidance.ts +78 -0
  461. package/src/resources/extensions/gsd/guided-flow.ts +145 -24
  462. package/src/resources/extensions/gsd/health-widget.ts +91 -27
  463. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  464. package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
  465. package/src/resources/extensions/gsd/memory-relations.ts +1 -1
  466. package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
  467. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  468. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  469. package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
  470. package/src/resources/extensions/gsd/notifications.ts +13 -6
  471. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  472. package/src/resources/extensions/gsd/preferences-models.ts +2 -1
  473. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  474. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  475. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
  476. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  477. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  478. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  479. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  480. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  481. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  482. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  483. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  484. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  485. package/src/resources/extensions/gsd/prompts/run-uat.md +9 -5
  486. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  487. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  488. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  489. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  490. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  491. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  492. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  493. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  494. package/src/resources/extensions/gsd/skill-activation.ts +3 -6
  495. package/src/resources/extensions/gsd/state.ts +12 -1
  496. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
  497. package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
  498. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
  499. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +97 -1
  500. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +273 -37
  501. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
  502. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
  503. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
  504. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  505. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
  506. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
  507. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  508. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  509. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  510. package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
  511. package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
  512. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  513. package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
  514. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +12 -11
  515. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +36 -0
  516. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  517. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  518. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +328 -0
  519. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
  520. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  521. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  522. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  523. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
  524. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
  525. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  526. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  527. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
  528. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  529. package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
  530. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
  531. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
  532. package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
  533. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +217 -0
  534. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
  535. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  536. package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
  537. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
  538. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
  539. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
  540. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
  541. package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
  542. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
  543. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  544. package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
  545. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  546. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  547. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
  548. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +143 -0
  549. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
  550. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  551. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
  552. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  553. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
  554. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  555. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
  556. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
  557. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  558. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +26 -2
  559. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
  560. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
  561. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
  562. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
  563. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  564. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +45 -2
  565. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
  566. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  567. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  568. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +88 -0
  569. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +44 -0
  570. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  571. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  572. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  573. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  574. package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
  575. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
  576. package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
  577. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  578. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
  579. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
  580. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
  581. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
  582. package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
  583. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
  584. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  585. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  586. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  587. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
  588. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  589. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  590. package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
  591. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  592. package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
  593. package/src/resources/extensions/gsd/tools/complete-task.ts +90 -2
  594. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -0
  595. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
  596. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  597. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  598. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  599. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
  600. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  601. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  602. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
  603. package/src/resources/extensions/gsd/uat-policy.ts +60 -15
  604. package/src/resources/extensions/gsd/unit-context-composer.ts +99 -0
  605. package/src/resources/extensions/gsd/unit-registry.ts +34 -4
  606. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  607. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  608. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  609. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  610. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  611. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
  612. package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
  613. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  614. package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
  615. package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
  616. package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
  617. package/src/resources/extensions/gsd/worktree.ts +7 -1
  618. package/src/resources/extensions/mcp-client/manager.ts +7 -1
  619. package/src/resources/extensions/shared/gsd-browser-cli.ts +54 -3
  620. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  621. package/src/resources/shared/package-manager-detection.ts +1 -1
  622. package/src/resources/shared/package.json +3 -0
  623. package/src/resources/skills/create-skill/SKILL.md +3 -0
  624. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  625. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  626. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  627. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  628. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  629. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  630. /package/dist/web/standalone/.next/static/{AOpDeK_gJHU8OZjRo31gQ → pZbHa49xI-knmKlphIRq0}/_buildManifest.js +0 -0
  631. /package/dist/web/standalone/.next/static/{AOpDeK_gJHU8OZjRo31gQ → pZbHa49xI-knmKlphIRq0}/_ssgManifest.js +0 -0
@@ -0,0 +1,193 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Deterministic timing tests for the exec-sandbox graceful-kill
3
+ // ladder + hard-deadline force-resolve (S04/T02).
4
+ //
5
+ // T01 extended runExecSandbox's timeout path to a graceful
6
+ // SIGTERM -> grace -> SIGKILL ladder (via killProcessTree) plus a caller-side
7
+ // force-resolve hard deadline so a non-closing ("D-state") child can never hang
8
+ // the awaiting promise. A true D-state child is non-portable, so we simulate the
9
+ // exact symptom deterministically:
10
+ // 1. A SIGTERM-cooperative child (trap 'exit 0' TERM) closes promptly on the
11
+ // first SIGTERM — proving the ladder resolves via `close` well before the
12
+ // force-resolve deadline.
13
+ // 2. A SIGTERM-ignoring (trap '' TERM) child combined with a LARGE
14
+ // kill_grace_ms (so SIGKILL never fires in-window) and a SHORT
15
+ // force_resolve_delay_ms — the only way the promise can settle is the
16
+ // hard deadline, proving the no-hang guarantee.
17
+ //
18
+ // Unlike the sync bash path (which throws on force-resolve), runExecSandbox
19
+ // always RESOLVES; force-resolve calls finalize(null, "SIGKILL") and preserves
20
+ // timed_out === true so the agent can still distinguish a graceful timeout exit
21
+ // from a forced kill.
22
+
23
+ import { test } from 'node:test';
24
+ import assert from 'node:assert/strict';
25
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
26
+ import { tmpdir } from 'node:os';
27
+ import { join } from 'node:path';
28
+
29
+ import { EXEC_DEFAULTS, runExecSandbox, type ExecSandboxOptions } from '../exec-sandbox.ts';
30
+
31
+ const isWin = process.platform === 'win32';
32
+
33
+ function freshBase(): string {
34
+ return mkdtempSync(join(tmpdir(), 'gsd-exec-gracekill-'));
35
+ }
36
+
37
+ function cleanup(dir: string): void {
38
+ rmSync(dir, { recursive: true, force: true });
39
+ }
40
+
41
+ function baseOpts(base: string, overrides: Partial<ExecSandboxOptions> = {}): ExecSandboxOptions {
42
+ return {
43
+ baseDir: base,
44
+ clamp_timeout_ms: EXEC_DEFAULTS.clampTimeoutMs,
45
+ default_timeout_ms: 10_000,
46
+ stdout_cap_bytes: 1_024,
47
+ stderr_cap_bytes: 1_024,
48
+ digest_chars: 120,
49
+ env_allowlist: EXEC_DEFAULTS.envAllowlist,
50
+ ...overrides,
51
+ };
52
+ }
53
+
54
+ // Wall-clock guard: reject if the call has not settled by `ms`. Proves no-hang
55
+ // independently of the assertions on timing/markers.
56
+ function wallClockGuard<T>(promise: Promise<T>, ms: number): Promise<T> {
57
+ return Promise.race([
58
+ promise,
59
+ new Promise<never>((_, reject) => {
60
+ const t = setTimeout(() => reject(new Error(`Call did not settle within ${ms}ms (hang)`)), ms);
61
+ if (typeof t === 'object' && 'unref' in t) t.unref();
62
+ }),
63
+ ]);
64
+ }
65
+
66
+ // Clean up a detached child (and its process group) that a large kill_grace_ms
67
+ // intentionally leaves alive past the force-resolve deadline.
68
+ function cleanupByPidFile(pidFile: string): void {
69
+ if (!existsSync(pidFile)) return;
70
+ const pid = Number.parseInt(readFileSync(pidFile, 'utf-8').trim(), 10);
71
+ if (!Number.isFinite(pid) || pid <= 0) return;
72
+ if (isWin) return; // best-effort; test is skipped on win32
73
+ try {
74
+ process.kill(-pid, 'SIGKILL');
75
+ } catch {
76
+ try {
77
+ process.kill(pid, 'SIGKILL');
78
+ } catch {
79
+ // already gone
80
+ }
81
+ }
82
+ }
83
+
84
+ test(
85
+ 'runExecSandbox: SIGTERM-cooperative child exits promptly within grace on timeout',
86
+ { skip: isWin ? 'Unix-primary graceful semantics' : false, timeout: 20_000 },
87
+ async (t) => {
88
+ const base = freshBase();
89
+ t.after(() => cleanup(base));
90
+
91
+ const KILL_GRACE_MS = 5_000;
92
+ const FORCE_RESOLVE_DELAY_MS = 8_000; // grace + hard-deadline; must NOT be reached
93
+ const TIMEOUT_MS = 300;
94
+
95
+ // Child traps SIGTERM and exits 0, then sleeps long. The first SIGTERM from
96
+ // the ladder ends it immediately -> `close` fires -> finalize via close,
97
+ // well before the force-resolve deadline.
98
+ const script = `trap 'exit 0' TERM; sleep 30`;
99
+
100
+ const result = await wallClockGuard(
101
+ runExecSandbox(
102
+ { runtime: 'bash', script, timeout_ms: TIMEOUT_MS },
103
+ baseOpts(base, {
104
+ kill_grace_ms: KILL_GRACE_MS,
105
+ force_resolve_delay_ms: FORCE_RESOLVE_DELAY_MS,
106
+ }),
107
+ ),
108
+ 15_000,
109
+ );
110
+
111
+ // timed_out is preserved even though the child exited cooperatively.
112
+ assert.equal(result.timed_out, true, 'timeout fired so timed_out must be true');
113
+ // Proves SIGTERM (close) resolved it, NOT the force-resolve deadline:
114
+ // a force-resolve would land at ~TIMEOUT_MS + FORCE_RESOLVE_DELAY_MS (~8.3s).
115
+ assert.ok(
116
+ result.duration_ms < KILL_GRACE_MS,
117
+ `expected prompt close well under grace (${KILL_GRACE_MS}ms), got ${result.duration_ms}ms`,
118
+ );
119
+ // A clean SIGTERM-trapped exit resolves via `close` with an exit code,
120
+ // not the force-resolve sentinel (exit_code null / signal SIGKILL).
121
+ assert.notEqual(
122
+ result.signal,
123
+ 'SIGKILL',
124
+ 'cooperative child must not be force-resolved as SIGKILL',
125
+ );
126
+ assert.equal(result.force_resolved, false, 'a cooperative close must not be flagged as force-resolved');
127
+ },
128
+ );
129
+
130
+ test(
131
+ 'runExecSandbox: SIGTERM-ignoring (non-closing) child force-resolves via hard deadline without hanging',
132
+ { skip: isWin ? 'Unix-primary graceful semantics; force-resolve covered on POSIX' : false, timeout: 20_000 },
133
+ async (t) => {
134
+ const base = freshBase();
135
+ const pidFile = join(base, 'child.pid');
136
+ t.after(() => {
137
+ cleanupByPidFile(pidFile);
138
+ cleanup(base);
139
+ });
140
+
141
+ // Timing seams: SIGKILL never fires in-window (grace huge), so the only way
142
+ // the promise can settle is the hard deadline -> proves the caller-side
143
+ // force-resolve.
144
+ const KILL_GRACE_MS = 30_000;
145
+ const FORCE_RESOLVE_DELAY_MS = 800;
146
+ // Generous timeout so the SIGTERM trap is reliably installed before the kill
147
+ // fires, even under heavy parallel test load. A too-tight timeout can race
148
+ // the shell's startup: the kill lands before `trap '' TERM` runs, SIGTERM
149
+ // takes its default action, the child closes on SIGTERM, and the
150
+ // force-resolve path never runs (flaky 'SIGTERM' instead of 'SIGKILL').
151
+ const TIMEOUT_MS = 1_500;
152
+
153
+ // Install the SIGTERM trap FIRST (before any other command) so the shell is
154
+ // already immune by the time the kill fires; then record the detached
155
+ // shell's PID (process-group leader) for cleanup. The shell loops forever
156
+ // holding its stdout pipe open -> `close` never fires in-window -> the
157
+ // caller's hard deadline must force-resolve.
158
+ const script = `trap '' TERM; echo $$ > '${pidFile}'; while true; do sleep 1; done`;
159
+
160
+ const start = Date.now();
161
+ const result = await wallClockGuard(
162
+ runExecSandbox(
163
+ { runtime: 'bash', script, timeout_ms: TIMEOUT_MS },
164
+ baseOpts(base, {
165
+ kill_grace_ms: KILL_GRACE_MS,
166
+ force_resolve_delay_ms: FORCE_RESOLVE_DELAY_MS,
167
+ }),
168
+ ),
169
+ 8_000,
170
+ );
171
+ const elapsed = Date.now() - start;
172
+
173
+ // (a) Did not hang and settled well before the SIGKILL grace would fire.
174
+ assert.ok(
175
+ elapsed < KILL_GRACE_MS,
176
+ `expected force-resolve before SIGKILL grace (${KILL_GRACE_MS}ms), took ${elapsed}ms`,
177
+ );
178
+ // (b) Settled in the force-resolve band: >= timeout (kill initiated) and
179
+ // roughly timeout + force_resolve_delay (generous CI slack, but kept below
180
+ // the 8000ms wallClockGuard so the upper bound is actually reachable).
181
+ assert.ok(
182
+ elapsed >= TIMEOUT_MS && elapsed <= TIMEOUT_MS + FORCE_RESOLVE_DELAY_MS + 4_000,
183
+ `expected settle near ${TIMEOUT_MS + FORCE_RESOLVE_DELAY_MS}ms, took ${elapsed}ms`,
184
+ );
185
+ // (c) Force-resolve preserves timed_out and surfaces the SIGKILL sentinel
186
+ // (exit_code null) plus the explicit force_resolved flag, so the agent can
187
+ // tell a forced kill (D-state hard deadline) from a clean SIGKILL exit.
188
+ assert.equal(result.timed_out, true, 'force-resolve must preserve timed_out');
189
+ assert.equal(result.exit_code, null, 'force-resolve exit_code must be null');
190
+ assert.equal(result.signal, 'SIGKILL', 'force-resolve must mark signal SIGKILL');
191
+ assert.equal(result.force_resolved, true, 'force-resolve must set force_resolved=true');
192
+ },
193
+ );
@@ -2,7 +2,7 @@ import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
3
 
4
4
  import { registerExecTools } from "../bootstrap/exec-tools.ts";
5
- import { executeUatExec } from "../tools/exec-tool.ts";
5
+ import { executeGsdExec, executeUatExec } from "../tools/exec-tool.ts";
6
6
  import type { ExecSandboxRequest, ExecSandboxResult } from "../exec-sandbox.ts";
7
7
 
8
8
  function makeExecResult(request: ExecSandboxRequest): ExecSandboxResult {
@@ -12,6 +12,7 @@ function makeExecResult(request: ExecSandboxRequest): ExecSandboxResult {
12
12
  exit_code: 0,
13
13
  signal: null,
14
14
  timed_out: false,
15
+ force_resolved: false,
15
16
  duration_ms: 1,
16
17
  stdout_bytes: 12,
17
18
  stderr_bytes: 0,
@@ -51,6 +52,33 @@ test("executeUatExec accepts evidence-mode aliases for intent", async () => {
51
52
  assert.equal(requests[0]?.metadata?.intent, "uat-artifact-check");
52
53
  });
53
54
 
55
+ test("gsd_exec surfaces a force-resolved (D-state) kill distinctly from a clean exit", async () => {
56
+ // A hard-deadline force-resolve sets force_resolved=true with a synthetic SIGKILL
57
+ // signal and null exit code. The tool result must carry that flag in details and
58
+ // render it as exit=timeout(force-killed) so the agent can tell it apart from a
59
+ // normally-exited or cleanly-timed-out command.
60
+ const result = await executeGsdExec(
61
+ { runtime: "bash", script: "sleep 60" },
62
+ {
63
+ baseDir: "/tmp/gsd-exec-force-resolved-test",
64
+ preferences: null,
65
+ run: async (request) => ({
66
+ ...makeExecResult(request),
67
+ exit_code: null,
68
+ signal: "SIGKILL",
69
+ timed_out: true,
70
+ force_resolved: true,
71
+ digest: "[no stdout \u2014 timed out]",
72
+ }),
73
+ },
74
+ );
75
+
76
+ assert.equal(result.isError, true, "a force-resolved kill is an error result");
77
+ assert.equal(result.details?.force_resolved, true, "details must expose force_resolved");
78
+ const text = result.content.map((c) => c.text ?? "").join("\n");
79
+ assert.match(text, /exit=timeout\(force-killed\)/, "summary must distinguish a force-killed result");
80
+ });
81
+
54
82
  test("registerExecTools exposes gsd_uat_exec intent as recoverable string schema", () => {
55
83
  const tools: Array<{ name: string; parameters: any }> = [];
56
84
  registerExecTools({
@@ -4,10 +4,13 @@
4
4
  import test from "node:test";
5
5
  import assert from "node:assert/strict";
6
6
  import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
7
+ import { execFileSync } from "node:child_process";
7
8
  import { join } from "node:path";
8
9
  import { tmpdir } from "node:os";
9
10
 
10
11
  import { buildGsdHomeModel, showGsdHome } from "../gsd-command-home.ts";
12
+ import { buildIdleMenuSummary, detectIdleMilestoneResidueHint } from "../closeout-wizard.ts";
13
+ import { closeDatabase, insertMilestone, openDatabase } from "../gsd-db.ts";
11
14
  import type { GSDState } from "../types.ts";
12
15
 
13
16
  function baseState(overrides: Partial<GSDState> = {}): GSDState {
@@ -118,6 +121,123 @@ test("/gsd home recommends start or configure after all milestones complete", ()
118
121
  assert.match(model.summary.join("\n"), /All milestones complete/);
119
122
  });
120
123
 
124
+ test("/gsd home recommends fix or recover when milestone git residue is stranded", () => {
125
+ const model = buildGsdHomeModel(baseState({
126
+ activeMilestone: null,
127
+ activeSlice: null,
128
+ activeTask: null,
129
+ phase: "complete",
130
+ nextAction: "All milestones complete.",
131
+ }), {
132
+ strandedQuick: null,
133
+ unmergedMilestones: [],
134
+ idleResidueHint: {
135
+ milestoneIds: ["M008"],
136
+ message:
137
+ "Stranded milestone git residue detected (M008: worktree dir and/or milestone/* branch). " +
138
+ "Run /gsd dispatch complete-milestone M008 or /gsd status to recover closeout before starting new work.",
139
+ },
140
+ });
141
+
142
+ assert.equal(action(model, "fix_recover").recommended, true);
143
+ assert.equal(action(model, "fix_recover").enabled, true);
144
+ assert.match(model.summary[0], /Stranded milestone git residue/);
145
+ assert.equal(action(model, "continue_step").enabled, false);
146
+ });
147
+
148
+ test("detectIdleMilestoneResidueHint reports missing workflow database in a git repo", () => {
149
+ const base = mkdtempSync(join(tmpdir(), "gsd-home-residue-"));
150
+ try {
151
+ execFileSync("git", ["init", "-b", "main"], { cwd: base, stdio: "ignore" });
152
+ const hint = detectIdleMilestoneResidueHint(base);
153
+ assert.ok(hint);
154
+ assert.match(hint!.message, /\.gsd\/gsd\.db/);
155
+ } finally {
156
+ rmSync(base, { recursive: true, force: true });
157
+ }
158
+ });
159
+
160
+ test("detectIdleMilestoneResidueHint matches unique-format milestone ids (M###-abc123)", () => {
161
+ const base = mkdtempSync(join(tmpdir(), "gsd-home-residue-unique-"));
162
+ try {
163
+ execFileSync("git", ["init", "-b", "main"], { cwd: base, stdio: "ignore" });
164
+ mkdirSync(join(base, ".gsd-worktrees", "M042-abc123"), { recursive: true });
165
+ mkdirSync(join(base, ".gsd"), { recursive: true });
166
+
167
+ openDatabase(join(base, ".gsd", "gsd.db"));
168
+ try {
169
+ // Closed milestone with lingering worktree dir — classic residue.
170
+ insertMilestone({ id: "M042-abc123", title: "Closed Unique", status: "complete" });
171
+ const hint = detectIdleMilestoneResidueHint(base);
172
+ assert.ok(hint, "unique-format closed milestone with worktree should be detected");
173
+ assert.deepEqual(hint!.milestoneIds, ["M042-abc123"]);
174
+ assert.match(hint!.message, /M042-abc123/);
175
+ } finally {
176
+ closeDatabase();
177
+ }
178
+ } finally {
179
+ rmSync(base, { recursive: true, force: true });
180
+ }
181
+ });
182
+
183
+ test("detectIdleMilestoneResidueHint ignores in-flight milestones with worktree artifacts", () => {
184
+ const base = mkdtempSync(join(tmpdir(), "gsd-home-residue-active-"));
185
+ try {
186
+ execFileSync("git", ["init", "-b", "main"], { cwd: base, stdio: "ignore" });
187
+ mkdirSync(join(base, ".gsd-worktrees", "M001"), { recursive: true });
188
+ mkdirSync(join(base, ".gsd-worktrees", "M002-abc123"), { recursive: true });
189
+ mkdirSync(join(base, ".gsd"), { recursive: true });
190
+
191
+ openDatabase(join(base, ".gsd", "gsd.db"));
192
+ try {
193
+ // Active and pending milestones must not be flagged as stranded residue.
194
+ insertMilestone({ id: "M001", title: "Active milestone", status: "active" });
195
+ insertMilestone({ id: "M002-abc123", title: "Pending milestone", status: "pending" });
196
+ const hint = detectIdleMilestoneResidueHint(base);
197
+ assert.equal(hint, null, "active/pending milestone worktrees must not be classified as residue");
198
+ } finally {
199
+ closeDatabase();
200
+ }
201
+ } finally {
202
+ rmSync(base, { recursive: true, force: true });
203
+ }
204
+ });
205
+
206
+ test("buildIdleMenuSummary surfaces idle residue hint even when phase is complete", () => {
207
+ const summary = buildIdleMenuSummary(
208
+ {
209
+ activeMilestone: null,
210
+ activeSlice: null,
211
+ activeTask: null,
212
+ phase: "complete",
213
+ recentDecisions: [],
214
+ blockers: [],
215
+ nextAction: "All milestones complete.",
216
+ lastCompletedMilestone: { id: "M001", title: "Menu Cleanup" },
217
+ registry: [{ id: "M001", title: "Menu Cleanup", status: "complete" }],
218
+ requirements: { active: 0, validated: 0, deferred: 0, outOfScope: 0, blocked: 0, total: 0 },
219
+ progress: {
220
+ milestones: { done: 1, total: 1 },
221
+ slices: { done: 0, total: 0 },
222
+ tasks: { done: 0, total: 0 },
223
+ },
224
+ },
225
+ {
226
+ strandedQuick: null,
227
+ unmergedMilestones: [],
228
+ idleResidueHint: {
229
+ milestoneIds: ["M008"],
230
+ message:
231
+ "Stranded milestone git residue detected (M008: worktree dir and/or milestone/* branch). " +
232
+ "Run /gsd dispatch complete-milestone M008 or /gsd status to recover closeout before starting new work.",
233
+ },
234
+ },
235
+ );
236
+
237
+ assert.match(summary[0] ?? "", /Stranded milestone git residue/);
238
+ assert.doesNotMatch(summary.join("\n"), /All milestones complete/);
239
+ });
240
+
121
241
  test("showGsdHome renders the five-slot home text without an interactive TUI", async () => {
122
242
  const base = mkdtempSync(join(tmpdir(), "gsd-home-"));
123
243
  const notifications: Array<{ message: string; level: string }> = [];
@@ -30,6 +30,8 @@ import {
30
30
  insertTask,
31
31
  getTask,
32
32
  getSliceTasks,
33
+ getMilestoneSliceSummaries,
34
+ getClosedSliceIds,
33
35
  getActiveMilestoneFromDb,
34
36
  deleteMilestone,
35
37
  clearEngineHierarchy,
@@ -947,6 +949,31 @@ describe('gsd-db', () => {
947
949
  closeDatabase();
948
950
  });
949
951
 
952
+ test('gsd-db: slice summaries use the canonical closed vocabulary; getClosedSliceIds filters to closed ids', () => {
953
+ openDatabase(':memory:');
954
+ insertMilestone({ id: 'M001', status: 'active' });
955
+ insertSlice({ milestoneId: 'M001', id: 'S01', title: 'Complete', status: 'complete', depends: [], sequence: 1 });
956
+ insertSlice({ milestoneId: 'M001', id: 'S02', title: 'Done', status: 'done', depends: ['S01'], sequence: 2 });
957
+ insertSlice({ milestoneId: 'M001', id: 'S03', title: 'Skipped', status: 'skipped', depends: [], sequence: 3 });
958
+ insertSlice({ milestoneId: 'M001', id: 'S04', title: 'Closed', status: 'closed', depends: [], sequence: 4 });
959
+ insertSlice({ milestoneId: 'M001', id: 'S05', title: 'Active', status: 'active', depends: [], sequence: 5 });
960
+ insertSlice({ milestoneId: 'M001', id: 'S06', title: 'Pending', status: 'pending', depends: ['S05'], sequence: 6 });
961
+
962
+ const summaries = getMilestoneSliceSummaries('M001');
963
+ assert.deepStrictEqual(summaries[0], { id: 'S01', title: 'Complete', done: true, depends: [] });
964
+ assert.deepStrictEqual(summaries[5], { id: 'S06', title: 'Pending', done: false, depends: ['S05'] });
965
+ assert.deepStrictEqual(
966
+ summaries.map((s) => s.done),
967
+ [true, true, true, true, false, false],
968
+ 'complete/done/skipped/closed are closed; active/pending are not',
969
+ );
970
+
971
+ assert.deepStrictEqual(getClosedSliceIds('M001'), ['S01', 'S02', 'S03', 'S04']);
972
+ assert.deepStrictEqual(getClosedSliceIds('M999'), [], 'unknown milestone yields no closed ids');
973
+
974
+ closeDatabase();
975
+ });
976
+
950
977
  test('gsd-db: FTS5 unavailable warning normalizes provider typo', () => {
951
978
  const previousStderr = setStderrLoggingEnabled(false);
952
979
  _resetLogs();
@@ -10,6 +10,8 @@ import {
10
10
  recoveryRemediation,
11
11
  needsAttentionBlockerGuidance,
12
12
  needsRemediationBlockerGuidance,
13
+ uatSignoffBlockerGuidance,
14
+ worktreeCreationFailedGuidance,
13
15
  crashResumeHint,
14
16
  doctorFixHint,
15
17
  type RecoveryGuidanceKey,
@@ -95,6 +97,27 @@ describe("milestone blocker guidance", () => {
95
97
  assert.match(text, /\/gsd status/);
96
98
  assert.match(text, /\/gsd validate-milestone/);
97
99
  });
100
+
101
+ test("UAT sign-off guidance explains direct dispatch target", () => {
102
+ const missing = uatSignoffBlockerGuidance("M007", "S02");
103
+ const failing = uatSignoffBlockerGuidance("M007", "S02", "FAIL");
104
+
105
+ for (const text of [missing, failing]) {
106
+ assert.match(text, /Manual UAT sign-off \(PASS\) is required before milestone closure/);
107
+ assert.match(text, /\/gsd dispatch uat/);
108
+ assert.match(text, /most recently completed slice/);
109
+ assert.match(text, /re-run UAT for S02/);
110
+ assert.match(text, /gsd_uat_result_save/);
111
+ }
112
+ });
113
+
114
+ test("worktree creation failure guidance does not claim bootstrap continues", () => {
115
+ const text = worktreeCreationFailedGuidance("M007", "boom");
116
+
117
+ assert.match(text, /Auto-worktree creation for M007 failed: boom\. Continuing in project root\./);
118
+ assert.match(text, /Worktree isolation is degraded for this session\./);
119
+ assert.doesNotMatch(text, /work continues in the project root/i);
120
+ });
98
121
  });
99
122
 
100
123
  describe("crash resume hints", () => {
@@ -11,6 +11,7 @@ import {
11
11
  _dispatchWorkflowForTest,
12
12
  resolveGuidedDispatchProjectRoot,
13
13
  } from "../guided-flow.ts";
14
+ import { getRequiredWorkflowToolsForUnit } from "../unit-tool-contracts.ts";
14
15
 
15
16
  test("guided dispatch falls back to cwd only when no project root is supplied", () => {
16
17
  const cwd = process.cwd();
@@ -77,12 +78,8 @@ test("guided dispatch passes the explicit project root through model and compati
77
78
  seen.modelRoot = projectRoot;
78
79
  return { routing: null, appliedModel: null };
79
80
  },
80
- getTransportSupportError: (
81
- _provider: string | undefined,
82
- _requiredTools: string[],
83
- options?: { projectRoot?: string },
84
- ) => {
85
- seen.compatibilityRoot = options?.projectRoot ?? "";
81
+ getDispatchReadinessError: (input: { projectRoot?: string }) => {
82
+ seen.compatibilityRoot = input.projectRoot ?? "";
86
83
  return null;
87
84
  },
88
85
  },
@@ -119,6 +116,7 @@ test("guided dispatch accepts workflow MCP tools absent from parent active tool
119
116
  getProviderAuthMode: () => "externalCli",
120
117
  },
121
118
  ui: {
119
+ setStatus: () => {},
122
120
  notify: (message: string) => {
123
121
  notifications.push(message);
124
122
  },
@@ -134,8 +132,22 @@ test("guided dispatch accepts workflow MCP tools absent from parent active tool
134
132
  "write",
135
133
  ];
136
134
 
135
+ // The workflow MCP server registers its tools out of band, so the unit's
136
+ // required workflow tools show up in the registered tool snapshot
137
+ // (getAllTools) under the MCP server prefix without ever entering the parent
138
+ // session's active tool surface (getActiveTools). This is exactly the shape
139
+ // the readiness gate must accept. Derive the surface from the unit contract
140
+ // so this test stays correct if discuss-milestone's required tools change.
141
+ const registeredTools = [
142
+ ...activeTools,
143
+ ...getRequiredWorkflowToolsForUnit("discuss-milestone").map(
144
+ (tool) => `mcp__gsd-workflow__${tool}`,
145
+ ),
146
+ ];
147
+
137
148
  const pi = {
138
149
  getActiveTools: () => [...activeTools],
150
+ getAllTools: () => registeredTools.map((name) => ({ name })),
139
151
  setActiveTools: (tools: string[]) => {
140
152
  activeTools = [...tools];
141
153
  },
@@ -134,6 +134,21 @@ describe("auto-worktree lifecycle", () => {
134
134
  teardownAutoWorktree(tempDir, "M003");
135
135
  });
136
136
 
137
+ test("isInAutoWorktree returns false when ambient cwd was deleted", (t) => {
138
+ const cwd = t.mock.method(process, "cwd", () => {
139
+ const err = new Error("process.cwd failed") as NodeJS.ErrnoException;
140
+ err.code = "ENOENT";
141
+ err.syscall = "uv_cwd";
142
+ throw err;
143
+ });
144
+
145
+ try {
146
+ assert.equal(isInAutoWorktree("/repo"), false);
147
+ } finally {
148
+ cwd.mock.restore();
149
+ }
150
+ });
151
+
137
152
  test("symlink-resolved auto worktree is detected after module state reset", () => {
138
153
  tempDir = createTempRepo();
139
154
  const savedGsdHome = process.env.GSD_HOME;
@@ -0,0 +1,104 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Verify the non-blocking runEnvironmentChecksAsync is behaviourally
3
+ // identical to the synchronous runEnvironmentChecks (the health-widget render
4
+ // path was moved onto the async variant for performance), and that the single-
5
+ // scan checkPortConflicts still detects a real in-use port.
6
+
7
+ import test, { type TestContext } from "node:test";
8
+ import assert from "node:assert/strict";
9
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
10
+ import { join, dirname } from "node:path";
11
+ import { tmpdir } from "node:os";
12
+ import { createServer } from "node:net";
13
+
14
+ import {
15
+ runEnvironmentChecks,
16
+ runEnvironmentChecksAsync,
17
+ type EnvironmentCheckResult,
18
+ } from "../../doctor-environment.ts";
19
+
20
+ function makeProject(t: TestContext, files: Record<string, string>): string {
21
+ const dir = mkdtempSync(join(tmpdir(), "gsd-env-async-"));
22
+ t.after(() => {
23
+ try {
24
+ rmSync(dir, { recursive: true, force: true });
25
+ } catch {
26
+ /* ignore */
27
+ }
28
+ });
29
+ for (const [name, content] of Object.entries(files)) {
30
+ const filePath = join(dir, name);
31
+ mkdirSync(dirname(filePath), { recursive: true });
32
+ writeFileSync(filePath, content);
33
+ }
34
+ return dir;
35
+ }
36
+
37
+ // Stable, order-independent signature of a check-result set for comparison.
38
+ function normalize(results: EnvironmentCheckResult[]): string[] {
39
+ return results.map((r) => `${r.name}|${r.status}|${r.message}|${r.detail ?? ""}`).sort();
40
+ }
41
+
42
+ test("runEnvironmentChecksAsync returns the same results as runEnvironmentChecks", async (t) => {
43
+ const dir = makeProject(t, {
44
+ "package.json": JSON.stringify({
45
+ name: "fixture",
46
+ engines: { node: ">=18" },
47
+ scripts: { dev: "vite --port 4321", build: "tsc" },
48
+ devDependencies: { typescript: "^5.0.0" },
49
+ }),
50
+ ".env.example": "API_KEY=\n",
51
+ Dockerfile: "FROM node:20\n",
52
+ });
53
+ mkdirSync(join(dir, "node_modules"), { recursive: true });
54
+
55
+ const sync = runEnvironmentChecks(dir);
56
+ const asyncResults = await runEnvironmentChecksAsync(dir);
57
+
58
+ assert.deepEqual(
59
+ normalize(asyncResults),
60
+ normalize(sync),
61
+ "async checks must produce the identical result set as the sync checks",
62
+ );
63
+ // Sanity: the fixture is rich enough that the suite actually produced checks.
64
+ assert.ok(sync.length > 0, "expected the fixture to yield environment checks");
65
+ });
66
+
67
+ test("runEnvironmentChecksAsync matches sync on a bare directory (no package.json)", async (t) => {
68
+ const dir = makeProject(t, {});
69
+ const sync = runEnvironmentChecks(dir);
70
+ const asyncResults = await runEnvironmentChecksAsync(dir);
71
+ assert.deepEqual(normalize(asyncResults), normalize(sync));
72
+ });
73
+
74
+ test(
75
+ "single-scan port check detects a real in-use port, identically sync and async",
76
+ { skip: process.platform === "win32" ? "lsof-based port check is macOS/Linux only" : false },
77
+ async (t) => {
78
+ // Bind a real listener, then reference its port from package.json scripts so
79
+ // collectPortsToCheck picks it up. The server stays up across both check runs.
80
+ const server = createServer();
81
+ const port = await new Promise<number>((resolve, reject) => {
82
+ server.once("error", reject);
83
+ server.listen(0, "127.0.0.1", () => {
84
+ const addr = server.address();
85
+ resolve(typeof addr === "object" && addr ? addr.port : 0);
86
+ });
87
+ });
88
+ t.after(() => new Promise<void>((resolve) => server.close(() => resolve())));
89
+ assert.ok(port >= 1024 && port <= 65535, "ephemeral port should be in the checked range");
90
+
91
+ const dir = makeProject(t, {
92
+ "package.json": JSON.stringify({ name: "fixture", scripts: { dev: `serve --port ${port}` } }),
93
+ });
94
+
95
+ const syncConflicts = runEnvironmentChecks(dir).filter((r) => r.name === "port_conflict");
96
+ const asyncConflicts = (await runEnvironmentChecksAsync(dir)).filter((r) => r.name === "port_conflict");
97
+
98
+ // Equivalence holds regardless of whether lsof is present on the runner.
99
+ assert.deepEqual(normalize(asyncConflicts), normalize(syncConflicts), "sync and async must agree on port conflicts");
100
+ // On macOS/Linux lsof is standard, so the listener must be reported and named.
101
+ assert.equal(syncConflicts.length, 1, "expected exactly one port conflict for the in-use port");
102
+ assert.match(syncConflicts[0]!.message, new RegExp(`\\b${port}\\b`), "conflict message must name the in-use port");
103
+ },
104
+ );