@opengsd/gsd-pi 1.2.0-dev.b1abb545 → 1.2.0-dev.fb12b103

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 (520) hide show
  1. package/dist/cli-style.d.ts +17 -0
  2. package/dist/cli-style.js +28 -0
  3. package/dist/cli.js +1 -1
  4. package/dist/headless-events.d.ts +4 -2
  5. package/dist/headless-events.js +7 -29
  6. package/dist/models-resolver.d.ts +3 -13
  7. package/dist/models-resolver.js +3 -22
  8. package/dist/resource-loader.js +2 -14
  9. package/dist/resources/.managed-resources-content-hash +1 -1
  10. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  11. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  12. package/dist/resources/extensions/async-jobs/index.js +65 -0
  13. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  14. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  15. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  16. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  17. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  18. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  19. package/dist/resources/extensions/bg-shell/utilities.js +5 -2
  20. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  21. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  22. package/dist/resources/extensions/browser-tools/index.js +69 -12
  23. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  24. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +38 -6
  25. package/dist/resources/extensions/gsd/auto/orchestrator.js +40 -9
  26. package/dist/resources/extensions/gsd/auto/phases.js +6 -1
  27. package/dist/resources/extensions/gsd/auto-dispatch.js +12 -1
  28. package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
  29. package/dist/resources/extensions/gsd/auto-post-unit.js +19 -8
  30. package/dist/resources/extensions/gsd/auto-prompts.js +15 -10
  31. package/dist/resources/extensions/gsd/auto-start.js +21 -21
  32. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  33. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +7 -16
  34. package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
  35. package/dist/resources/extensions/gsd/auto-worktree.js +35 -352
  36. package/dist/resources/extensions/gsd/auto.js +8 -20
  37. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
  38. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -12
  39. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  40. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +151 -20
  41. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +30 -4
  42. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  43. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  44. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  45. package/dist/resources/extensions/gsd/captures.js +5 -15
  46. package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
  47. package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
  48. package/dist/resources/extensions/gsd/constants.js +0 -2
  49. package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
  50. package/dist/resources/extensions/gsd/db/engine.js +755 -0
  51. package/dist/resources/extensions/gsd/db/queries.js +372 -0
  52. package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
  53. package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
  54. package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
  55. package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
  56. package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
  57. package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
  58. package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
  59. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  60. package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
  61. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
  62. package/dist/resources/extensions/gsd/error-classifier.js +9 -0
  63. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  64. package/dist/resources/extensions/gsd/git-service.js +1 -0
  65. package/dist/resources/extensions/gsd/gitignore.js +3 -0
  66. package/dist/resources/extensions/gsd/gsd-db.js +171 -2048
  67. package/dist/resources/extensions/gsd/guidance.js +98 -0
  68. package/dist/resources/extensions/gsd/guided-flow.js +51 -5
  69. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  70. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  71. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  72. package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
  73. package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
  74. package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
  75. package/dist/resources/extensions/gsd/model-router.js +3 -0
  76. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  77. package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
  78. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
  79. package/dist/resources/extensions/gsd/paths.js +37 -24
  80. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  81. package/dist/resources/extensions/gsd/preferences-models.js +14 -48
  82. package/dist/resources/extensions/gsd/preferences.js +14 -0
  83. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  84. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  85. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  86. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  87. package/dist/resources/extensions/gsd/prompts/run-uat.md +1 -1
  88. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  89. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  90. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  91. package/dist/resources/extensions/gsd/publication.js +87 -0
  92. package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
  93. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  94. package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
  95. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
  96. package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
  97. package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
  98. package/dist/resources/extensions/gsd/state.js +1 -20
  99. package/dist/resources/extensions/gsd/status-guards.js +56 -8
  100. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  101. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  102. package/dist/resources/extensions/gsd/tools/complete-slice.js +24 -43
  103. package/dist/resources/extensions/gsd/tools/exec-tool.js +10 -8
  104. package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
  105. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
  106. package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
  107. package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
  108. package/dist/resources/extensions/gsd/uat-policy.js +2 -1
  109. package/dist/resources/extensions/gsd/undo.js +8 -7
  110. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  111. package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
  112. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  113. package/dist/resources/extensions/gsd/unit-registry.js +337 -0
  114. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  115. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  116. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  117. package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
  118. package/dist/resources/extensions/gsd/worktree-lifecycle.js +9 -1
  119. package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
  120. package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
  121. package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
  122. package/dist/resources/extensions/gsd/worktree-root.js +28 -6
  123. package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
  124. package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
  125. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  126. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  127. package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
  128. package/dist/resources/shared/package.json +3 -0
  129. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  130. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  131. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  132. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  133. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  134. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  135. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  136. package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
  137. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  138. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  139. package/dist/web/standalone/.next/BUILD_ID +1 -1
  140. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  141. package/dist/web/standalone/.next/build-manifest.json +3 -3
  142. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  143. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  144. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  145. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  147. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  153. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  154. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  155. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  156. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  158. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  159. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  162. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  164. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  168. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  170. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  174. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  176. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  178. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  180. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  182. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  184. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  186. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  188. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  190. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  192. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  195. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/index.html +1 -1
  197. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  198. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  199. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  200. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  201. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  203. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  204. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  205. package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
  206. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  207. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  210. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  211. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  212. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  213. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  214. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  215. package/dist/web/standalone/node_modules/postcss/lib/container.js +18 -26
  216. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +14 -47
  217. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  218. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  219. package/dist/web/standalone/node_modules/postcss/lib/input.js +29 -54
  220. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +37 -47
  221. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +9 -26
  222. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +55 -57
  223. package/dist/web/standalone/node_modules/postcss/lib/node.js +31 -99
  224. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  225. package/dist/web/standalone/node_modules/postcss/lib/parser.js +9 -10
  226. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  227. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +11 -30
  228. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  229. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  230. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  231. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +28 -69
  232. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +2 -6
  233. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  234. package/dist/web/standalone/package.json +1 -1
  235. package/dist/worktree-cli.js +3 -6
  236. package/dist/worktree-status-banner.js +7 -11
  237. package/package.json +1 -1
  238. package/packages/cloud-mcp-gateway/package.json +2 -2
  239. package/packages/contracts/dist/rpc.d.ts +1 -0
  240. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  241. package/packages/contracts/dist/rpc.js.map +1 -1
  242. package/packages/contracts/dist/workflow.d.ts +4 -0
  243. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  244. package/packages/contracts/dist/workflow.js.map +1 -1
  245. package/packages/contracts/package.json +1 -1
  246. package/packages/daemon/package.json +4 -4
  247. package/packages/gsd-agent-core/package.json +5 -5
  248. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  249. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  250. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +8 -0
  251. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  252. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  253. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  254. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  255. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  256. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  257. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  258. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  259. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  260. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  261. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  262. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  263. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  264. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  265. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  266. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  267. package/packages/gsd-agent-modes/package.json +7 -7
  268. package/packages/mcp-server/dist/cli.js +6 -3
  269. package/packages/mcp-server/dist/cli.js.map +1 -1
  270. package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
  271. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  272. package/packages/mcp-server/dist/workflow-tools.js +46 -21
  273. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  274. package/packages/mcp-server/package.json +3 -3
  275. package/packages/native/package.json +1 -1
  276. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  277. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  278. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  279. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  280. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  281. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  282. package/packages/pi-agent-core/dist/index.js +3 -0
  283. package/packages/pi-agent-core/dist/index.js.map +1 -1
  284. package/packages/pi-agent-core/package.json +1 -1
  285. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  286. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  287. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  288. package/packages/pi-ai/dist/models.generated.d.ts +478 -484
  289. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  290. package/packages/pi-ai/dist/models.generated.js +500 -533
  291. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  292. package/packages/pi-ai/package.json +1 -1
  293. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  294. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  296. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
  299. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  301. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  302. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  304. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  305. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  306. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  307. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  308. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/index.js +1 -1
  310. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  312. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  313. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  314. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  315. package/packages/pi-coding-agent/package.json +7 -7
  316. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  317. package/packages/pi-tui/dist/tui.js +9 -0
  318. package/packages/pi-tui/dist/tui.js.map +1 -1
  319. package/packages/pi-tui/package.json +2 -2
  320. package/packages/rpc-client/package.json +2 -2
  321. package/pkg/package.json +1 -1
  322. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  323. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  324. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  325. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  326. package/src/resources/extensions/async-jobs/index.ts +79 -0
  327. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  328. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  329. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  330. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  331. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  332. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  333. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  334. package/src/resources/extensions/bg-shell/utilities.ts +5 -2
  335. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  336. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  337. package/src/resources/extensions/browser-tools/index.ts +71 -13
  338. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  339. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
  340. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  341. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  342. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +40 -4
  343. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
  344. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
  345. package/src/resources/extensions/gsd/auto/orchestrator.ts +46 -10
  346. package/src/resources/extensions/gsd/auto/phases.ts +10 -1
  347. package/src/resources/extensions/gsd/auto-dispatch.ts +12 -0
  348. package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
  349. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -7
  350. package/src/resources/extensions/gsd/auto-prompts.ts +40 -26
  351. package/src/resources/extensions/gsd/auto-start.ts +21 -22
  352. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  353. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +10 -17
  354. package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
  355. package/src/resources/extensions/gsd/auto-worktree.ts +41 -364
  356. package/src/resources/extensions/gsd/auto.ts +20 -24
  357. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
  358. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +33 -12
  359. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  360. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +180 -15
  361. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +29 -3
  362. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  363. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  364. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  365. package/src/resources/extensions/gsd/captures.ts +5 -16
  366. package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
  367. package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
  368. package/src/resources/extensions/gsd/constants.ts +0 -3
  369. package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
  370. package/src/resources/extensions/gsd/db/engine.ts +809 -0
  371. package/src/resources/extensions/gsd/db/queries.ts +453 -0
  372. package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
  373. package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
  374. package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
  375. package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
  376. package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
  377. package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
  378. package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
  379. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  380. package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
  381. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
  382. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  383. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  384. package/src/resources/extensions/gsd/git-service.ts +1 -0
  385. package/src/resources/extensions/gsd/gitignore.ts +3 -0
  386. package/src/resources/extensions/gsd/gsd-db.ts +173 -2373
  387. package/src/resources/extensions/gsd/guidance.ts +139 -0
  388. package/src/resources/extensions/gsd/guided-flow.ts +50 -5
  389. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  390. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  391. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  392. package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
  393. package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
  394. package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
  395. package/src/resources/extensions/gsd/model-router.ts +3 -0
  396. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  397. package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
  398. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
  399. package/src/resources/extensions/gsd/paths.ts +42 -22
  400. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  401. package/src/resources/extensions/gsd/preferences-models.ts +12 -47
  402. package/src/resources/extensions/gsd/preferences.ts +18 -0
  403. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  404. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  405. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  406. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  407. package/src/resources/extensions/gsd/prompts/run-uat.md +1 -1
  408. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  409. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  410. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  411. package/src/resources/extensions/gsd/publication.ts +122 -0
  412. package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
  413. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  414. package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
  415. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
  416. package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
  417. package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
  418. package/src/resources/extensions/gsd/state.ts +4 -21
  419. package/src/resources/extensions/gsd/status-guards.ts +59 -8
  420. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  421. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
  422. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
  423. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +16 -19
  424. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
  425. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
  426. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
  427. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
  428. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  429. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  430. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  431. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  432. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
  433. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  434. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  435. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  436. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  437. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
  438. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  439. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  440. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  441. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
  442. package/src/resources/extensions/gsd/tests/guidance.test.ts +125 -0
  443. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +58 -15
  444. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +74 -59
  445. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  446. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  447. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  448. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
  449. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  450. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  451. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  452. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  453. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  454. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  455. package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
  456. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +248 -1
  457. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
  458. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
  459. package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
  460. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
  461. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
  462. package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
  463. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  464. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  465. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  466. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  467. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +24 -29
  468. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  469. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
  470. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  471. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  472. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  473. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
  474. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
  475. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
  476. package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
  477. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
  478. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
  479. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
  480. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
  481. package/src/resources/extensions/gsd/tests/write-gate.test.ts +42 -0
  482. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  483. package/src/resources/extensions/gsd/tools/complete-slice.ts +23 -58
  484. package/src/resources/extensions/gsd/tools/exec-tool.ts +9 -8
  485. package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
  486. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
  487. package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
  488. package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
  489. package/src/resources/extensions/gsd/uat-policy.ts +2 -1
  490. package/src/resources/extensions/gsd/undo.ts +9 -8
  491. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  492. package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
  493. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  494. package/src/resources/extensions/gsd/unit-registry.ts +412 -0
  495. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  496. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  497. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  498. package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
  499. package/src/resources/extensions/gsd/worktree-lifecycle.ts +10 -1
  500. package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
  501. package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
  502. package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
  503. package/src/resources/extensions/gsd/worktree-root.ts +29 -6
  504. package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
  505. package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
  506. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  507. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  508. package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
  509. package/src/resources/shared/package.json +3 -0
  510. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  511. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  512. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  513. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  514. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  515. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  516. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  517. package/src/resources/skills/gsd-browser/SKILL.md +1 -1
  518. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  519. /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → mU4QIDlpVHDdjDpeEKh5W}/_buildManifest.js +0 -0
  520. /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → mU4QIDlpVHDdjDpeEKh5W}/_ssgManifest.js +0 -0
