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

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 (551) 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 +14 -34
  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/GSD-WORKFLOW.md +5 -4
  11. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  12. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  13. package/dist/resources/extensions/async-jobs/index.js +65 -0
  14. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  15. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  16. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  17. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  18. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  19. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  20. package/dist/resources/extensions/bg-shell/utilities.js +5 -2
  21. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  22. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  23. package/dist/resources/extensions/browser-tools/index.js +69 -12
  24. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  25. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +38 -6
  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 +105 -0
  29. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  30. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  31. package/dist/resources/extensions/gsd/auto/orchestrator.js +94 -48
  32. package/dist/resources/extensions/gsd/auto/phases.js +8 -3
  33. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +8 -32
  34. package/dist/resources/extensions/gsd/auto-dispatch.js +40 -57
  35. package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
  36. package/dist/resources/extensions/gsd/auto-post-unit.js +31 -14
  37. package/dist/resources/extensions/gsd/auto-prompts.js +81 -19
  38. package/dist/resources/extensions/gsd/auto-start.js +24 -26
  39. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  40. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +12 -20
  41. package/dist/resources/extensions/gsd/auto-verification.js +9 -28
  42. package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
  43. package/dist/resources/extensions/gsd/auto-worktree.js +35 -352
  44. package/dist/resources/extensions/gsd/auto.js +8 -20
  45. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
  46. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -12
  47. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  48. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +229 -36
  49. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +319 -71
  50. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  51. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  52. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  53. package/dist/resources/extensions/gsd/captures.js +5 -15
  54. package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
  55. package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
  56. package/dist/resources/extensions/gsd/consent-question.js +337 -0
  57. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  58. package/dist/resources/extensions/gsd/constants.js +0 -2
  59. package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
  60. package/dist/resources/extensions/gsd/db/engine.js +755 -0
  61. package/dist/resources/extensions/gsd/db/queries.js +398 -0
  62. package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
  63. package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
  64. package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
  65. package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
  66. package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
  67. package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
  68. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  69. package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
  70. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  71. package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
  72. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
  73. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  74. package/dist/resources/extensions/gsd/error-classifier.js +9 -0
  75. package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
  76. package/dist/resources/extensions/gsd/files.js +33 -19
  77. package/dist/resources/extensions/gsd/git-service.js +1 -0
  78. package/dist/resources/extensions/gsd/gitignore.js +3 -0
  79. package/dist/resources/extensions/gsd/gsd-db.js +171 -2048
  80. package/dist/resources/extensions/gsd/guidance.js +158 -0
  81. package/dist/resources/extensions/gsd/guided-flow.js +51 -5
  82. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  83. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  84. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  85. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  86. package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
  87. package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
  88. package/dist/resources/extensions/gsd/milestone-closeout.js +13 -23
  89. package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
  90. package/dist/resources/extensions/gsd/model-router.js +3 -0
  91. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  92. package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
  93. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
  94. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  95. package/dist/resources/extensions/gsd/paths.js +37 -24
  96. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  97. package/dist/resources/extensions/gsd/preferences-models.js +14 -48
  98. package/dist/resources/extensions/gsd/preferences.js +14 -0
  99. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  100. package/dist/resources/extensions/gsd/prompts/plan-slice.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/run-uat.md +6 -4
  104. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  105. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  106. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  107. package/dist/resources/extensions/gsd/publication.js +87 -0
  108. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  109. package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
  110. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  111. package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
  112. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
  113. package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
  114. package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
  115. package/dist/resources/extensions/gsd/state.js +6 -20
  116. package/dist/resources/extensions/gsd/status-guards.js +56 -8
  117. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  118. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  119. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  120. package/dist/resources/extensions/gsd/tools/complete-slice.js +44 -53
  121. package/dist/resources/extensions/gsd/tools/exec-tool.js +10 -8
  122. package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
  123. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
  124. package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
  125. package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
  126. package/dist/resources/extensions/gsd/uat-policy.js +42 -16
  127. package/dist/resources/extensions/gsd/undo.js +8 -7
  128. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  129. package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
  130. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  131. package/dist/resources/extensions/gsd/unit-registry.js +337 -0
  132. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  133. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  134. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  135. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  136. package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
  137. package/dist/resources/extensions/gsd/worktree-lifecycle.js +12 -3
  138. package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
  139. package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
  140. package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
  141. package/dist/resources/extensions/gsd/worktree-root.js +28 -6
  142. package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
  143. package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
  144. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  145. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  146. package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
  147. package/dist/resources/shared/package.json +3 -0
  148. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  149. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  150. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  151. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  152. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  153. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  154. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  155. package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
  156. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  157. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  158. package/dist/web/standalone/.next/BUILD_ID +1 -1
  159. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  160. package/dist/web/standalone/.next/build-manifest.json +3 -3
  161. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  162. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  163. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  164. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  165. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  166. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  167. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  168. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  169. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  170. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  171. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  172. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  173. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  174. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  176. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  177. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  178. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  179. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  180. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  182. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  184. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  186. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  188. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  190. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  191. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  192. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  194. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  195. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  197. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  198. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  200. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  201. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  202. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  203. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  204. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  205. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  206. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  207. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  208. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  209. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  210. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  211. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  212. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  214. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  215. package/dist/web/standalone/.next/server/app/index.html +1 -1
  216. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  217. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  218. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  219. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  220. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  221. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  222. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  223. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  224. package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
  225. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  226. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  227. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  228. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  229. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  230. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  231. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  232. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  233. package/dist/web/standalone/package.json +1 -1
  234. package/dist/worktree-cli.js +3 -6
  235. package/dist/worktree-status-banner.js +7 -11
  236. package/package.json +1 -1
  237. package/packages/cloud-mcp-gateway/package.json +2 -2
  238. package/packages/contracts/dist/rpc.d.ts +1 -0
  239. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  240. package/packages/contracts/dist/rpc.js.map +1 -1
  241. package/packages/contracts/dist/workflow.d.ts +4 -0
  242. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  243. package/packages/contracts/dist/workflow.js.map +1 -1
  244. package/packages/contracts/package.json +1 -1
  245. package/packages/daemon/package.json +4 -4
  246. package/packages/gsd-agent-core/package.json +5 -5
  247. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  248. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  249. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +8 -0
  250. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  251. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  252. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  253. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  254. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  255. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  256. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  257. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  258. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  259. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  260. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  261. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  262. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  263. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  264. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  265. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  266. package/packages/gsd-agent-modes/package.json +7 -7
  267. package/packages/mcp-server/dist/cli.js +6 -3
  268. package/packages/mcp-server/dist/cli.js.map +1 -1
  269. package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
  270. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  271. package/packages/mcp-server/dist/workflow-tools.js +46 -21
  272. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  273. package/packages/mcp-server/package.json +3 -3
  274. package/packages/native/package.json +1 -1
  275. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  276. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  277. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  278. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  279. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  280. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  281. package/packages/pi-agent-core/dist/index.js +3 -0
  282. package/packages/pi-agent-core/dist/index.js.map +1 -1
  283. package/packages/pi-agent-core/package.json +1 -1
  284. package/packages/pi-ai/README.md +1 -0
  285. package/packages/pi-ai/dist/models.generated.d.ts +192 -0
  286. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  287. package/packages/pi-ai/dist/models.generated.js +166 -0
  288. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  289. package/packages/pi-ai/package.json +3 -2
  290. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  291. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  293. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  294. package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
  296. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  299. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  301. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  303. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  305. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/index.js +1 -1
  307. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  309. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  311. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  312. package/packages/pi-coding-agent/package.json +7 -7
  313. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  314. package/packages/pi-tui/dist/tui.js +9 -0
  315. package/packages/pi-tui/dist/tui.js.map +1 -1
  316. package/packages/pi-tui/package.json +2 -2
  317. package/packages/rpc-client/package.json +2 -2
  318. package/pkg/package.json +1 -1
  319. package/src/resources/GSD-WORKFLOW.md +5 -4
  320. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  321. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  322. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  323. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  324. package/src/resources/extensions/async-jobs/index.ts +79 -0
  325. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  326. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  327. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  328. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  329. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  330. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  331. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  332. package/src/resources/extensions/bg-shell/utilities.ts +5 -2
  333. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  334. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  335. package/src/resources/extensions/browser-tools/index.ts +71 -13
  336. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  337. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
  338. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  339. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  340. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +40 -4
  341. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
  342. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  343. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  344. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  345. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  346. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
  347. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  348. package/src/resources/extensions/gsd/auto/orchestrator.ts +109 -51
  349. package/src/resources/extensions/gsd/auto/phases.ts +12 -3
  350. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -32
  351. package/src/resources/extensions/gsd/auto-dispatch.ts +38 -52
  352. package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
  353. package/src/resources/extensions/gsd/auto-post-unit.ts +37 -13
  354. package/src/resources/extensions/gsd/auto-prompts.ts +118 -35
  355. package/src/resources/extensions/gsd/auto-start.ts +24 -29
  356. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  357. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +14 -21
  358. package/src/resources/extensions/gsd/auto-verification.ts +8 -26
  359. package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
  360. package/src/resources/extensions/gsd/auto-worktree.ts +41 -364
  361. package/src/resources/extensions/gsd/auto.ts +20 -24
  362. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
  363. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +33 -12
  364. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  365. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +270 -37
  366. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +368 -78
  367. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  368. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  369. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  370. package/src/resources/extensions/gsd/captures.ts +5 -16
  371. package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
  372. package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
  373. package/src/resources/extensions/gsd/consent-question.ts +416 -0
  374. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  375. package/src/resources/extensions/gsd/constants.ts +0 -3
  376. package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
  377. package/src/resources/extensions/gsd/db/engine.ts +809 -0
  378. package/src/resources/extensions/gsd/db/queries.ts +490 -0
  379. package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
  380. package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
  381. package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
  382. package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
  383. package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
  384. package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
  385. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  386. package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
  387. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  388. package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
  389. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
  390. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  391. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  392. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  393. package/src/resources/extensions/gsd/files.ts +33 -12
  394. package/src/resources/extensions/gsd/git-service.ts +1 -0
  395. package/src/resources/extensions/gsd/gitignore.ts +3 -0
  396. package/src/resources/extensions/gsd/gsd-db.ts +173 -2373
  397. package/src/resources/extensions/gsd/guidance.ts +217 -0
  398. package/src/resources/extensions/gsd/guided-flow.ts +50 -5
  399. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  400. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  401. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  402. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  403. package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
  404. package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
  405. package/src/resources/extensions/gsd/milestone-closeout.ts +13 -23
  406. package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
  407. package/src/resources/extensions/gsd/model-router.ts +3 -0
  408. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  409. package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
  410. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
  411. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  412. package/src/resources/extensions/gsd/paths.ts +42 -22
  413. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  414. package/src/resources/extensions/gsd/preferences-models.ts +12 -47
  415. package/src/resources/extensions/gsd/preferences.ts +18 -0
  416. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  417. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  418. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  419. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  420. package/src/resources/extensions/gsd/prompts/run-uat.md +6 -4
  421. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  422. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  423. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  424. package/src/resources/extensions/gsd/publication.ts +122 -0
  425. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  426. package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
  427. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  428. package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
  429. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
  430. package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
  431. package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
  432. package/src/resources/extensions/gsd/state.ts +9 -21
  433. package/src/resources/extensions/gsd/status-guards.ts +59 -8
  434. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  435. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
  436. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
  437. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +101 -26
  438. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
  439. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
  440. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
  441. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
  442. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  443. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  444. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  445. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  446. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
  447. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  448. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  449. package/src/resources/extensions/gsd/tests/consent-question.test.ts +336 -0
  450. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  451. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  452. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  453. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  454. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  455. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  456. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  457. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
  458. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  459. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  460. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  461. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
  462. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  463. package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
  464. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +58 -15
  465. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +74 -59
  466. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  467. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  468. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  469. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  470. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
  471. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  472. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  473. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  474. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  475. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +139 -0
  476. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  477. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  478. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  479. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  480. package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
  481. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +248 -1
  482. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
  483. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
  484. package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
  485. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
  486. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
  487. package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
  488. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  489. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  490. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  491. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  492. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
  493. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  494. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
  495. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  496. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  497. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  498. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
  499. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
  500. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
  501. package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
  502. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
  503. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
  504. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
  505. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
  506. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  507. package/src/resources/extensions/gsd/tests/write-gate.test.ts +109 -1
  508. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  509. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  510. package/src/resources/extensions/gsd/tools/complete-slice.ts +43 -68
  511. package/src/resources/extensions/gsd/tools/exec-tool.ts +9 -8
  512. package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
  513. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
  514. package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
  515. package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
  516. package/src/resources/extensions/gsd/uat-policy.ts +62 -16
  517. package/src/resources/extensions/gsd/undo.ts +9 -8
  518. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  519. package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
  520. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  521. package/src/resources/extensions/gsd/unit-registry.ts +412 -0
  522. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  523. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  524. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  525. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  526. package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
  527. package/src/resources/extensions/gsd/worktree-lifecycle.ts +13 -9
  528. package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
  529. package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
  530. package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
  531. package/src/resources/extensions/gsd/worktree-root.ts +29 -6
  532. package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
  533. package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
  534. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  535. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  536. package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
  537. package/src/resources/shared/package.json +3 -0
  538. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  539. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  540. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  541. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  542. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  543. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  544. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  545. package/src/resources/skills/gsd-browser/SKILL.md +1 -1
  546. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  547. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  548. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  549. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  550. /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → jmTLg6xZmAuq_LIqKOxrH}/_buildManifest.js +0 -0
  551. /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → jmTLg6xZmAuq_LIqKOxrH}/_ssgManifest.js +0 -0
