@opengsd/gsd-pi 1.2.0-dev.955e4da0 → 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 (424) 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 +3 -0
  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/stream-adapter.js +30 -4
  25. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  26. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  27. package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
  28. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  29. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  30. package/dist/resources/extensions/gsd/auto/orchestrator.js +61 -44
  31. package/dist/resources/extensions/gsd/auto/phases.js +2 -2
  32. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +8 -32
  33. package/dist/resources/extensions/gsd/auto-dispatch.js +40 -57
  34. package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
  35. package/dist/resources/extensions/gsd/auto-post-unit.js +23 -8
  36. package/dist/resources/extensions/gsd/auto-prompts.js +81 -19
  37. package/dist/resources/extensions/gsd/auto-start.js +18 -15
  38. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  39. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +12 -20
  40. package/dist/resources/extensions/gsd/auto-verification.js +9 -28
  41. package/dist/resources/extensions/gsd/auto-worktree.js +30 -90
  42. package/dist/resources/extensions/gsd/auto.js +4 -13
  43. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
  44. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
  45. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  46. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +212 -48
  47. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +303 -77
  48. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  49. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  50. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  51. package/dist/resources/extensions/gsd/captures.js +4 -6
  52. package/dist/resources/extensions/gsd/consent-question.js +337 -0
  53. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  54. package/dist/resources/extensions/gsd/constants.js +0 -2
  55. package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
  56. package/dist/resources/extensions/gsd/db/queries.js +26 -0
  57. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  58. package/dist/resources/extensions/gsd/doctor-environment.js +2 -6
  59. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  60. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +13 -15
  61. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  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/files.js +33 -19
  65. package/dist/resources/extensions/gsd/guidance.js +158 -0
  66. package/dist/resources/extensions/gsd/guided-flow.js +17 -2
  67. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  68. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  69. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  70. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  71. package/dist/resources/extensions/gsd/migrate/safety.js +4 -1
  72. package/dist/resources/extensions/gsd/milestone-closeout.js +13 -23
  73. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  74. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +6 -4
  75. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  76. package/dist/resources/extensions/gsd/paths.js +27 -0
  77. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  78. package/dist/resources/extensions/gsd/preferences-models.js +14 -48
  79. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  80. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  81. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  82. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  83. package/dist/resources/extensions/gsd/prompts/run-uat.md +6 -4
  84. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  85. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  86. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  87. package/dist/resources/extensions/gsd/publication.js +87 -0
  88. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  89. package/dist/resources/extensions/gsd/recovery-classification.js +37 -94
  90. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  91. package/dist/resources/extensions/gsd/state.js +6 -20
  92. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  93. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  94. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  95. package/dist/resources/extensions/gsd/tools/complete-slice.js +20 -10
  96. package/dist/resources/extensions/gsd/tools/exec-tool.js +9 -7
  97. package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
  98. package/dist/resources/extensions/gsd/uat-policy.js +42 -16
  99. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  100. package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
  101. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  102. package/dist/resources/extensions/gsd/unit-registry.js +337 -0
  103. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  104. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  105. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  106. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  107. package/dist/resources/extensions/gsd/worktree-git-recovery.js +15 -9
  108. package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
  109. package/dist/resources/extensions/gsd/worktree-root.js +11 -0
  110. package/dist/resources/extensions/gsd/worktree-session-state.js +4 -5
  111. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  112. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  113. package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
  114. package/dist/resources/shared/package.json +3 -0
  115. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  116. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  117. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  118. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  119. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  120. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  121. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  122. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  123. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  124. package/dist/web/standalone/.next/BUILD_ID +1 -1
  125. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  126. package/dist/web/standalone/.next/build-manifest.json +3 -3
  127. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  128. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  145. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/index.html +1 -1
  148. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  153. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  154. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  155. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  156. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  157. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  160. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  161. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  162. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  163. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  164. package/dist/web/standalone/package.json +1 -1
  165. package/dist/worktree-cli.js +3 -6
  166. package/dist/worktree-status-banner.js +7 -15
  167. package/package.json +1 -1
  168. package/packages/cloud-mcp-gateway/package.json +2 -2
  169. package/packages/contracts/dist/rpc.d.ts +1 -0
  170. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  171. package/packages/contracts/dist/rpc.js.map +1 -1
  172. package/packages/contracts/dist/workflow.d.ts +4 -0
  173. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  174. package/packages/contracts/dist/workflow.js.map +1 -1
  175. package/packages/contracts/package.json +1 -1
  176. package/packages/daemon/package.json +4 -4
  177. package/packages/gsd-agent-core/package.json +5 -5
  178. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  179. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  180. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  181. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  186. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  187. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  188. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  190. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  193. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  194. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  196. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  197. package/packages/gsd-agent-modes/package.json +7 -7
  198. package/packages/mcp-server/dist/cli.js +6 -3
  199. package/packages/mcp-server/dist/cli.js.map +1 -1
  200. package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
  201. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.js +17 -1
  203. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  204. package/packages/mcp-server/package.json +3 -3
  205. package/packages/native/package.json +1 -1
  206. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  207. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  208. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  209. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  210. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  211. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  212. package/packages/pi-agent-core/dist/index.js +3 -0
  213. package/packages/pi-agent-core/dist/index.js.map +1 -1
  214. package/packages/pi-agent-core/package.json +1 -1
  215. package/packages/pi-ai/README.md +1 -0
  216. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  217. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  218. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  219. package/packages/pi-ai/dist/models.generated.d.ts +35 -125
  220. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  221. package/packages/pi-ai/dist/models.generated.js +46 -120
  222. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  223. package/packages/pi-ai/package.json +3 -2
  224. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  225. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  226. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  227. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  228. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  229. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  230. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  231. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  232. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  234. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  236. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  237. package/packages/pi-coding-agent/dist/index.js +1 -1
  238. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  239. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  240. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  241. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  242. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  243. package/packages/pi-coding-agent/package.json +7 -7
  244. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  245. package/packages/pi-tui/dist/tui.js +9 -0
  246. package/packages/pi-tui/dist/tui.js.map +1 -1
  247. package/packages/pi-tui/package.json +2 -2
  248. package/packages/rpc-client/package.json +2 -2
  249. package/pkg/package.json +1 -1
  250. package/src/resources/GSD-WORKFLOW.md +5 -4
  251. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  252. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  253. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  254. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  255. package/src/resources/extensions/async-jobs/index.ts +79 -0
  256. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  257. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  258. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  259. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  260. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  261. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  262. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  263. package/src/resources/extensions/bg-shell/utilities.ts +3 -0
  264. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  265. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  266. package/src/resources/extensions/browser-tools/index.ts +71 -13
  267. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  268. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
  269. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  270. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +34 -4
  271. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  272. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  273. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  274. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  275. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  276. package/src/resources/extensions/gsd/auto/orchestrator.ts +70 -46
  277. package/src/resources/extensions/gsd/auto/phases.ts +2 -2
  278. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -32
  279. package/src/resources/extensions/gsd/auto-dispatch.ts +38 -52
  280. package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
  281. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -8
  282. package/src/resources/extensions/gsd/auto-prompts.ts +118 -35
  283. package/src/resources/extensions/gsd/auto-start.ts +18 -17
  284. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  285. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +14 -21
  286. package/src/resources/extensions/gsd/auto-verification.ts +8 -26
  287. package/src/resources/extensions/gsd/auto-worktree.ts +30 -93
  288. package/src/resources/extensions/gsd/auto.ts +8 -15
  289. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
  290. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
  291. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  292. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +251 -47
  293. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +352 -84
  294. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  295. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  296. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  297. package/src/resources/extensions/gsd/captures.ts +4 -6
  298. package/src/resources/extensions/gsd/consent-question.ts +416 -0
  299. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  300. package/src/resources/extensions/gsd/constants.ts +0 -3
  301. package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
  302. package/src/resources/extensions/gsd/db/queries.ts +37 -0
  303. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  304. package/src/resources/extensions/gsd/doctor-environment.ts +2 -7
  305. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  306. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +13 -15
  307. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  308. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  309. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  310. package/src/resources/extensions/gsd/files.ts +33 -12
  311. package/src/resources/extensions/gsd/guidance.ts +217 -0
  312. package/src/resources/extensions/gsd/guided-flow.ts +16 -2
  313. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  314. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  315. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  316. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  317. package/src/resources/extensions/gsd/migrate/safety.ts +4 -1
  318. package/src/resources/extensions/gsd/milestone-closeout.ts +13 -23
  319. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  320. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -4
  321. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  322. package/src/resources/extensions/gsd/paths.ts +33 -0
  323. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  324. package/src/resources/extensions/gsd/preferences-models.ts +12 -47
  325. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  326. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  327. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  328. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  329. package/src/resources/extensions/gsd/prompts/run-uat.md +6 -4
  330. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  331. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  332. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  333. package/src/resources/extensions/gsd/publication.ts +122 -0
  334. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  335. package/src/resources/extensions/gsd/recovery-classification.ts +42 -96
  336. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  337. package/src/resources/extensions/gsd/state.ts +9 -21
  338. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  339. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
  340. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +101 -26
  341. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  342. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  343. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  344. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  345. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -0
  346. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  347. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  348. package/src/resources/extensions/gsd/tests/consent-question.test.ts +336 -0
  349. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  350. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  351. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  352. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  353. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  354. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  355. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  356. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  357. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  358. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  359. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  360. package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
  361. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +53 -11
  362. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +73 -58
  363. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  364. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  365. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  366. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  367. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  368. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  369. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  370. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +139 -0
  371. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  372. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  373. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  374. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  375. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +157 -0
  376. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
  377. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  378. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  379. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  380. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  381. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
  382. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  383. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
  384. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  385. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  386. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  387. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
  388. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  389. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
  390. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  391. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  392. package/src/resources/extensions/gsd/tools/complete-slice.ts +20 -10
  393. package/src/resources/extensions/gsd/tools/exec-tool.ts +8 -7
  394. package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
  395. package/src/resources/extensions/gsd/uat-policy.ts +62 -16
  396. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  397. package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
  398. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  399. package/src/resources/extensions/gsd/unit-registry.ts +412 -0
  400. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  401. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  402. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  403. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  404. package/src/resources/extensions/gsd/worktree-git-recovery.ts +15 -9
  405. package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
  406. package/src/resources/extensions/gsd/worktree-root.ts +12 -0
  407. package/src/resources/extensions/gsd/worktree-session-state.ts +3 -5
  408. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  409. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  410. package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
  411. package/src/resources/shared/package.json +3 -0
  412. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  413. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  414. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  415. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  416. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  417. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  418. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  419. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  420. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  421. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  422. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  423. /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → jmTLg6xZmAuq_LIqKOxrH}/_buildManifest.js +0 -0
  424. /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → jmTLg6xZmAuq_LIqKOxrH}/_ssgManifest.js +0 -0