@@ -10,6 +10,7 @@ import { DISCUSS_TOOLS_ALLOWLIST } from "../constants.ts";
10
10
  import { buildMinimalAutoGsdToolSet, buildMinimalGsdToolSet, buildMinimalGsdWorkflowToolSet, buildRequestScopedGsdToolSet, MINIMAL_AUTO_BASE_TOOL_NAMES, MINIMAL_GSD_TOOL_NAMES, requestHasGsdCustomType, restoreGsdWorkflowTools, scopeGsdWorkflowToolsForDispatch } from "../bootstrap/register-hooks.ts";
11
11
  import { filterToolsForProvider } from "../model-router.ts";
12
12
  import { applyUnitSkillVisibility } from "../skill-scope.ts";
13
+ import { drainLogs } from "../workflow-logger.ts";
13
14
 
14
15
  test("buildMinimalGsdToolSet preserves non-GSD tools and replaces broad GSD surface", () => {
15
16
  const result = buildMinimalGsdToolSet([
@@ -17,6 +18,7 @@ test("buildMinimalGsdToolSet preserves non-GSD tools and replaces broad GSD surf
17
18
  "read",
18
19
  "browser_open",
19
20
  "gsd_plan_milestone",
21
+ "gsd_plan_slice",
20
22
  "gsd_task_complete",
21
23
  "gsd_exec",
22
24
  "gsd_exec_search",
@@ -103,6 +105,40 @@ test("buildMinimalAutoGsdToolSet keeps unit-specific completion tools without al
103
105
  assert.ok(!result.includes("gsd_complete_slice"));
104
106
  });
105
107
 
108
+ test("buildMinimalAutoGsdToolSet warns when plan-milestone required tools are unresolved", () => {
109
+ drainLogs();
110
+ const result = buildMinimalAutoGsdToolSet(
111
+ [
112
+ "ask_user_questions",
113
+ "bash",
114
+ "read",
115
+ "gsd_milestone_status",
116
+ "gsd_plan_milestone",
117
+ ],
118
+ "plan-milestone",
119
+ [
120
+ "ask_user_questions",
121
+ "bash",
122
+ "read",
123
+ "gsd_milestone_status",
124
+ "gsd_plan_milestone",
125
+ ],
126
+ );
127
+
128
+ assert.ok(result.includes("gsd_plan_milestone"));
129
+ assert.ok(!result.includes("gsd_plan_slice"));
130
+
131
+ const logs = drainLogs();
132
+ assert.ok(
133
+ logs.some((entry) =>
134
+ entry.component === "bootstrap" &&
135
+ entry.message.includes("buildMinimalAutoGsdToolSet(plan-milestone)") &&
136
+ entry.message.includes("gsd_plan_slice")
137
+ ),
138
+ `expected missing gsd_plan_slice bootstrap warning, got ${JSON.stringify(logs)}`,
139
+ );
140
+ });
141
+
106
142
  test("buildMinimalAutoGsdToolSet scopes run-uat to UAT-specific and read-only tools", () => {
107
143
  const active = ["ask_user_questions", "bash", "read", "edit", "write", "gsd_summary_save"];
108
144
  const registered = [
@@ -613,6 +649,46 @@ test("buildMinimalAutoGsdToolSet resolves MCP-scoped gsd_memory_query and gsd_ca
613
649
  );
614
650
  });
615
651
 
652
+ // ── Regression #627: auto-mode cannot run plan-milestone because gsd_plan_slice is missing ──
653
+ // gsd_plan_slice is in AUTO_UNIT_SCOPED_TOOLS["plan-milestone"] (via unit-tool-contracts).
654
+ // buildMinimalAutoGsdToolSet must expose it when unitType is "plan-milestone".
655
+
656
+ test("buildMinimalAutoGsdToolSet includes gsd_plan_slice for plan-milestone (regression #627)", () => {
657
+ const result = buildMinimalAutoGsdToolSet([
658
+ "bash",
659
+ "read",
660
+ "gsd_plan_milestone",
661
+ "gsd_plan_slice",
662
+ "gsd_milestone_status",
663
+ "gsd_checkpoint_db",
664
+ "memory_query",
665
+ "capture_thought",
666
+ ], "plan-milestone");
667
+
668
+ assert.ok(
669
+ result.includes("gsd_plan_slice"),
670
+ "gsd_plan_slice must be included in plan-milestone auto-mode tool set",
671
+ );
672
+ });
673
+
674
+ test("buildMinimalAutoGsdToolSet resolves MCP-scoped gsd_plan_slice for plan-milestone when subprocess only registers prefixed variant (regression #627)", () => {
675
+ const result = buildMinimalAutoGsdToolSet([
676
+ "bash",
677
+ "read",
678
+ "mcp__gsd-workflow__gsd_plan_milestone",
679
+ "mcp__gsd-workflow__gsd_plan_slice",
680
+ "mcp__gsd-workflow__gsd_milestone_status",
681
+ "mcp__gsd-workflow__gsd_checkpoint_db",
682
+ "mcp__gsd-workflow__memory_query",
683
+ "mcp__gsd-workflow__capture_thought",
684
+ ], "plan-milestone");
685
+
686
+ assert.ok(
687
+ result.includes("mcp__gsd-workflow__gsd_plan_slice"),
688
+ "mcp__gsd-workflow__gsd_plan_slice must be included when only the MCP-scoped variant is available",
689
+ );
690
+ });
691
+
616
692
  test("applyUnitSkillVisibility sets manifest or clears for wildcard", () => {
617
693
  const calls: Array<string[] | undefined> = [];
618
694
  applyUnitSkillVisibility({
@@ -48,6 +48,7 @@ import {
48
48
  isDeterministicPolicyError,
49
49
  isPendingUserApprovalGateError,
50
50
  isToolInvocationError,
51
+ isToolUnavailableError,
51
52
  isQueuedUserMessageSkip,
52
53
  } from "../auto-tool-tracking.ts";
53
54
  import {
@@ -121,6 +122,13 @@ describe("#2883: isToolInvocationError classification", () => {
121
122
  assert.equal(isToolInvocationError("No such tool available: mcp__gsd-workflow__memory_query"), true);
122
123
  });
123
124
 
125
+ test("isToolUnavailableError singles out the startup-race error as transient", () => {
126
+ assert.equal(isToolUnavailableError("No such tool available: mcp__gsd-workflow__gsd_uat_exec"), true);
127
+ assert.equal(isToolUnavailableError("Validation failed for tool gsd_complete_slice"), false);
128
+ assert.equal(isToolUnavailableError("Unexpected end of JSON input"), false);
129
+ assert.equal(isToolUnavailableError(""), false);
130
+ });
131
+
124
132
  test("detects ESM export-link errors", () => {
125
133
  assert.equal(
126
134
  isToolInvocationError("The requested module '../paths.js' does not provide an export named 'gsdProjectionRoot'"),
@@ -0,0 +1,155 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Contract coverage for the Tool Surface Readiness gate and its recovery classification.
3
+
4
+ import { describe, test } from "node:test";
5
+ import assert from "node:assert/strict";
6
+
7
+ import { getToolSurfaceReadinessError } from "../tool-surface-readiness.ts";
8
+ import { isToolUnavailableError } from "../auto-tool-tracking.ts";
9
+ import { classifyError, isTransient } from "../error-classifier.ts";
10
+ import { toMcpToolName } from "../mcp-tool-name.ts";
11
+ import { classifyFailure } from "../recovery-classification.ts";
12
+
13
+ const SERVER = "gsd-workflow";
14
+
15
+ function prefixed(tool: string): string {
16
+ return toMcpToolName(SERVER, tool);
17
+ }
18
+
19
+ const RUN_UAT_TOOLS = [
20
+ "gsd_uat_exec",
21
+ "gsd_uat_result_save",
22
+ "gsd_resume",
23
+ "gsd_milestone_status",
24
+ "gsd_journal_query",
25
+ ];
26
+
27
+ describe("getToolSurfaceReadinessError", () => {
28
+ test("returns null when no unit type or no workflow server is in play", () => {
29
+ const observation = { tools: [], mcpServers: [] };
30
+ assert.equal(
31
+ getToolSurfaceReadinessError({ unitType: undefined, workflowServerName: SERVER, observation }),
32
+ null,
33
+ );
34
+ assert.equal(
35
+ getToolSurfaceReadinessError({ unitType: "run-uat", workflowServerName: undefined, observation }),
36
+ null,
37
+ );
38
+ });
39
+
40
+ test("returns null for units with no required workflow tools", () => {
41
+ const error = getToolSurfaceReadinessError({
42
+ unitType: "rewrite-docs",
43
+ workflowServerName: SERVER,
44
+ observation: { tools: [], mcpServers: [{ name: SERVER, status: "failed" }] },
45
+ });
46
+ assert.equal(error, null);
47
+ });
48
+
49
+ test("returns an error when the expected workflow server is absent from the init surface", () => {
50
+ const error = getToolSurfaceReadinessError({
51
+ unitType: "run-uat",
52
+ workflowServerName: SERVER,
53
+ observation: { tools: ["read", "bash"], mcpServers: [{ name: "other-server", status: "connected" }] },
54
+ });
55
+ assert.ok(error, "expected a readiness error when the workflow server is absent");
56
+ assert.match(error, /workflow tool surface not ready for run-uat/);
57
+ assert.match(error, /absent from the init surface/);
58
+ assert.match(error, /gsd_uat_exec/);
59
+ });
60
+
61
+ test("passes a still-connecting (pending) server through instead of aborting", () => {
62
+ // The SDK reports still-connecting servers as "pending" at init — the
63
+ // common healthy session. A genuine miss after pass-through is caught
64
+ // in-session ("No such tool available" → tool-unavailable → retry).
65
+ const error = getToolSurfaceReadinessError({
66
+ unitType: "plan-slice",
67
+ workflowServerName: SERVER,
68
+ observation: { tools: ["read", "bash"], mcpServers: [{ name: SERVER, status: "pending" }] },
69
+ });
70
+ assert.equal(error, null);
71
+ });
72
+
73
+ test("returns null when all required tools are registered under the MCP prefix", () => {
74
+ const error = getToolSurfaceReadinessError({
75
+ unitType: "run-uat",
76
+ workflowServerName: SERVER,
77
+ observation: {
78
+ tools: ["read", ...RUN_UAT_TOOLS.map(prefixed)],
79
+ mcpServers: [{ name: SERVER, status: "connected" }],
80
+ },
81
+ });
82
+ assert.equal(error, null);
83
+ });
84
+
85
+ test("reports the failed server and the missing tools when the surface never registered", () => {
86
+ const error = getToolSurfaceReadinessError({
87
+ unitType: "run-uat",
88
+ workflowServerName: SERVER,
89
+ observation: { tools: ["read", "bash"], mcpServers: [{ name: SERVER, status: "failed" }] },
90
+ });
91
+ assert.ok(error, "expected a readiness error");
92
+ assert.match(error, /workflow tool surface not ready for run-uat/);
93
+ assert.match(error, /status is "failed"/);
94
+ assert.match(error, /gsd_uat_exec/);
95
+ });
96
+
97
+ test("aborts on needs-auth (terminal — cannot self-heal)", () => {
98
+ const error = getToolSurfaceReadinessError({
99
+ unitType: "run-uat",
100
+ workflowServerName: SERVER,
101
+ observation: { tools: ["read", "bash"], mcpServers: [{ name: SERVER, status: "needs-auth" }] },
102
+ });
103
+ assert.ok(error, "expected a readiness error for needs-auth");
104
+ assert.match(error, /status is "needs-auth"/);
105
+ });
106
+
107
+ test("aborts on disabled (terminal — cannot self-heal)", () => {
108
+ const error = getToolSurfaceReadinessError({
109
+ unitType: "run-uat",
110
+ workflowServerName: SERVER,
111
+ observation: { tools: ["read", "bash"], mcpServers: [{ name: SERVER, status: "disabled" }] },
112
+ });
113
+ assert.ok(error, "expected a readiness error for disabled");
114
+ assert.match(error, /status is "disabled"/);
115
+ });
116
+
117
+ test("reports partially-registered surfaces even when the server says connected", () => {
118
+ const error = getToolSurfaceReadinessError({
119
+ unitType: "run-uat",
120
+ workflowServerName: SERVER,
121
+ observation: {
122
+ tools: [prefixed("gsd_uat_exec")],
123
+ mcpServers: [{ name: SERVER, status: "connected" }],
124
+ },
125
+ });
126
+ assert.ok(error, "expected a readiness error");
127
+ assert.match(error, /connected but has not registered/);
128
+ assert.match(error, /gsd_uat_result_save/);
129
+ assert.doesNotMatch(error, /gsd_uat_exec,/);
130
+ });
131
+ });
132
+
133
+ describe("readiness error classification contract", () => {
134
+ const readinessError = getToolSurfaceReadinessError({
135
+ unitType: "run-uat",
136
+ workflowServerName: SERVER,
137
+ observation: { tools: [], mcpServers: [{ name: SERVER, status: "failed" }] },
138
+ })!;
139
+
140
+ test("auto-tool-tracking treats the readiness error as tool-unavailable", () => {
141
+ assert.equal(isToolUnavailableError(readinessError), true);
142
+ });
143
+
144
+ test("error-classifier treats the readiness error as transient", () => {
145
+ const cls = classifyError(`Claude Code error: ${readinessError}`);
146
+ assert.equal(isTransient(cls), true);
147
+ });
148
+
149
+ test("Recovery Classification maps the readiness error to tool-unavailable → retry", () => {
150
+ const recovery = classifyFailure({ error: new Error(readinessError), unitType: "run-uat", unitId: "M001" });
151
+ assert.equal(recovery.failureKind, "tool-unavailable");
152
+ assert.equal(recovery.action, "retry");
153
+ assert.equal(recovery.exitReason, "tool-unavailable");
154
+ });
155
+ });
@@ -5,7 +5,6 @@ import {
5
5
  classifyUatContent,
6
6
  getDeclaredUatType,
7
7
  getUatBrowserToolSupportError,
8
- hasUatBrowserToolSurface,
9
8
  isPartialEligibleUatType,
10
9
  resolveEffectiveUatType,
11
10
  shouldDispatchUatForContent,
@@ -13,6 +12,12 @@ import {
13
12
  uatTypeIncludesBrowser,
14
13
  validateUatModePolicy,
15
14
  } from "../uat-policy.ts";
15
+ import {
16
+ assertBrowserAutomationContractAvailable,
17
+ assertBrowserAutomationContractMissing,
18
+ assertBrowserBackedUatCanDispatch,
19
+ BROWSER_AUTOMATION_CONTRACT_TOOLS,
20
+ } from "./browser-automation-contract-fixture.ts";
16
21
 
17
22
  describe("uat-policy", () => {
18
23
  it("defaults missing UAT mode to artifact-driven", () => {
@@ -63,14 +68,14 @@ describe("uat-policy", () => {
63
68
  }
64
69
  });
65
70
 
66
- it("detects direct and MCP-shaped browser tool surfaces", () => {
67
- assert.equal(hasUatBrowserToolSurface(["read", "browser_navigate"]), true);
68
- assert.equal(hasUatBrowserToolSurface(["read", "mcp__gsd-browser__browser_navigate"]), true);
69
- assert.equal(hasUatBrowserToolSurface(["read", "mcp__gsd-browser__*"]), true);
70
- assert.equal(hasUatBrowserToolSurface(["read", "mcp__browser-uat__*"]), true);
71
- assert.equal(hasUatBrowserToolSurface(["read", "mcp__gsd-workflow__*"]), false);
72
- assert.equal(hasUatBrowserToolSurface(["read", "gsd_uat_exec"]), false);
73
- assert.equal(hasUatBrowserToolSurface(undefined), false);
71
+ it("detects Browser Automation Contract capability across adapters", () => {
72
+ assertBrowserAutomationContractAvailable(BROWSER_AUTOMATION_CONTRACT_TOOLS.piProvider);
73
+ assertBrowserAutomationContractAvailable(BROWSER_AUTOMATION_CONTRACT_TOOLS.externalMcpClient);
74
+ assertBrowserAutomationContractAvailable(BROWSER_AUTOMATION_CONTRACT_TOOLS.externalMcpWildcard);
75
+ assertBrowserAutomationContractAvailable(BROWSER_AUTOMATION_CONTRACT_TOOLS.otherBrowserMcp);
76
+ assertBrowserAutomationContractMissing(BROWSER_AUTOMATION_CONTRACT_TOOLS.workflowOnly);
77
+ assertBrowserAutomationContractMissing(BROWSER_AUTOMATION_CONTRACT_TOOLS.withoutBrowser);
78
+ assertBrowserAutomationContractMissing(undefined);
74
79
  });
75
80
 
76
81
  it("reports missing browser tools only for browser-backed UAT with a known tool snapshot", () => {
@@ -92,26 +97,16 @@ describe("uat-policy", () => {
92
97
  }),
93
98
  null,
94
99
  );
95
- assert.equal(
96
- getUatBrowserToolSupportError({
97
- uatType: "human-experience",
98
- activeTools: ["read", "gsd_uat_exec"],
99
- registeredTools: ["browser_navigate"],
100
- milestoneId: "M001",
101
- sliceId: "S01",
102
- }),
103
- null,
104
- );
105
- assert.equal(
106
- getUatBrowserToolSupportError({
107
- uatType: "human-experience",
108
- activeTools: ["read", "gsd_uat_exec"],
109
- registeredTools: ["mcp__gsd-browser__*"],
110
- milestoneId: "M001",
111
- sliceId: "S01",
112
- }),
113
- null,
114
- );
100
+ assertBrowserBackedUatCanDispatch({
101
+ uatType: "human-experience",
102
+ activeTools: BROWSER_AUTOMATION_CONTRACT_TOOLS.withoutBrowser,
103
+ registeredTools: BROWSER_AUTOMATION_CONTRACT_TOOLS.piProvider,
104
+ });
105
+ assertBrowserBackedUatCanDispatch({
106
+ uatType: "human-experience",
107
+ activeTools: BROWSER_AUTOMATION_CONTRACT_TOOLS.withoutBrowser,
108
+ registeredTools: BROWSER_AUTOMATION_CONTRACT_TOOLS.externalMcpWildcard,
109
+ });
115
110
 
116
111
  const error = getUatBrowserToolSupportError({
117
112
  uatType: "browser-executable",
@@ -0,0 +1,209 @@
1
+ // gsd-pi — ADR-032 Unit Closeout module tests (Interactive Closeout adapter path).
2
+ //
3
+ // All git/preference/notification effects go through the injected deps seam —
4
+ // no real repos, no notification store state.
5
+
6
+ import test from "node:test";
7
+ import assert from "node:assert/strict";
8
+
9
+ import {
10
+ closeUnit,
11
+ isUnitCloseoutTool,
12
+ runInteractiveUnitCloseout,
13
+ type UnitCloseoutDeps,
14
+ } from "../unit-closeout.ts";
15
+
16
+ interface DepsLog {
17
+ commits: Array<{ unitType: string; unitId: string }>;
18
+ notices: Array<{ message: string; severity: string }>;
19
+ }
20
+
21
+ function makeDeps(overrides: {
22
+ isolation?: "none" | "worktree" | "branch";
23
+ branch?: string | null;
24
+ commitResult?: string | null | (() => string | null);
25
+ } = {}): { deps: UnitCloseoutDeps; log: DepsLog } {
26
+ const log: DepsLog = { commits: [], notices: [] };
27
+ const deps: UnitCloseoutDeps = {
28
+ isolationMode: () => overrides.isolation ?? "none",
29
+ currentBranch: () => (overrides.branch === undefined ? "main" : overrides.branch),
30
+ commit: (_basePath, unitType, unitId) => {
31
+ log.commits.push({ unitType, unitId });
32
+ const result = overrides.commitResult;
33
+ if (typeof result === "function") return result();
34
+ return result === undefined ? "chore(gsd): closeout" : result;
35
+ },
36
+ notify: (message, severity) => {
37
+ log.notices.push({ message, severity });
38
+ },
39
+ };
40
+ return { deps, log };
41
+ }
42
+
43
+ const BASE = "/tmp/closeout-test-project";
44
+
45
+ test("task boundary commits and stays quiet", () => {
46
+ const { deps, log } = makeDeps({ isolation: "worktree" });
47
+ const result = closeUnit(
48
+ { basePath: BASE, unitType: "execute-task", unitId: "M001/S01/T01", boundary: "task", outcome: "complete" },
49
+ deps,
50
+ );
51
+ assert.equal(result.gitVerdict, "committed");
52
+ assert.equal(result.notice, undefined);
53
+ assert.deepEqual(log.commits, [{ unitType: "execute-task", unitId: "M001/S01/T01" }]);
54
+ assert.equal(log.notices.length, 0);
55
+ });
56
+
57
+ test("milestone boundary under isolation none commits without a notice", () => {
58
+ const { deps, log } = makeDeps({ isolation: "none" });
59
+ const result = closeUnit(
60
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
61
+ deps,
62
+ );
63
+ assert.equal(result.gitVerdict, "committed");
64
+ assert.equal(log.notices.length, 0);
65
+ });
66
+
67
+ test("milestone boundary off-worktree under isolation worktree fails closed loudly", () => {
68
+ const { deps, log } = makeDeps({ isolation: "worktree", branch: "main" });
69
+ const result = closeUnit(
70
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
71
+ deps,
72
+ );
73
+ assert.equal(result.gitVerdict, "isolation-bypassed");
74
+ assert.equal(log.notices.length, 1);
75
+ assert.equal(log.notices[0].severity, "warning");
76
+ assert.match(log.notices[0].message, /isolation preference was not honoured/);
77
+ assert.match(log.notices[0].message, /git\.isolation is "worktree"/);
78
+ assert.match(log.notices[0].message, /committed directly on "main"/);
79
+ });
80
+
81
+ test("milestone boundary on a milestone branch defers the merge to worktree tooling", () => {
82
+ const { deps, log } = makeDeps({ isolation: "worktree", branch: "milestone/M001" });
83
+ const result = closeUnit(
84
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
85
+ deps,
86
+ );
87
+ assert.equal(result.gitVerdict, "milestone-branch");
88
+ assert.equal(log.notices.length, 1);
89
+ assert.equal(log.notices[0].severity, "info");
90
+ assert.match(log.notices[0].message, /worktree merge/);
91
+ });
92
+
93
+ test("clean tree records nothing-to-commit, and the bypass notice says so", () => {
94
+ const { deps, log } = makeDeps({ isolation: "branch", branch: "main", commitResult: null });
95
+ const result = closeUnit(
96
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
97
+ deps,
98
+ );
99
+ assert.equal(result.gitVerdict, "isolation-bypassed");
100
+ assert.equal(result.commitMessage, null);
101
+ assert.match(log.notices[0].message, /nothing left to commit/);
102
+ });
103
+
104
+ test("commit failure is surfaced, never thrown", () => {
105
+ const { deps, log } = makeDeps({
106
+ commitResult: () => {
107
+ throw new Error("index.lock exists");
108
+ },
109
+ });
110
+ const result = closeUnit(
111
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
112
+ deps,
113
+ );
114
+ assert.equal(result.gitVerdict, "commit-failed");
115
+ assert.equal(log.notices[0].severity, "error");
116
+ assert.match(log.notices[0].message, /index\.lock/);
117
+ });
118
+
119
+ test("re-entrancy is safe: a re-fire over an already-clean tree is nothing-to-commit", () => {
120
+ // No result cache — re-entrancy is absorbed by git itself. The second fire
121
+ // sees a clean tree (commit returns null) and records nothing-to-commit.
122
+ let firstFire = true;
123
+ const { deps, log } = makeDeps({
124
+ isolation: "worktree",
125
+ branch: "main",
126
+ commitResult: () => {
127
+ const committed = firstFire;
128
+ firstFire = false;
129
+ return committed ? "chore(gsd): closeout" : null;
130
+ },
131
+ });
132
+ const request = {
133
+ basePath: BASE,
134
+ unitType: "complete-milestone",
135
+ unitId: "M001",
136
+ boundary: "milestone" as const,
137
+ outcome: "complete" as const,
138
+ };
139
+ const first = closeUnit(request, deps);
140
+ const second = closeUnit(request, deps);
141
+ assert.equal(first.gitVerdict, "isolation-bypassed");
142
+ assert.equal(first.commitMessage, "chore(gsd): closeout");
143
+ assert.equal(second.gitVerdict, "isolation-bypassed");
144
+ assert.equal(second.commitMessage, null);
145
+ assert.match(second.notice ?? "", /nothing left to commit/);
146
+ assert.equal(log.commits.length, 2);
147
+ });
148
+
149
+ // ─── Interactive adapter mapping ──────────────────────────────────────────
150
+
151
+ test("isUnitCloseoutTool recognizes exactly the closeout tools", () => {
152
+ assert.equal(isUnitCloseoutTool("gsd_complete_milestone"), true);
153
+ assert.equal(isUnitCloseoutTool("gsd_save_gate_result"), false);
154
+ assert.equal(isUnitCloseoutTool("read"), false);
155
+ });
156
+
157
+ test("interactive adapter is scoped to milestone boundaries — task/slice tools do not commit", () => {
158
+ const { deps, log } = makeDeps();
159
+ assert.equal(isUnitCloseoutTool("gsd_task_complete"), false);
160
+ assert.equal(isUnitCloseoutTool("gsd_slice_complete"), false);
161
+ assert.equal(
162
+ runInteractiveUnitCloseout(
163
+ { basePath: BASE, canonicalToolName: "gsd_task_complete", input: { milestoneId: "M001", sliceId: "S02", taskId: "T03" } },
164
+ deps,
165
+ ),
166
+ null,
167
+ );
168
+ assert.equal(
169
+ runInteractiveUnitCloseout(
170
+ { basePath: BASE, canonicalToolName: "gsd_slice_complete", input: { milestoneId: "M001", sliceId: "S02" } },
171
+ deps,
172
+ ),
173
+ null,
174
+ );
175
+ assert.equal(log.commits.length, 0);
176
+ });
177
+
178
+ test("interactive adapter maps milestone tool input to canonical unit type", () => {
179
+ const { deps, log } = makeDeps();
180
+ const result = runInteractiveUnitCloseout(
181
+ { basePath: BASE, canonicalToolName: "gsd_complete_milestone", input: { milestoneId: "M001" } },
182
+ deps,
183
+ );
184
+ assert.equal(result?.gitVerdict, "committed");
185
+ assert.deepEqual(log.commits, [{ unitType: "complete-milestone", unitId: "M001" }]);
186
+ });
187
+
188
+ test("interactive adapter accepts snake_case ids and milestone-only input", () => {
189
+ const { deps, log } = makeDeps();
190
+ const result = runInteractiveUnitCloseout(
191
+ { basePath: BASE, canonicalToolName: "gsd_complete_milestone", input: { milestone_id: "M007" } },
192
+ deps,
193
+ );
194
+ assert.equal(result?.gitVerdict, "committed");
195
+ assert.deepEqual(log.commits, [{ unitType: "complete-milestone", unitId: "M007" }]);
196
+ });
197
+
198
+ test("interactive adapter declines unidentifiable input instead of guessing", () => {
199
+ const { deps, log } = makeDeps();
200
+ assert.equal(
201
+ runInteractiveUnitCloseout({ basePath: BASE, canonicalToolName: "gsd_complete_milestone", input: {} }, deps),
202
+ null,
203
+ );
204
+ assert.equal(
205
+ runInteractiveUnitCloseout({ basePath: BASE, canonicalToolName: "not_a_closeout_tool", input: { milestoneId: "M001" } }, deps),
206
+ null,
207
+ );
208
+ assert.equal(log.commits.length, 0);
209
+ });
@@ -11,6 +11,7 @@ import {
11
11
  composeContractedUnitContext,
12
12
  composeContextModeInstructions,
13
13
  composeInlinedContext,
14
+ composeToolSurfaceInstructions,
14
15
  composeUnitContext,
15
16
  manifestBudgetChars,
16
17
  type ArtifactResolver,
@@ -24,6 +25,7 @@ import type {
24
25
  UnitContextManifest,
25
26
  } from "../unit-context-manifest.ts";
26
27
  import { KNOWN_UNIT_TYPES, UNIT_MANIFESTS } from "../unit-context-manifest.ts";
28
+ import { getUnitToolSurfaceContract } from "../unit-tool-contracts.ts";
27
29
  import {
28
30
  buildExecuteTaskPrompt,
29
31
  buildGateEvaluatePrompt,
@@ -165,12 +167,32 @@ test("Context Mode composer: every known eligible unit renders its configured la
165
167
  }
166
168
  assert.ok(out.startsWith("## Context Mode"), `${unitType} should render standalone Context Mode heading`);
167
169
  assert.match(out, new RegExp(`Lane: \\*\\*${laneLabelByMode[manifest.contextMode]} lane\\*\\*\\.`, "i"));
168
- assert.match(out, /`gsd_exec`/, `${unitType} should mention gsd_exec`);
169
- assert.match(out, /`gsd_exec_search`/, `${unitType} should mention gsd_exec_search`);
170
+ const forbidden = getUnitToolSurfaceContract(unitType)?.forbiddenGsdTools ?? {};
171
+ if ("gsd_exec" in forbidden) {
172
+ // Units that forbid gsd_exec (run-uat) have it stripped from their
173
+ // Claude Code dispatch surface; guidance steering to it produces
174
+ // "No such tool available" loops in the dispatched agent.
175
+ assert.doesNotMatch(out, /`gsd_exec`/, `${unitType} forbids gsd_exec; guidance must not steer to it`);
176
+ assert.doesNotMatch(out, /`gsd_exec_search`/, `${unitType} guidance must not steer to gsd_exec_search`);
177
+ assert.match(out, /`gsd_uat_exec`/, `${unitType} guidance should steer to gsd_uat_exec instead`);
178
+ } else {
179
+ assert.match(out, /`gsd_exec`/, `${unitType} should mention gsd_exec`);
180
+ assert.match(out, /`gsd_exec_search`/, `${unitType} should mention gsd_exec_search`);
181
+ }
170
182
  assert.match(out, /`gsd_resume`/, `${unitType} should mention gsd_resume`);
171
183
  }
172
184
  });
173
185
 
186
+ test("Context Mode composer: run-uat guidance steers to gsd_uat_exec in both render modes", () => {
187
+ const nested = composeContextModeInstructions("run-uat", { enabled: true, renderMode: "nested" });
188
+ assert.match(nested, /^Context Mode \(verification lane\): /);
189
+ assert.match(nested, /`gsd_uat_exec`/);
190
+ assert.doesNotMatch(nested, /`gsd_exec`/);
191
+ const standalone = composeContextModeInstructions("run-uat", { enabled: true, renderMode: "standalone" });
192
+ assert.match(standalone, /`gsd_uat_exec`/);
193
+ assert.doesNotMatch(standalone, /`gsd_exec`/);
194
+ });
195
+
174
196
  test("Context Mode composer: workflow-preferences and research-decision render no Context Mode block", () => {
175
197
  assert.strictEqual(
176
198
  composeContextModeInstructions("workflow-preferences", { enabled: true, renderMode: "standalone" }),
@@ -182,6 +204,49 @@ test("Context Mode composer: workflow-preferences and research-decision render n
182
204
  );
183
205
  });
184
206
 
207
+ test("Tool Surface composer: run-uat forbids gsd_exec and Bash", () => {
208
+ const out = composeToolSurfaceInstructions("run-uat", { renderMode: "standalone" });
209
+ assert.match(out, /^## Tool Surface/);
210
+ assert.match(out, /Do not call `gsd_exec`/);
211
+ assert.match(out, /`Bash`/);
212
+ assert.match(out, /`gsd_uat_exec`/);
213
+ assert.match(out, /`gsd_save_gate_result`/);
214
+ assert.match(out, /`gsd_summary_save`/);
215
+ });
216
+
217
+ test("Tool Surface composer: complete-slice steers verification to gsd_exec", () => {
218
+ const out = composeToolSurfaceInstructions("complete-slice", { renderMode: "standalone" });
219
+ assert.match(out, /`gsd_exec`/);
220
+ assert.match(out, /not direct `bash`/);
221
+ assert.match(out, /`gsd_uat_result_save`/);
222
+ });
223
+
224
+ test("Tool Surface composer: planning units restrict writes to .gsd", () => {
225
+ const out = composeToolSurfaceInstructions("discuss-milestone", { renderMode: "standalone" });
226
+ assert.match(out, /restricted to `\.gsd\/\*\*`/);
227
+ assert.match(out, /`ask_user_questions`/);
228
+ });
229
+
230
+ test("Tool Surface composer: planning-dispatch lists allowed subagents", () => {
231
+ const out = composeToolSurfaceInstructions("plan-slice", { renderMode: "standalone" });
232
+ assert.match(out, /\*\*scout\*\*/);
233
+ assert.match(out, /\*\*planner\*\*/);
234
+ });
235
+
236
+ test("Tool Surface composer: execute-task warns against slice/milestone closeout tools", () => {
237
+ const out = composeToolSurfaceInstructions("execute-task", { renderMode: "nested" });
238
+ assert.match(out, /^Tool surface: /);
239
+ assert.match(out, /`gsd_task_complete`/);
240
+ assert.match(out, /Do not call `gsd_slice_complete`/);
241
+ });
242
+
243
+ test("Tool Surface composer: unknown unit renders empty block", () => {
244
+ assert.strictEqual(
245
+ composeToolSurfaceInstructions("never-dispatched", { renderMode: "standalone" }),
246
+ "",
247
+ );
248
+ });
249
+
185
250
  // ─── Integration: migrated buildReassessRoadmapPrompt ─────────────────────
186
251
 
187
252
  function makeFixtureBase(): string {