@@ -5,6 +5,8 @@ import {
5
5
  STATE_TRANSITION_MATRIX,
6
6
  findTransition,
7
7
  validateTransitionMatrix,
8
+ isLegalEdge,
9
+ IllegalPhaseTransitionError,
8
10
  } from "../state-transition-matrix.ts";
9
11
 
10
12
  test("state transition matrix covers required swarm hardening events", () => {
@@ -42,3 +44,37 @@ test("state transition matrix entries all have guard and reason codes", () => {
42
44
  assert.ok(entry.reasonCode.length > 0, `${entry.event} must include reason code`);
43
45
  }
44
46
  });
47
+
48
+ // ─── ADR-030: Phase Transition Invariant ───────────────────────────────────
49
+
50
+ test("isLegalEdge treats a self-edge as trivially legal", () => {
51
+ assert.equal(isLegalEdge("executing", "executing"), true);
52
+ assert.equal(isLegalEdge("planning", "planning"), true);
53
+ });
54
+
55
+ test("isLegalEdge accepts edges enumerated in the matrix", () => {
56
+ assert.equal(isLegalEdge("planning", "executing"), true);
57
+ assert.equal(isLegalEdge("executing", "summarizing"), true);
58
+ assert.equal(isLegalEdge("summarizing", "validating-milestone"), true);
59
+ assert.equal(isLegalEdge("completing-milestone", "complete"), true);
60
+ });
61
+
62
+ test("isLegalEdge honors the * wildcard rows (any -> blocked, any -> executing)", () => {
63
+ assert.equal(isLegalEdge("planning", "blocked"), true);
64
+ assert.equal(isLegalEdge("summarizing", "executing"), true);
65
+ });
66
+
67
+ test("isLegalEdge rejects an edge no matrix entry permits", () => {
68
+ // executing -> complete skips validation — exactly the illegal jump the
69
+ // invariant exists to catch.
70
+ assert.equal(isLegalEdge("executing", "complete"), false);
71
+ assert.equal(isLegalEdge("planning", "summarizing"), false);
72
+ });
73
+
74
+ test("IllegalPhaseTransitionError carries both endpoints and a descriptive message", () => {
75
+ const err = new IllegalPhaseTransitionError("executing", "complete");
76
+ assert.equal(err.from, "executing");
77
+ assert.equal(err.to, "complete");
78
+ assert.equal(err.name, "IllegalPhaseTransitionError");
79
+ assert.match(err.message, /executing -> complete/);
80
+ });
@@ -9,7 +9,10 @@ import {
9
9
  isDeferredStatus,
10
10
  isInactiveStatus,
11
11
  isSkippedForDispatch,
12
+ toStatus,
13
+ RAW_CLOSED_STATUSES,
12
14
  } from '../status-guards.ts';
15
+ import { TERMINAL_STATUS_SQL } from '../db/sql-constants.ts';
13
16
 
14
17
  test('isClosedStatus: "complete" returns true', () => {
15
18
  assert.equal(isClosedStatus('complete'), true);
@@ -95,3 +98,38 @@ test('isSkippedForDispatch does NOT skip pending/active/planned', () => {
95
98
  assert.equal(isSkippedForDispatch(s), false, `${s} should block dispatch ordering`);
96
99
  }
97
100
  });
101
+
102
+ // ─── ADR-030: canonical Status vocabulary + normalization ──────────────────
103
+
104
+ test('toStatus passes canonical values through unchanged', () => {
105
+ for (const s of ['pending', 'queued', 'active', 'parked', 'in_progress', 'blocked', 'complete', 'skipped', 'deferred']) {
106
+ assert.equal(toStatus(s), s, `${s} is canonical and should be returned verbatim`);
107
+ }
108
+ });
109
+
110
+ test('toStatus maps known aliases to canonical', () => {
111
+ assert.equal(toStatus('done'), 'complete');
112
+ assert.equal(toStatus('closed'), 'complete');
113
+ assert.equal(toStatus('planned'), 'pending');
114
+ assert.equal(toStatus('in-progress'), 'in_progress');
115
+ });
116
+
117
+ test('toStatus trims surrounding whitespace before matching', () => {
118
+ assert.equal(toStatus(' complete '), 'complete');
119
+ assert.equal(toStatus(' done '), 'complete');
120
+ });
121
+
122
+ test('toStatus quarantines unknown values verbatim (tolerant read, no throw)', () => {
123
+ assert.equal(toStatus('weird-legacy-value'), 'weird-legacy-value');
124
+ });
125
+
126
+ test('RAW_CLOSED_STATUSES is the single source: every member is closed', () => {
127
+ for (const s of RAW_CLOSED_STATUSES) {
128
+ assert.equal(isClosedStatus(s), true, `${s} is in RAW_CLOSED_STATUSES so must be closed`);
129
+ }
130
+ });
131
+
132
+ test('TERMINAL_STATUS_SQL is derived from RAW_CLOSED_STATUSES and renders identically', () => {
133
+ assert.equal(TERMINAL_STATUS_SQL, "'complete', 'done', 'skipped', 'closed'");
134
+ assert.equal(TERMINAL_STATUS_SQL, RAW_CLOSED_STATUSES.map((s) => `'${s}'`).join(', '));
135
+ });
@@ -0,0 +1,70 @@
1
+ // GSD Extension — Stop Notice module tests
2
+ // Locks the emitter↔detector round-trip: every notice the formatters produce
3
+ // must be recognized by the classifiers the headless host uses for exit codes.
4
+
5
+ import { describe, test } from "node:test";
6
+ import assert from "node:assert/strict";
7
+
8
+ import {
9
+ formatStopNoticePrefix,
10
+ isBlockedStopReason,
11
+ stopNoticeDisplayReason,
12
+ stopNoticeKind,
13
+ isTerminalNotice,
14
+ isPauseNotice,
15
+ isBlockedNoticeMessage,
16
+ isManualResolutionNotice,
17
+ PAUSED_NOTICE_PREFIXES,
18
+ TERMINAL_NOTICE_PREFIXES,
19
+ } from "../stop-notice.js";
20
+
21
+ describe("stop notice formatting", () => {
22
+ test("plain stop has no reason suffix", () => {
23
+ assert.equal(formatStopNoticePrefix(), "Auto-mode stopped");
24
+ assert.equal(formatStopNoticePrefix(null), "Auto-mode stopped");
25
+ });
26
+
27
+ test("reason is appended after an em-dash", () => {
28
+ assert.equal(formatStopNoticePrefix("user request"), "Auto-mode stopped — user request");
29
+ });
30
+
31
+ test("Blocked: marker switches the prefix and is stripped from display", () => {
32
+ assert.equal(formatStopNoticePrefix("Blocked: validation gate"), "Auto-mode blocked — validation gate");
33
+ assert.equal(stopNoticeKind("Blocked: x"), "blocked");
34
+ assert.equal(stopNoticeKind("stop"), "stopped");
35
+ assert.ok(isBlockedStopReason("blocked: lowercase too"));
36
+ assert.equal(stopNoticeDisplayReason("Blocked: spaced "), "spaced");
37
+ });
38
+ });
39
+
40
+ describe("emitter↔detector round-trip", () => {
41
+ test("formatted stop notices classify as terminal", () => {
42
+ for (const reason of [undefined, "user request"]) {
43
+ const message = formatStopNoticePrefix(reason).toLowerCase();
44
+ assert.ok(isTerminalNotice(message), `not terminal: ${message}`);
45
+ }
46
+ });
47
+
48
+ test("pause prefixes classify as pause and as blocked (operator intervention)", () => {
49
+ for (const prefix of PAUSED_NOTICE_PREFIXES) {
50
+ assert.ok(isPauseNotice(`${prefix}: provider error`));
51
+ assert.ok(isBlockedNoticeMessage(`${prefix}: provider error`));
52
+ }
53
+ });
54
+
55
+ test("idempotent-advance pauses are non-blocking", () => {
56
+ assert.equal(isBlockedNoticeMessage("auto-mode paused (idempotent advance: unit already active)"), false);
57
+ });
58
+
59
+ test("manual-resolution notices classify as blocked", () => {
60
+ const message = "merge conflict — resolve manually and re-run /gsd auto";
61
+ assert.ok(isManualResolutionNotice(message));
62
+ assert.ok(isBlockedNoticeMessage(message));
63
+ });
64
+
65
+ test("terminal prefixes cover the known stop vocabulary", () => {
66
+ for (const message of ["auto-mode stopped.", "auto-mode complete", "auto-mode idle", "no active milestone"]) {
67
+ assert.ok(TERMINAL_NOTICE_PREFIXES.some((prefix) => message.startsWith(prefix)), message);
68
+ }
69
+ });
70
+ });
@@ -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
+ });
@@ -3,9 +3,9 @@ import assert from "node:assert/strict";
3
3
 