@@ -1,10 +1,12 @@
1
1
  // Project/App: gsd-pi
2
- // File Purpose: Web-app detection and Playwright/UAT guidance for planning and slice closeout.
2
+ // File Purpose: Web-app detection and browser-UAT guidance for planning and slice closeout.
3
3
 
4
4
  import { existsSync, readFileSync } from "node:fs";
5
5
  import { resolve } from "node:path";
6
6
 
7
+ import { resolveAmbientBrowserEngineResolution, type BrowserEngineResolution } from "../browser-tools/engine/selection.js";
7
8
  import { detectWebApp } from "../browser-tools/web-app-detect.js";
9
+ import { UAT_MODE_POLICIES, type UatType } from "./uat-policy.js";
8
10
 
9
11
  export { detectWebApp };
10
12
 
@@ -47,24 +49,61 @@ export function findPlaywrightTestScript(projectRoot: string): string | null {
47
49
  return null;
48
50
  }
49
51
 
52
+ function describeBrowserToolBacking(engineResolution: BrowserEngineResolution): string {
53
+ switch (engineResolution.engine) {
54
+ case "gsd-browser":
55
+ return "This project looks browser-facing. GSD exposes `browser_*` tools backed by the managed gsd-browser engine for run-uat.";
56
+ case "legacy":
57
+ return "This project looks browser-facing. GSD exposes Playwright-backed `browser_*` tools for run-uat.";
58
+ case "off":
59
+ return "This project looks browser-facing, but Pi browser tools are disabled (GSD_BROWSER_ENGINE=off) — prefer `runtime-executable` UAT with automated browser test commands.";
60
+ }
61
+ }
62
+
63
+ // One bullet per recommended UAT mode; `mode` keys into UAT_MODE_POLICIES so
64
+ // modes that require browser tools drop out of the guidance when the resolved
65
+ // engine provides none (mixed/live-runtime share one bullet and one policy bit).
66
+ const UAT_MODE_GUIDANCE: ReadonlyArray<{ mode: UatType; bullet: string }> = [
67
+ {
68
+ mode: "browser-executable",
69
+ bullet: "- `browser-executable` — navigate to `http://localhost:…`, click, screenshot, assert via `browser_*` tools during run-uat",
70
+ },
71
+ {
72
+ mode: "runtime-executable",
73
+ bullet: "- `runtime-executable` — run an automated browser test command via `gsd_uat_exec` (for example `npx playwright test`)",
74
+ },
75
+ {
76
+ mode: "mixed",
77
+ bullet: "- `mixed` / `live-runtime` — combine runtime startup checks with interactive browser verification",
78
+ },
79
+ ];
80
+
50
81
  /**
51
82
  * Markdown block injected into plan/complete-slice prompts when the project
52
- * looks browser-facing. Returns null for CLI/library-only repos.
83
+ * looks browser-facing. Returns null for CLI/library-only repos. Guidance is
84
+ * composed from the resolved Browser Automation Engine so prompts never claim
85
+ * an engine the runtime is not using; `engineResolution` is injectable for
86
+ * tests and defaults to the ambient resolution.
53
87
  */