4
4
  import {
5
5
  classifyUatContent,
6
+ classifyUatContentForRun,
6
7
  getDeclaredUatType,
7
8
  getUatBrowserToolSupportError,
8
- hasUatBrowserToolSurface,
9
9
  isPartialEligibleUatType,
10
10
  resolveEffectiveUatType,
11
11
  shouldDispatchUatForContent,
@@ -13,12 +13,104 @@ import {
13
13
  uatTypeIncludesBrowser,
14
14
  validateUatModePolicy,
15
15
  } from "../uat-policy.ts";
16
+ import {
17
+ assertBrowserAutomationContractAvailable,
18
+ assertBrowserAutomationContractMissing,
19
+ assertBrowserBackedUatCanDispatch,
20
+ BROWSER_AUTOMATION_CONTRACT_TOOLS,
21
+ } from "./browser-automation-contract-fixture.ts";
16
22
 
17
23
  describe("uat-policy", () => {
18
24
  it("defaults missing UAT mode to artifact-driven", () => {
19
25
  assert.equal(getDeclaredUatType("# UAT\n\nCheck generated files."), "artifact-driven");
20
26
  });
21
27
 
28
+ it("parses a bare keyword under ## UAT Type (M006/S01 agent format drift)", () => {
29
+ const content = [
30
+ "# S01 UAT",
31
+ "",
32
+ "## UAT Type",
33
+ "browser-executable",
34
+ "",
35
+ "## Preconditions",
36
+ "- Run `node tests/browser/search-uat.mjs` (it starts its own server on an ephemeral port; do not start serve-static separately).",
37
+ ].join("\n");
38
+ assert.equal(getDeclaredUatType(content), "browser-executable");
39
+ assert.equal(shouldEscalateArtifactUatToBrowser(content), false);
40
+ });
41
+
42
+ it("promotes browser-executable UAT when slice context names test:uat but UAT only documents test:server (M007/S01)", () => {
43
+ const uatFile = [
44
+ "# S01 UAT",
45
+ "",
46
+ "## UAT Type",
47
+ "- UAT mode: browser-executable",
48
+ "",
49
+ "## Preconditions",
50
+ "- Start the dev/local verification server with `npm run test:server`.",
51
+ "- Open the app at the localhost URL printed by the server.",
52
+ ].join("\n");
53
+ const sliceContext = [
54
+ "Fresh slice-level verification ran via `gsd_exec` with `npm run test:uat` and passed.",
55
+ "The run produced PASS with browser diagnostics consoleErrors=0.",
56
+ ].join("\n");
57
+
58
+ assert.equal(classifyUatContentForRun(uatFile, sliceContext).effectiveType, "runtime-executable");
59
+ assert.equal(classifyUatContentForRun(uatFile).effectiveType, "browser-executable");
60
+ });
61
+
62
+ it("promotes browser-executable UAT to runtime-executable when a self-contained harness is named (M006/S01)", () => {
63
+ const content = [
64
+ "# S01 UAT",
65
+ "",
66
+ "## UAT Type",
67
+ "- UAT mode: browser-executable",
68
+ "",
69
+ "## Preconditions",
70
+ "- Start the local app server with `npm run start`.",
71
+ "- Open the app at `http://127.0.0.1:4173`.",
72
+ "",
73
+ "## Evidence",
74
+ "- Fresh closeout verification command: `node --check app.js && node --check tests/browser/search-uat.mjs && npm run test:uat`",
75
+ ].join("\n");
76
+
77
+ assert.equal(resolveEffectiveUatType(content), "runtime-executable");
78
+ assert.deepEqual(classifyUatContent(content), {
79
+ declaredType: "browser-executable",
80
+ modeDeclared: true,
81
+ effectiveType: "runtime-executable",
82
+ browserRequired: false,
83
+ shouldDispatchByDefault: true,
84
+ });
85
+ });
86
+
87
+ it("parses a UAT mode line case-insensitively with bold markers", () => {
88
+ const content = [
89
+ "## UAT Type",
90
+ "- **UAT Mode:** Runtime-Executable (npx playwright test)",
91
+ ].join("\n");
92
+ assert.equal(getDeclaredUatType(content), "runtime-executable");
93
+ });
94
+
95
+ it("does not parse prose in the section as a mode declaration", () => {
96
+ const content = [
97
+ "## UAT Type",
98
+ "- Why this mode is sufficient: static checks cover the schema.",
99
+ ].join("\n");
100
+ assert.equal(getDeclaredUatType(content), "artifact-driven");
101
+ });
102
+
103
+ it("treats an explicit UAT mode line with an unrecognised value as undeclared", () => {
104
+ const content = [
105
+ "## UAT Type",
106
+ "- UAT mode: manual-spot-check",
107
+ "- browser-executable would also work",
108
+ ].join("\n");
109
+ // The explicit declaration wins (and fails to parse) — the stray keyword
110
+ // bullet below it must not be promoted to the declared mode.
111
+ assert.equal(getDeclaredUatType(content), "artifact-driven");
112
+ });
113
+
22
114
  it("escalates artifact-driven UAT to browser-executable when the spec requires browser work", () => {
23
115
  const content = [
24
116
  "## UAT Type",
@@ -33,6 +125,7 @@ describe("uat-policy", () => {
33
125
  assert.equal(shouldDispatchUatForContent(content, undefined), true);
34
126
  assert.deepEqual(classifyUatContent(content), {
35
127
  declaredType: "artifact-driven",
128
+ modeDeclared: true,
36
129
  effectiveType: "browser-executable",
37
130
  browserRequired: true,
38
131
  shouldDispatchByDefault: true,
@@ -63,14 +156,14 @@ describe("uat-policy", () => {
63
156
  }
64
157
  });
65
158
 
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);
159
+ it("detects Browser Automation Contract capability across adapters", () => {
160
+ assertBrowserAutomationContractAvailable(BROWSER_AUTOMATION_CONTRACT_TOOLS.piProvider);
161
+ assertBrowserAutomationContractAvailable(BROWSER_AUTOMATION_CONTRACT_TOOLS.externalMcpClient);
162
+ assertBrowserAutomationContractAvailable(BROWSER_AUTOMATION_CONTRACT_TOOLS.externalMcpWildcard);
163
+ assertBrowserAutomationContractAvailable(BROWSER_AUTOMATION_CONTRACT_TOOLS.otherBrowserMcp);
164
+ assertBrowserAutomationContractMissing(BROWSER_AUTOMATION_CONTRACT_TOOLS.workflowOnly);
165
+ assertBrowserAutomationContractMissing(BROWSER_AUTOMATION_CONTRACT_TOOLS.withoutBrowser);
166
+ assertBrowserAutomationContractMissing(undefined);
74
167
  });
75
168
 
76
169
  it("reports missing browser tools only for browser-backed UAT with a known tool snapshot", () => {
@@ -92,26 +185,16 @@ describe("uat-policy", () => {
92
185
  }),
93
186
  null,
94
187
  );
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
- );
188
+ assertBrowserBackedUatCanDispatch({
189
+ uatType: "human-experience",
190
+ activeTools: BROWSER_AUTOMATION_CONTRACT_TOOLS.withoutBrowser,
191
+ registeredTools: BROWSER_AUTOMATION_CONTRACT_TOOLS.piProvider,
192
+ });
193
+ assertBrowserBackedUatCanDispatch({
194
+ uatType: "human-experience",
195
+ activeTools: BROWSER_AUTOMATION_CONTRACT_TOOLS.withoutBrowser,
196
+ registeredTools: BROWSER_AUTOMATION_CONTRACT_TOOLS.externalMcpWildcard,
197
+ });
115
198
 
116
199
  const error = getUatBrowserToolSupportError({
117
200
  uatType: "browser-executable",