54
- export function buildWebAppUatGuidanceBlock(projectRoot: string): string | null {
88
+ export function buildWebAppUatGuidanceBlock(
89
+ projectRoot: string,
90
+ engineResolution?: BrowserEngineResolution,
91
+ ): string | null {
55
92
  if (!detectWebApp(projectRoot)) return null;
56
93
 
94
+ const resolvedEngine = engineResolution ?? resolveAmbientBrowserEngineResolution(projectRoot);
95
+ const browserToolsAvailable = resolvedEngine.engine !== "off";
57
96
  const playwrightScript = findPlaywrightTestScript(projectRoot);
58
97
  const hasPlaywright = hasPlaywrightTestDependency(projectRoot) || playwrightScript !== null;
59
98
  const lines = [
60
99
  "### Web App UAT (detected)",
61
100
  "",
62
- "This project looks browser-facing. GSD exposes Playwright-backed `browser_*` tools by default for run-uat.",
101
+ describeBrowserToolBacking(resolvedEngine),
63
102
  "",
64
103
  "**UAT modes (pick one per slice — do not use `artifact-driven` for browser steps):**",
65
- "- `browser-executable` — navigate to `http://localhost:…`, click, screenshot, assert via `browser_*` tools during run-uat",
66
- "- `runtime-executable` run an automated browser test command via `gsd_uat_exec` (for example `npx playwright test`)",
67
- "- `mixed` / `live-runtime` — combine runtime startup checks with interactive browser verification",
104
+ ...UAT_MODE_GUIDANCE
105
+ .filter(({ mode }) => browserToolsAvailable || !UAT_MODE_POLICIES[mode].browserTools)
106
+ .map(({ bullet }) => bullet),
68
107
  "",
69
108
  "**Planning / closeout rules:**",
70
109
  "- Preconditions must name the dev-server command and URL (for example `npm run dev` → `http://localhost:3000`)",
@@ -93,8 +132,12 @@ export function buildWebAppUatGuidanceBlock(projectRoot: string): string | null
93
132
  "**Playwright scaffolding (first UI slice):** no `playwright` / `@playwright/test` dependency yet.",
94
133
  "- Add a planning task that installs Playwright, adds `playwright.config.ts`, and creates a minimal smoke spec (for example `e2e/smoke.spec.ts`)",
95
134
  "- Task `verify` should run `npx playwright test` (or the focused spec) with a safe, simple command",
96
- "- Until specs exist, use `browser-executable` UAT with localhost preconditions and interactive `browser_*` checks at slice closeout",
97
135
  );
136
+ if (browserToolsAvailable) {
137
+ lines.push(
138
+ "- Until specs exist, use `browser-executable` UAT with localhost preconditions and interactive `browser_*` checks at slice closeout",
139
+ );
140
+ }
98
141
  }
99
142
 
100
143
  return lines.join("\n");
@@ -28,7 +28,7 @@ export const WORKFLOW_TOOL_ALIAS_PAIRS: readonly WorkflowToolAliasPair[] =
28
28
  export const WORKFLOW_TOOL_ALIAS_TO_CANONICAL: Readonly<Record<string, string>> =
29
29
  Object.fromEntries(WORKFLOW_TOOL_ALIAS_PAIRS.map(({ alias, canonical }) => [alias, canonical]));
30
30
 
31
- const WORKFLOW_MCP_ADAPTER_TOOL_NAMES = [
31
+ export const WORKFLOW_MCP_ADAPTER_TOOL_NAMES = [
32
32
  "gsd_cancel",
33
33
  "gsd_captures",
34
34
  "ask_user_questions",
@@ -45,6 +45,9 @@ const WORKFLOW_MCP_ADAPTER_TOOL_NAMES = [
45
45
  "gsd_status",
46
46
  ] as const;
47
47
 
48
+ /** Session-orchestration tools exposed by the workflow MCP adapter alongside the contract tools. */
49
+ export type WorkflowMcpAdapterToolName = (typeof WORKFLOW_MCP_ADAPTER_TOOL_NAMES)[number];
50
+
48
51
  export const WORKFLOW_TOOL_SURFACE_NAMES = [
49
52
  ...WORKFLOW_MCP_ADAPTER_TOOL_NAMES,
50
53
  ...DB_WORKFLOW_TOOL_NAMES,
@@ -8,8 +8,9 @@
8
8
  * git operations during worktree transitions:
9
9
  *
10
10
  * - `checkoutBranchWithStashGuard` — branch switch with stash protection,
11
- * including the stash-pop EEXIST collision recovery for `.gsd/` runtime
12
- * files (force-checkout + targeted stash drop).
11
+ * including the stash-pop EEXIST collision recovery for untracked files
12
+ * (force-checkout + targeted stash drop; #645 broadened it beyond `.gsd/`,
13
+ * guarded by "no non-.gsd unmerged entries remain").
13
14
  * - `removeMergeStateFiles` — clears SQUASH_MSG / MERGE_HEAD / etc. left by
14
15
  * a failed merge so subsequent merges don't fail on stale state.
15
16
  * - `cleanupConflictState` — merge-abort + index reset + state-file cleanup
@@ -257,23 +258,28 @@ export function checkoutBranchWithStashGuard(
257
258
  : "";
258
259
  const stashPopMessage = `${stderrText}\n${msg}`.trim();
259
260
  const alreadyExists = stashAlreadyExistsFilesFromError(popErr);
260
- const gsdAlreadyExists = alreadyExists.filter((f) => f.startsWith(".gsd/"));
261
- const nonGsdAlreadyExists = alreadyExists.filter((f) => !f.startsWith(".gsd/"));
262
261
  const isUntrackedRestoreFailure = stashPopMessage.includes("could not restore untracked files from stash");
263
262
  const stashRefForDrop = stashRefFromError(popErr);
264
- const nonGsdUnmerged = nativeConflictFiles(basePath).filter((f) => !f.startsWith(".gsd/"));
263
+ const allConflictFiles = nativeConflictFiles(basePath);
264
+ const nonGsdUnmerged = allConflictFiles.filter((f) => !f.startsWith(".gsd/"));
265
+ const gsdUnmerged = allConflictFiles.filter((f) => f.startsWith(".gsd/"));
265
266
  const gsdContentConflicts = isUntrackedRestoreFailure
266
267
  ? gsdJsonlFilesWithConflictMarkers(basePath)
267
268
  : [];
268
- const gsdConflictFiles = [...new Set([...gsdAlreadyExists, ...gsdContentConflicts])];
269
+ // Resolve ALL untracked-collision files by accepting HEAD — files in
270
+ // alreadyExists were untracked on the source branch by definition of the
271
+ // "already exists, no checkout" failure, so target HEAD is authoritative.
272
+ // gsdUnmerged: .gsd/ index conflicts left by the partial stash pop are
273
+ // also resolved via HEAD — .gsd/ runtime state is always authoritative
274
+ // on the target branch, so accepting HEAD is safe here too.
275
+ const resolvable = [...new Set([...alreadyExists, ...gsdContentConflicts, ...gsdUnmerged])];
269
276
 
270
277
  if (
271
278
  isUntrackedRestoreFailure &&
272
- gsdConflictFiles.length > 0 &&
273
- nonGsdAlreadyExists.length === 0 &&
279
+ resolvable.length > 0 &&
274
280
  nonGsdUnmerged.length === 0
275
281
  ) {
276
- for (const f of gsdConflictFiles) {
282
+ for (const f of resolvable) {
277
283
  execFileSync("git", ["checkout", "HEAD", "--", f], {
278
284
  cwd: basePath,
279
285
  stdio: ["ignore", "pipe", "pipe"],
@@ -47,6 +47,7 @@ import {
47
47
  // callers — production wiring previously injected them via deps; the seam
48
48
  // added type churn without enabling test variation.
49
49
  import { loadEffectiveGSDPreferences, getIsolationMode } from "./preferences.js";
50
+ import { isolationDegradedFallbackGuidance, worktreeCreationFailedGuidance } from "./guidance.js";
50
51
  import { invalidateAllCaches } from "./cache.js";
51
52
  import { resolveMilestoneFile } from "./paths.js";
52
53
  import { getMilestone, insertMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
@@ -693,10 +694,7 @@ export function _enterMilestoneCore(
693
694
  s.basePath = basePath;
694
695
  rebuildGitService(s, deps);
695
696
  invalidateAllCaches();
696
- ctx.notify(
697
- `Worktree isolation is degraded. Fell back to branch milestone/${milestoneId}.`,
698
- "warning",
699
- );
697
+ ctx.notify(isolationDegradedFallbackGuidance(milestoneId), "warning");
700
698
  return { ok: true, mode: "branch", path: basePath };
701
699
  } catch (err) {
702
700
  debugLog("WorktreeLifecycle", {
@@ -883,10 +881,7 @@ export function _enterMilestoneCore(
883
881
  eventType: "worktree-create-failed",
884
882
  data: { milestoneId, error: msg, fallback: "project-root" },
885
883
  });
886
- ctx.notify(
887
- `Auto-worktree creation for ${milestoneId} failed: ${msg}. Continuing in project root.`,
888
- "warning",
889
- );
884
+ ctx.notify(worktreeCreationFailedGuidance(milestoneId, msg), "warning");
890
885
  // Degrade isolation for the rest of this session so mergeAndExit
891
886
  // doesn't try to merge a nonexistent worktree branch (#2483)
892
887
  s.isolationDegraded = true;
@@ -69,6 +69,18 @@ export function isGsdWorktreePath(path: string): boolean {
69
69
  return findWorktreeSegment(path.replaceAll("\\", "/")) !== null;
70
70
  }
71
71
 
72
+ /**
73
+ * Project-root prefix of a GSD worktree path, or null when the path is not
74
+ * inside a recognized worktree layout. Pure string split — no env handling,
75
+ * HOME guard, or filesystem fallbacks (resolveWorktreeProjectRoot adds
76
+ * those). Separator normalization is 1:1 on characters, so the prefix is
77
+ * sliced from the ORIGINAL string and keeps its separators.
78
+ */
79
+ export function projectRootFromWorktreePath(path: string): string | null {
80
+ const segment = findWorktreeSegment(path.replaceAll("\\", "/"));
81
+ return segment ? path.slice(0, segment.gsdIdx) : null;
82
+ }
83
+
72
84
  /**
73
85
  * When a milestone worktree lives under the external-state layout
74
86
  * (`<gsdHome>/projects/<hash>/worktrees/<MID>/`, or the `GSD_STATE_DIR`
@@ -1,5 +1,5 @@
1
1
  // GSD worktree session state
2
- import { findWorktreeSegment } from "./worktree-root.js";
2
+ import { findWorktreeSegment, projectRootFromWorktreePath } from "./worktree-root.js";
3
3
 
4
4
  let originalCwd: string | null = null;
5
5
 
@@ -17,10 +17,8 @@ export function clearWorktreeOriginalCwd(): void {
17
17
 
18
18
  export function ensureWorktreeOriginalCwdFromPath(cwd: string = process.cwd()): string | null {
19
19
  if (originalCwd) return originalCwd;
20
- const segment = findWorktreeSegment(cwd.replaceAll("\\", "/"));
21
- if (segment) {
22
- originalCwd = cwd.slice(0, segment.gsdIdx);
23
- }
20
+ const root = projectRootFromWorktreePath(cwd);
21
+ if (root) originalCwd = root;
24
22
  return originalCwd;
25
23
  }
26
24
 
@@ -243,9 +243,11 @@ export function registerNativeSearchHooks(pi: NativeSearchPI): { getIsAnthropic:
243
243
  // Anthropic-only tool never leaks into OpenAI Responses requests.
244
244
  isAnthropic = isAnthropicProvider && payloadLooksAnthropic !== false;
245
245
  } else {
246
- // Last resort: session-restore paths where the SDK doesn't pass model.
247
- // The model-name prefix is best-effort and assumes direct Anthropic.
248
- isAnthropic = payloadLooksAnthropic === true;
246
+ // No authoritative provider info available (no event.model, no model_select).
247
+ // Do NOT inject native web_search guessing on model name alone causes 400
248
+ // "unsupported_value" errors when the actual provider (copilot, openrouter,
249
+ // proxy, etc.) doesn't expose the server-side search tool (#648).
250
+ isAnthropic = false;
249
251
  }
250
252
  if (!isAnthropic) return;
251
253
 
@@ -0,0 +1,66 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Browser Automation Contract — the single source for the canonical
3
+ // Pi-facing browser tool vocabulary. Engine adapters (legacy Playwright, managed
4
+ // gsd-browser), UAT policy, dispatch preflight, and evidence detection all derive
5
+ // their browser tool knowledge from this module instead of re-listing names.
6
+
7
+ /**
8
+ * Canonical `browser_*` tool names of the Browser Automation Contract.
9
+ *
10
+ * These are the product-level names Units see regardless of which Browser
11
+ * Automation Engine serves them (ADR-024). Adding a capability here is the
12
+ * one-line vocabulary change; the engine adapters and presentation surfaces
13
+ * are typed against this list, so missing coverage fails typecheck.
14
+ */
15
+ export const BROWSER_CONTRACT_TOOL_NAMES = [
16
+ "browser_navigate",
17
+ "browser_click",
18
+ "browser_type",
19
+ "browser_fill_form",
20
+ "browser_click_ref",
21
+ "browser_fill_ref",
22
+ "browser_wait_for",
23
+ "browser_assert",
24
+ "browser_verify",
25
+ "browser_screenshot",
26
+ "browser_snapshot_refs",
27
+ "browser_find",
28
+ "browser_get_console_logs",
29
+ "browser_get_network_logs",
30
+ "browser_evaluate",
31
+ "browser_reload",
32
+ "browser_batch",
33
+ "browser_act",
34
+ ] as const;
35
+
36
+ export type BrowserContractToolName = (typeof BROWSER_CONTRACT_TOOL_NAMES)[number];
37
+
38
+ const BROWSER_CONTRACT_TOOL_NAME_SET: ReadonlySet<string> = new Set(BROWSER_CONTRACT_TOOL_NAMES);
39
+
40
+ export function isBrowserContractToolName(name: string): name is BrowserContractToolName {
41
+ return BROWSER_CONTRACT_TOOL_NAME_SET.has(name);
42
+ }
43
+
44
+ /**
45
+ * Whether a canonical (non-MCP-prefixed) tool name belongs to the browser tool
46
+ * family. Broader than the contract list on purpose: an External MCP Client or
47
+ * host integration may supply additional `browser_*` tools that still satisfy
48
+ * browser-backed UAT.
49
+ */
50
+ export function hasBrowserContractPrefix(canonicalToolName: string): boolean {
51
+ return canonicalToolName.startsWith("browser_");
52
+ }
53
+
54
+ /**
55
+ * Contract tool names whose appearance in prose marks browser-backed UAT
56
+ * activity (requirement or evidence language). Consumed by the
57
+ * browser-evidence regexes so textual detection stays derived from the
58
+ * contract vocabulary.
59
+ */
60
+ export const BROWSER_EVIDENCE_SIGNAL_TOOL_NAMES = [
61
+ "browser_assert",
62
+ "browser_batch",
63
+ "browser_find",
64
+ "browser_verify",
65
+ "browser_snapshot_refs",
66
+ ] as const satisfies readonly BrowserContractToolName[];
@@ -55,6 +55,14 @@ function parseGsdBrowserVersion(output: string): string | null {
55
55
  return output.match(/\b(\d+\.\d+\.\d+)\b/)?.[1] ?? null;
56
56
  }
57
57
 
58
+ function isRecord(value: unknown): value is Record<string, unknown> {
59
+ return !!value && typeof value === "object" && !Array.isArray(value);
60
+ }
61
+
62
+ function resolveExplicitGsdBrowserCliPath(env: NodeJS.ProcessEnv): string | undefined {
63
+ return env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim() || undefined;
64
+ }
65
+
58
66
  function resolveBundledGsdBrowserPackageVersion(): string | null {
59
67
  try {
60
68
  const requireFromHere = createRequire(import.meta.url);
@@ -66,20 +74,28 @@ function resolveBundledGsdBrowserPackageVersion(): string | null {
66
74
  }
67
75
  }
68
76
 
77
+ // The `gsd-browser --version` subprocess result cannot change mid-session (the
78
+ // engine-switch guard forbids restarting with a different engine), and both the
79
+ // availability probe and the launch-config resolution ask for it at session
80
+ // start — memoize so the up-to-2s spawn happens once per process.
81
+ let cachedPathProbeVersion: string | null | undefined;
82
+
69
83
  function resolvePathGsdBrowserVersion(env: NodeJS.ProcessEnv): string | null {
70
84
  const explicit = env.GSD_BROWSER_PATH_VERSION?.trim();
71
85
  if (explicit) return parseGsdBrowserVersion(explicit);
86
+ if (cachedPathProbeVersion !== undefined) return cachedPathProbeVersion;
72
87
 
73
88
  try {
74
- return parseGsdBrowserVersion(execFileSync("gsd-browser", ["--version"], {
89
+ cachedPathProbeVersion = parseGsdBrowserVersion(execFileSync("gsd-browser", ["--version"], {
75
90
  encoding: "utf-8",
76
91
  env,
77
92
  stdio: ["ignore", "pipe", "ignore"],
78
93
  timeout: 2000,
79
94
  }));
80
95
  } catch {
81
- return null;
96
+ cachedPathProbeVersion = null;
82
97
  }
98
+ return cachedPathProbeVersion;
83
99
  }
84
100
 
85
101
  function shouldPreferPathGsdBrowser(env: NodeJS.ProcessEnv): boolean {
@@ -91,7 +107,7 @@ function shouldPreferPathGsdBrowser(env: NodeJS.ProcessEnv): boolean {
91
107
  }
92
108
 
93
109
  export function resolveBundledGsdBrowserCliPath(env: NodeJS.ProcessEnv = process.env): string | null {
94
- const explicit = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
110
+ const explicit = resolveExplicitGsdBrowserCliPath(env);
95
111
  if (explicit) return explicit;
96
112
 
97
113
  try {
@@ -115,6 +131,45 @@ export function resolveBundledGsdBrowserCliPath(env: NodeJS.ProcessEnv = process
115
131
  return null;
116
132
  }
117
133
 
134
+ export type GsdBrowserCliAvailability =
135
+ | { available: true; via: "explicit-env" | "bundled" | "path"; detail: string }
136
+ | { available: false; detail: string };
137
+
138
+ /**
139
+ * Cheap availability probe for the gsd-browser CLI: explicit env overrides,
140
+ * then the bundled @opengsd/gsd-browser binary (filesystem checks only), then
141
+ * a PATH lookup (one short subprocess, memoized). Used by Browser Automation
142
+ * Engine resolution to decide whether the managed engine is provable before
143
+ * preferring it over legacy Playwright. `via` names the provable source, not
144
+ * necessarily the launch source — resolveGsdBrowserMcpLaunchConfig may still
145
+ * prefer a newer PATH CLI over the bundled one.
146
+ */
147
+ export function resolveGsdBrowserCliAvailability(env: NodeJS.ProcessEnv = process.env): GsdBrowserCliAvailability {
148
+ const explicitCommand = env.GSD_BROWSER_MCP_COMMAND?.trim();
149
+ if (explicitCommand) {
150
+ return { available: true, via: "explicit-env", detail: `GSD_BROWSER_MCP_COMMAND=${explicitCommand}` };
151
+ }
152
+
153
+ const explicitCliPath = resolveExplicitGsdBrowserCliPath(env);
154
+ if (explicitCliPath) {
155
+ return existsSync(explicitCliPath)
156
+ ? { available: true, via: "explicit-env", detail: `CLI at ${explicitCliPath}` }
157
+ : { available: false, detail: `configured gsd-browser CLI path does not exist: ${explicitCliPath}` };
158
+ }
159
+
160
+ const bundledCliPath = resolveBundledGsdBrowserCliPath(env);
161
+ if (bundledCliPath) {
162
+ return { available: true, via: "bundled", detail: `bundled CLI at ${bundledCliPath}` };
163
+ }
164
+
165
+ const pathVersion = resolvePathGsdBrowserVersion(env);
166
+ if (pathVersion) {
167
+ return { available: true, via: "path", detail: `gsd-browser ${pathVersion} on PATH` };
168
+ }
169
+
170
+ return { available: false, detail: "no bundled or PATH gsd-browser CLI found" };
171
+ }
172
+
118
173
  export function buildGsdBrowserSessionName(projectRoot: string, suffix?: string): string {
119
174
  const resolvedProjectRoot = resolve(projectRoot);
120
175
  const base = sanitizeSessionSegment(basename(resolvedProjectRoot)) || "project";
@@ -123,6 +178,35 @@ export function buildGsdBrowserSessionName(projectRoot: string, suffix?: string)
123
178
  return cleanSuffix ? `gsd-${base}-${hash}-${cleanSuffix}` : `gsd-${base}-${hash}`;
124
179
  }
125
180
 
181
+ /**
182
+ * Recognize an MCP server config (from .mcp.json / Claude settings) as a
183
+ * gsd-browser server. Paired with resolveGsdBrowserMcpLaunchConfig: this module
184
+ * writes the config shape, so it also owns recognizing it. New launch shapes
185
+ * are taught here, in one place.
186
+ */
187
+ export function isGsdBrowserMcpServerConfig(config: unknown): boolean {
188
+ if (!isRecord(config)) return false;
189
+
190
+ const command = typeof config.command === "string" ? config.command : "";
191
+ if (command.includes("gsd-browser") || command.includes("@opengsd/gsd-browser")) {
192
+ return true;
193
+ }
194
+
195
+ if (isRecord(config.env)) {
196
+ const env = config.env;
197
+ if (
198
+ typeof env.GSD_BROWSER_CLI_PATH === "string"
199
+ || typeof env.GSD_BROWSER_BIN_PATH === "string"
200
+ || typeof env.GSD_BROWSER_MCP_COMMAND === "string"
201
+ ) {
202
+ return true;
203
+ }
204
+ }
205
+
206
+ const args = Array.isArray(config.args) ? config.args.filter((arg): arg is string => typeof arg === "string") : [];
207
+ return args.some((arg) => arg.includes("gsd-browser") || arg.includes("@opengsd/gsd-browser"));
208
+ }
209
+
126
210
  export function resolveGsdBrowserMcpLaunchConfig(
127
211
  projectRoot: string,
128
212
  env: NodeJS.ProcessEnv = process.env,
@@ -133,7 +217,7 @@ export function resolveGsdBrowserMcpLaunchConfig(
133
217
  const explicitArgs = parseJsonEnv<unknown>(env, "GSD_BROWSER_MCP_ARGS");
134
218
  const explicitEnv = parseJsonEnv<Record<string, string>>(env, "GSD_BROWSER_MCP_ENV");
135
219
  const explicitCommand = env.GSD_BROWSER_MCP_COMMAND?.trim();
136
- const explicitCliPath = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
220
+ const explicitCliPath = resolveExplicitGsdBrowserCliPath(env);
137
221
  const preferPathCli = !explicitCommand && !explicitCliPath && shouldPreferPathGsdBrowser(env);
138
222
  const bundledCliPath = !explicitCommand && !explicitCliPath && !preferPathCli
139
223
  ? resolveBundledGsdBrowserCliPath(env)
@@ -144,6 +228,10 @@ export function resolveGsdBrowserMcpLaunchConfig(
144
228
  // profile/cookies persist across pi sessions for the same project. gsd-browser
145
229
  // rejects --identity-scope unless --identity-key is also supplied.
146
230
  const identityKey = env.GSD_BROWSER_IDENTITY_KEY?.trim() || buildGsdBrowserSessionName(resolvedProjectRoot);
231
+ // identity-project must be a safe identifier (no path separators); full paths
232
+ // cause daemon startup to fail with "invalid name".
233
+ const identityProject =
234
+ env.GSD_BROWSER_IDENTITY_PROJECT?.trim() || buildGsdBrowserSessionName(resolvedProjectRoot);
147
235
  const command =
148
236
  explicitCommand
149
237
  || explicitCliPath
@@ -162,7 +250,7 @@ export function resolveGsdBrowserMcpLaunchConfig(
162
250
  "--identity-key",
163
251
  identityKey,
164
252
  "--identity-project",
165
- resolvedProjectRoot,
253
+ identityProject,
166
254
  ];
167
255
  const cwd = env.GSD_BROWSER_MCP_CWD?.trim() || resolvedProjectRoot;
168
256
 
@@ -176,3 +264,29 @@ export function resolveGsdBrowserMcpLaunchConfig(
176
264
  sessionName,
177
265
  };
178
266
  }
267
+
268
+ /**
269
+ * CLI invocation that starts the gsd-browser session daemon with the same
270
+ * session and identity flags as {@link resolveGsdBrowserMcpLaunchConfig}, so
271
+ * browser UAT can warm Chrome/CDP before the first MCP navigation.
272
+ */
273
+ export function resolveGsdBrowserDaemonStartInvocation(
274
+ projectRoot: string,
275
+ env: NodeJS.ProcessEnv = process.env,
276
+ options: GsdBrowserMcpLaunchOptions = {},
277
+ ): Pick<GsdBrowserMcpLaunchConfig, "command" | "args" | "cwd" | "env"> {
278
+ const launch = resolveGsdBrowserMcpLaunchConfig(projectRoot, env, options);
279
+ const mcpIndex = launch.args.indexOf("mcp");
280
+ if (mcpIndex < 0) {
281
+ throw new Error("gsd-browser launch config is missing mcp subcommand");
282
+ }
283
+
284
+ const prefix = launch.args.slice(0, mcpIndex);
285
+ const sessionFlags = launch.args.slice(mcpIndex + 1);
286
+ return {
287
+ command: launch.command,
288
+ args: [...prefix, "daemon", "start", ...sessionFlags],
289
+ cwd: launch.cwd,
290
+ ...(launch.env ? { env: launch.env } : {}),
291
+ };
292
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -45,7 +45,7 @@ skill-name/
45
45
  **Reference pattern**: In SKILL.md, reference scripts using the `scripts/` path:
46
46
 
47
47
  ```bash
48
- python ~/.claude/skills/skill-name/scripts/analyze.py input.har
48
+ python ~/.agents/skills/skill-name/scripts/analyze.py input.har
49
49
  ```
50
50
  </scripts_directory>
51
51
  </file_organization>
@@ -10,16 +10,21 @@
10
10
  ## Step 1: Select the Skill
11
11
 
12
12
  ```bash
13
- ls ~/.claude/skills/
13
+ # User-global skills
14
+ ls ~/.agents/skills/ 2>/dev/null
15
+ # Project-local skills
16
+ ls .agents/skills/ 2>/dev/null
14
17
  ```
15
18
 
16
19
  Present numbered list, ask: "Which skill needs a new reference?"
17
20
 
21
+ Determine `{skill-path}`: use `.agents/skills/{skill-name}` (project-local) if found there, otherwise `~/.agents/skills/{skill-name}` (user-global). Project-local takes precedence because the skill catalog loads it first on name collision.
22
+
18
23
  ## Step 2: Analyze Current Structure
19
24
 
20
25
  ```bash
21
- cat ~/.claude/skills/{skill-name}/SKILL.md
22
- ls ~/.claude/skills/{skill-name}/references/ 2>/dev/null
26
+ cat {skill-path}/SKILL.md
27
+ ls {skill-path}/references/ 2>/dev/null
23
28
  ```
24
29
 
25
30
  Determine:
@@ -12,6 +12,8 @@ Ask (if not already provided):
12
12
  - Which skill needs a script?
13
13
  - What operation should the script perform?
14
14
 
15
+ Determine `{skill-path}`: use `.agents/skills/{skill-name}` (project-local) if found there, otherwise `~/.agents/skills/{skill-name}` (user-global). Project-local takes precedence because the skill catalog loads it first on name collision.
16
+
15
17
  ## Step 2: Analyze Script Need
16
18
 
17
19
  Confirm this is a good script candidate:
@@ -24,7 +26,7 @@ If not a good fit, suggest alternatives (inline code in workflow, reference exam
24
26
  ## Step 3: Create Scripts Directory
25
27
 
26
28
  ```bash
27
- mkdir -p ~/.claude/skills/{skill-name}/scripts
29
+ mkdir -p {skill-path}/scripts
28
30
  ```
29
31
 
30
32
  ## Step 4: Design Script
@@ -58,7 +60,7 @@ set -euo pipefail
58
60
  ## Step 6: Make Executable (if bash)
59
61
 
60
62
  ```bash
61
- chmod +x ~/.claude/skills/{skill-name}/scripts/{script-name}.sh
63
+ chmod +x {skill-path}/scripts/{script-name}.sh
62
64
  ```
63
65
 
64
66
  ## Step 7: Update Workflow to Use Script
@@ -12,6 +12,8 @@ Ask (if not already provided):
12
12
  - Which skill needs a template?
13
13
  - What output does this template structure?
14
14
 
15
+ Determine `{skill-path}`: use `.agents/skills/{skill-name}` (project-local) if found there, otherwise `~/.agents/skills/{skill-name}` (user-global). Project-local takes precedence because the skill catalog loads it first on name collision.
16
+
15
17
  ## Step 2: Analyze Template Need
16
18
 
17
19
  Confirm this is a good template candidate:
@@ -24,7 +26,7 @@ If not a good fit, suggest alternatives (workflow guidance, reference examples).
24
26
  ## Step 3: Create Templates Directory
25
27
 
26
28
  ```bash
27
- mkdir -p ~/.claude/skills/{skill-name}/templates
29
+ mkdir -p {skill-path}/templates
28
30
  ```
29
31
 
30
32
  ## Step 4: Design Template Structure
@@ -12,17 +12,22 @@
12
12
  **DO NOT use AskUserQuestion** - there may be many skills.
13
13
 
14
14
  ```bash
15
- ls ~/.claude/skills/
15
+ # User-global skills
16
+ ls ~/.agents/skills/ 2>/dev/null
17
+ # Project-local skills
18
+ ls .agents/skills/ 2>/dev/null
16
19
  ```
17
20
 
18
21
  Present numbered list, ask: "Which skill needs a new workflow?"
19
22
 
23
+ Determine `{skill-path}`: use `.agents/skills/{skill-name}` (project-local) if found there, otherwise `~/.agents/skills/{skill-name}` (user-global). Project-local takes precedence because the skill catalog loads it first on name collision.
24
+
20
25
  ## Step 2: Analyze Current Structure
21
26
 
22
27
  Read the skill:
23
28
  ```bash
24
- cat ~/.claude/skills/{skill-name}/SKILL.md
25
- ls ~/.claude/skills/{skill-name}/workflows/ 2>/dev/null
29
+ cat {skill-path}/SKILL.md
30
+ ls {skill-path}/workflows/ 2>/dev/null
26
31
  ```
27
32
 
28
33
  Determine: