@opengsd/gsd-pi 1.2.0-dev.955e4da0 → 1.2.0-dev.9ad8ae33

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 (575) 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/mcp-server.js +2 -1
  7. package/dist/models-resolver.d.ts +3 -13
  8. package/dist/models-resolver.js +3 -22
  9. package/dist/resource-loader.d.ts +10 -5
  10. package/dist/resource-loader.js +123 -20
  11. package/dist/resources/.managed-resources-content-hash +1 -1
  12. package/dist/resources/GSD-WORKFLOW.md +5 -4
  13. package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
  14. package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
  15. package/dist/resources/extensions/async-jobs/index.js +65 -0
  16. package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
  17. package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
  18. package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
  19. package/dist/resources/extensions/bg-shell/overlay.js +9 -6
  20. package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
  21. package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
  22. package/dist/resources/extensions/bg-shell/utilities.js +3 -0
  23. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
  24. package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
  25. package/dist/resources/extensions/browser-tools/index.js +69 -12
  26. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +30 -4
  27. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  28. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  29. package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
  30. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  31. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  32. package/dist/resources/extensions/gsd/auto/orchestrator.js +89 -54
  33. package/dist/resources/extensions/gsd/auto/phases.js +49 -6
  34. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  35. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
  36. package/dist/resources/extensions/gsd/auto-dispatch.js +50 -58
  37. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -13
  38. package/dist/resources/extensions/gsd/auto-post-unit.js +35 -8
  39. package/dist/resources/extensions/gsd/auto-prompts.js +81 -19
  40. package/dist/resources/extensions/gsd/auto-start.js +41 -18
  41. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  42. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  43. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +12 -20
  44. package/dist/resources/extensions/gsd/auto-verification.js +23 -30
  45. package/dist/resources/extensions/gsd/auto-worktree.js +44 -91
  46. package/dist/resources/extensions/gsd/auto.js +41 -14
  47. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  48. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +29 -8
  49. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
  50. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  51. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
  52. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +212 -48
  53. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +303 -77
  54. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  55. package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
  56. package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
  57. package/dist/resources/extensions/gsd/captures.js +4 -6
  58. package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
  59. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  60. package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
  61. package/dist/resources/extensions/gsd/consent-question.js +353 -0
  62. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  63. package/dist/resources/extensions/gsd/constants.js +0 -2
  64. package/dist/resources/extensions/gsd/crash-recovery.js +12 -15
  65. package/dist/resources/extensions/gsd/db/queries.js +26 -0
  66. package/dist/resources/extensions/gsd/db-writer.js +8 -17
  67. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  68. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  69. package/dist/resources/extensions/gsd/doctor-environment.js +2 -6
  70. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  71. package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
  72. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +13 -15
  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/gsd-command-home.js +22 -12
  78. package/dist/resources/extensions/gsd/gsd-db.js +2 -1
  79. package/dist/resources/extensions/gsd/guidance.js +158 -0
  80. package/dist/resources/extensions/gsd/guided-flow.js +23 -5
  81. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  82. package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
  83. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  84. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  85. package/dist/resources/extensions/gsd/migrate/safety.js +4 -1
  86. package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
  87. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  88. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  89. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  90. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +6 -4
  91. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  92. package/dist/resources/extensions/gsd/paths.js +27 -0
  93. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  94. package/dist/resources/extensions/gsd/preferences-models.js +14 -48
  95. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  96. package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  97. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
  98. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  99. package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -2
  100. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  101. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  102. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  103. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  104. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  105. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  106. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  107. package/dist/resources/extensions/gsd/prompts/run-uat.md +7 -5
  108. package/dist/resources/extensions/gsd/prompts/system.md +5 -2
  109. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  110. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  111. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  112. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  113. package/dist/resources/extensions/gsd/publication.js +87 -0
  114. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  115. package/dist/resources/extensions/gsd/recovery-classification.js +37 -94
  116. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  117. package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
  118. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  119. package/dist/resources/extensions/gsd/state.js +6 -20
  120. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  121. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  122. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  123. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  124. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  125. package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
  126. package/dist/resources/extensions/gsd/tools/complete-task.js +3 -2
  127. package/dist/resources/extensions/gsd/tools/exec-tool.js +9 -7
  128. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -8
  129. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  130. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  131. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  132. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
  133. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  134. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  135. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
  136. package/dist/resources/extensions/gsd/uat-policy.js +42 -16
  137. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  138. package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
  139. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  140. package/dist/resources/extensions/gsd/unit-registry.js +337 -0
  141. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  142. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  143. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  144. package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
  145. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  146. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  147. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  148. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  149. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  150. package/dist/resources/extensions/gsd/worktree-git-recovery.js +15 -9
  151. package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
  152. package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
  153. package/dist/resources/extensions/gsd/worktree-root.js +11 -0
  154. package/dist/resources/extensions/gsd/worktree-session-state.js +4 -5
  155. package/dist/resources/extensions/gsd/worktree.js +8 -1
  156. package/dist/resources/extensions/search-the-web/native-search.js +5 -3
  157. package/dist/resources/extensions/shared/browser-contract.js +59 -0
  158. package/dist/resources/extensions/shared/gsd-browser-cli.js +116 -6
  159. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  160. package/dist/resources/shared/package-manager-detection.js +1 -1
  161. package/dist/resources/shared/package.json +3 -0
  162. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  163. package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
  164. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  165. package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
  166. package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
  167. package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
  168. package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  169. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  170. package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  171. package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
  172. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  173. package/dist/update-check.d.ts +2 -0
  174. package/dist/update-check.js +24 -1
  175. package/dist/update-cmd.js +20 -3
  176. package/dist/web/standalone/.next/BUILD_ID +1 -1
  177. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  178. package/dist/web/standalone/.next/build-manifest.json +3 -3
  179. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  180. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  181. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  182. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  183. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  184. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  185. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  186. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  187. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  188. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  189. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  190. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  191. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  192. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  193. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  194. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  195. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  196. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  197. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  207. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  208. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  209. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  212. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  213. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  214. package/dist/web/standalone/.next/static/chunks/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
  215. package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
  216. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  217. package/dist/web/standalone/package.json +1 -1
  218. package/dist/worktree-cli.js +3 -6
  219. package/dist/worktree-status-banner.js +7 -15
  220. package/package.json +2 -2
  221. package/packages/cloud-mcp-gateway/package.json +2 -2
  222. package/packages/contracts/dist/rpc.d.ts +1 -0
  223. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  224. package/packages/contracts/dist/rpc.js.map +1 -1
  225. package/packages/contracts/dist/workflow.d.ts +4 -0
  226. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  227. package/packages/contracts/dist/workflow.js.map +1 -1
  228. package/packages/contracts/package.json +1 -1
  229. package/packages/daemon/package.json +4 -4
  230. package/packages/gsd-agent-core/package.json +5 -5
  231. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  232. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  233. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  234. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  235. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  236. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +7 -0
  237. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  238. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  239. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
  240. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  241. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  242. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
  243. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  244. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  245. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
  246. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  247. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  248. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
  249. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  250. package/packages/gsd-agent-modes/package.json +7 -7
  251. package/packages/mcp-server/dist/cli.js +9 -1
  252. package/packages/mcp-server/dist/cli.js.map +1 -1
  253. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  254. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  255. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  256. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  257. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  258. package/packages/mcp-server/dist/server.js +4 -0
  259. package/packages/mcp-server/dist/server.js.map +1 -1
  260. package/packages/mcp-server/dist/workflow-tools.d.ts +26 -18
  261. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  262. package/packages/mcp-server/dist/workflow-tools.js +116 -39
  263. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  264. package/packages/mcp-server/package.json +5 -4
  265. package/packages/native/package.json +1 -1
  266. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts +1 -0
  267. package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
  268. package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
  269. package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
  270. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  271. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  272. package/packages/pi-agent-core/dist/index.js +3 -0
  273. package/packages/pi-agent-core/dist/index.js.map +1 -1
  274. package/packages/pi-agent-core/package.json +1 -1
  275. package/packages/pi-ai/README.md +1 -0
  276. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  277. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  278. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  279. package/packages/pi-ai/dist/index.d.ts +2 -0
  280. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  281. package/packages/pi-ai/dist/index.js +2 -0
  282. package/packages/pi-ai/dist/index.js.map +1 -1
  283. package/packages/pi-ai/dist/models.generated.d.ts +35 -125
  284. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  285. package/packages/pi-ai/dist/models.generated.js +46 -120
  286. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  287. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  288. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  289. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  290. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  291. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  292. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  293. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  294. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  295. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  296. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  297. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  298. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  299. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  300. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  301. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  302. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  303. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  304. package/packages/pi-ai/package.json +3 -2
  305. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
  306. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  307. package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
  308. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/provider-readiness.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
  311. package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
  313. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
  315. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  317. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  318. package/packages/pi-coding-agent/dist/index.js +1 -1
  319. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
  321. package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
  323. package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
  324. package/packages/pi-coding-agent/package.json +7 -7
  325. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  326. package/packages/pi-tui/dist/tui.js +9 -0
  327. package/packages/pi-tui/dist/tui.js.map +1 -1
  328. package/packages/pi-tui/package.json +2 -2
  329. package/packages/rpc-client/package.json +2 -2
  330. package/pkg/package.json +1 -1
  331. package/src/resources/GSD-WORKFLOW.md +5 -4
  332. package/src/resources/extensions/async-jobs/async-bash-cancel.test.ts +360 -0
  333. package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
  334. package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
  335. package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
  336. package/src/resources/extensions/async-jobs/index.ts +79 -0
  337. package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
  338. package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
  339. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
  340. package/src/resources/extensions/bg-shell/overlay.ts +9 -5
  341. package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
  342. package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
  343. package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
  344. package/src/resources/extensions/bg-shell/utilities.ts +3 -0
  345. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
  346. package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
  347. package/src/resources/extensions/browser-tools/index.ts +71 -13
  348. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
  349. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +40 -1
  350. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
  351. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +34 -4
  352. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  353. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  354. package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
  355. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  356. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  357. package/src/resources/extensions/gsd/auto/orchestrator.ts +98 -56
  358. package/src/resources/extensions/gsd/auto/phases.ts +65 -26
  359. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  360. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
  361. package/src/resources/extensions/gsd/auto-dispatch.ts +48 -61
  362. package/src/resources/extensions/gsd/auto-model-selection.ts +41 -12
  363. package/src/resources/extensions/gsd/auto-post-unit.ts +40 -8
  364. package/src/resources/extensions/gsd/auto-prompts.ts +118 -35
  365. package/src/resources/extensions/gsd/auto-start.ts +42 -21
  366. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  367. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  368. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +14 -21
  369. package/src/resources/extensions/gsd/auto-verification.ts +26 -28
  370. package/src/resources/extensions/gsd/auto-worktree.ts +44 -94
  371. package/src/resources/extensions/gsd/auto.ts +52 -16
  372. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  373. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +37 -10
  374. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
  375. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  376. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
  377. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +251 -47
  378. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +352 -84
  379. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  380. package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
  381. package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
  382. package/src/resources/extensions/gsd/captures.ts +4 -6
  383. package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
  384. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  385. package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
  386. package/src/resources/extensions/gsd/consent-question.ts +431 -0
  387. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  388. package/src/resources/extensions/gsd/constants.ts +0 -3
  389. package/src/resources/extensions/gsd/crash-recovery.ts +13 -11
  390. package/src/resources/extensions/gsd/db/queries.ts +37 -0
  391. package/src/resources/extensions/gsd/db-writer.ts +11 -19
  392. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  393. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  394. package/src/resources/extensions/gsd/doctor-environment.ts +2 -7
  395. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  396. package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
  397. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +13 -15
  398. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  399. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  400. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  401. package/src/resources/extensions/gsd/files.ts +33 -12
  402. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  403. package/src/resources/extensions/gsd/gsd-db.ts +4 -3
  404. package/src/resources/extensions/gsd/guidance.ts +217 -0
  405. package/src/resources/extensions/gsd/guided-flow.ts +37 -28
  406. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  407. package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
  408. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  409. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  410. package/src/resources/extensions/gsd/migrate/safety.ts +4 -1
  411. package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
  412. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  413. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  414. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  415. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -4
  416. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  417. package/src/resources/extensions/gsd/paths.ts +33 -0
  418. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  419. package/src/resources/extensions/gsd/preferences-models.ts +12 -47
  420. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  421. package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  422. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
  423. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  424. package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -2
  425. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  426. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  427. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  428. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  429. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  430. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  431. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  432. package/src/resources/extensions/gsd/prompts/run-uat.md +7 -5
  433. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  434. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  435. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  436. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  437. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  438. package/src/resources/extensions/gsd/publication.ts +122 -0
  439. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  440. package/src/resources/extensions/gsd/recovery-classification.ts +42 -96
  441. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  442. package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
  443. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  444. package/src/resources/extensions/gsd/state.ts +9 -21
  445. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  446. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +97 -1
  447. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +198 -26
  448. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  449. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
  450. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  451. package/src/resources/extensions/gsd/tests/browser-automation-contract-fixture.ts +39 -0
  452. package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
  453. package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
  454. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  455. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -0
  456. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  457. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  458. package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
  459. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  460. package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
  461. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
  462. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
  463. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  464. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -0
  465. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
  466. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  467. package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
  468. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  469. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
  470. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
  471. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
  472. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
  473. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +27 -0
  474. package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
  475. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +2 -6
  476. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +53 -11
  477. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +73 -58
  478. package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
  479. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
  480. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
  481. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
  482. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
  483. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  484. package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
  485. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  486. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +138 -0
  487. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  488. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  489. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  490. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  491. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  492. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  493. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +157 -0
  494. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  495. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -1
  496. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  497. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  498. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
  499. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  500. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  501. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  502. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  503. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +112 -29
  504. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  505. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
  506. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  507. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  508. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  509. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
  510. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  511. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  512. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  513. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +275 -40
  514. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  515. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  516. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  517. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
  518. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  519. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  520. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  521. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  522. package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
  523. package/src/resources/extensions/gsd/tools/complete-task.ts +3 -2
  524. package/src/resources/extensions/gsd/tools/exec-tool.ts +8 -7
  525. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -8
  526. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  527. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  528. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  529. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
  530. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  531. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  532. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
  533. package/src/resources/extensions/gsd/uat-policy.ts +62 -16
  534. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  535. package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
  536. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  537. package/src/resources/extensions/gsd/unit-registry.ts +412 -0
  538. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  539. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  540. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  541. package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
  542. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  543. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  544. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  545. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  546. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  547. package/src/resources/extensions/gsd/worktree-git-recovery.ts +15 -9
  548. package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
  549. package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
  550. package/src/resources/extensions/gsd/worktree-root.ts +12 -0
  551. package/src/resources/extensions/gsd/worktree-session-state.ts +3 -5
  552. package/src/resources/extensions/gsd/worktree.ts +7 -1
  553. package/src/resources/extensions/search-the-web/native-search.ts +5 -3
  554. package/src/resources/extensions/shared/browser-contract.ts +66 -0
  555. package/src/resources/extensions/shared/gsd-browser-cli.ts +141 -6
  556. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  557. package/src/resources/shared/package-manager-detection.ts +1 -1
  558. package/src/resources/shared/package.json +3 -0
  559. package/src/resources/skills/create-skill/SKILL.md +3 -0
  560. package/src/resources/skills/create-skill/references/executable-code.md +1 -1
  561. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  562. package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
  563. package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
  564. package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
  565. package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
  566. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
  567. package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
  568. package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
  569. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  570. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  571. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  572. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  573. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  574. /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → FBNo5cT_chy7YNoAQsU3o}/_buildManifest.js +0 -0
  575. /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → FBNo5cT_chy7YNoAQsU3o}/_ssgManifest.js +0 -0
@@ -1,14 +1,16 @@
1
1
  // gsd-pi - Write gate runtime persistence and policy guards.
2
- import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, realpathSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { copyFileSync, existsSync, lstatSync, mkdirSync, readlinkSync, realpathSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
3
3
  import { isAbsolute, join, relative, resolve, sep } from "node:path";
4
4
  import { minimatch } from "minimatch";
5
5
  import { GSD_PHASE_SCOPE_DISPLAY_REASON, shouldBlockAutoUnitToolCall } from "../auto-unit-tool-scope.js";
6
- import { stripMcpToolPrefix } from "../mcp-tool-name.js";
6
+ import { canonicalToolName } from "../engine-hook-contract.js";
7
+ import { loadJsonFileOrNull } from "../json-persistence.js";
7
8
  import { getIsolationMode } from "../preferences.js";
8
9
  import { compileSubagentPermissionContract } from "../unit-context-manifest.js";
9
10
  import { logWarning } from "../workflow-logger.js";
10
11
  import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "../worktree-root.js";
11
12
  import { worktreesDirs } from "../worktree-placement.js";
13
+ import { evaluateGateAnswer } from "../consent-verdict.js";
12
14
  /**
13
15
  * Regex matching milestone CONTEXT.md file names in both legacy M001
14
16
  * and unique M001-abc123 formats. Exported so regex-hardening tests
@@ -103,9 +105,6 @@ const GATE_QUESTION_PATTERNS = [
103
105
  const GATE_SAFE_TOOLS = new Set([
104
106
  "ask_user_questions",
105
107
  ]);
106
- export function canonicalToolName(toolName) {
107
- return stripMcpToolPrefix(toolName);
108
- }
109
108
  /**
110
109
  * Persistence is ON by default (opt-out).
111
110
  * Set GSD_PERSIST_WRITE_GATE_STATE="0" or GSD_PERSIST_WRITE_GATE_STATE="false"
@@ -144,13 +143,11 @@ function currentWriteGateSnapshot(basePath = process.cwd()) {
144
143
  pendingGateId: state.pendingGateId,
145
144
  };
146
145
  }
147
- function persistWriteGateSnapshot(basePath) {
148
- if (!shouldPersistWriteGateSnapshot())
149
- return;
146
+ function writeSnapshotFileAtomic(basePath, snapshot) {
150
147
  const path = writeGateSnapshotPath(basePath);
151
148
  ensureWriteGateSnapshotDirectory(basePath);
152
149
  const tempPath = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
153
- writeFileSync(tempPath, JSON.stringify(currentWriteGateSnapshot(basePath), null, 2), "utf-8");
150
+ writeFileSync(tempPath, JSON.stringify(snapshot, null, 2), "utf-8");
154
151
  try {
155
152
  renameSync(tempPath, path);
156
153
  }
@@ -166,6 +163,18 @@ function persistWriteGateSnapshot(basePath) {
166
163
  }
167
164
  }
168
165
  }
166
+ /**
167
+ * Persist the current in-memory state for `basePath`, stamped with the
168
+ * writer provenance tag. Callers (mutateWriteGateState / childMutate) are
169
+ * responsible for first reconciling in-memory content against the disk
170
+ * snapshot — the read-merge-write sequence is synchronous, so a concurrent
171
+ * writer's update is folded in by that unconditional pre-persist read.
172
+ */
173
+ function persistWriteGateSnapshot(basePath, writer) {
174
+ if (!shouldPersistWriteGateSnapshot())
175
+ return;
176
+ writeSnapshotFileAtomic(basePath, { ...currentWriteGateSnapshot(basePath), writer });
177
+ }
169
178
  function clearPersistedWriteGateSnapshot(basePath) {
170
179
  if (!shouldPersistWriteGateSnapshot())
171
180
  return;
@@ -190,6 +199,7 @@ function normalizeWriteGateSnapshot(value) {
190
199
  verifiedApprovalGates: [...new Set(verifiedGates)].sort(),
191
200
  activeQueuePhase: record.activeQueuePhase === true,
192
201
  pendingGateId: typeof record.pendingGateId === "string" ? record.pendingGateId : null,
202
+ ...(record.writer === "host" || record.writer === "child" ? { writer: record.writer } : {}),
193
203
  };
194
204
  }
195
205
  const EMPTY_SNAPSHOT = {
@@ -198,6 +208,14 @@ const EMPTY_SNAPSHOT = {
198
208
  activeQueuePhase: false,
199
209
  pendingGateId: null,
200
210
  };
211
+ /**
212
+ * Read the snapshot file as it exists on disk. Returns null when the file
213
+ * is missing or unparseable (no in-memory fallback — callers decide).
214
+ */
215
+ function readDiskSnapshot(basePath) {
216
+ const raw = loadJsonFileOrNull(writeGateSnapshotPath(basePath), (data) => typeof data === "object" && data !== null);
217
+ return raw === null ? null : normalizeWriteGateSnapshot(raw);
218
+ }
201
219
  export function loadWriteGateSnapshot(basePath) {
202
220
  const path = writeGateSnapshotPath(basePath);
203
221
  if (!existsSync(path)) {
@@ -208,29 +226,112 @@ export function loadWriteGateSnapshot(basePath) {
208
226
  return EMPTY_SNAPSHOT;
209
227
  return currentWriteGateSnapshot(basePath);
210
228
  }
211
- try {
212
- return normalizeWriteGateSnapshot(JSON.parse(readFileSync(path, "utf-8")));
213
- }
214
- catch {
215
- return currentWriteGateSnapshot(basePath);
229
+ const disk = readDiskSnapshot(basePath);
230
+ return disk ?? currentWriteGateSnapshot(basePath);
231
+ }
232
+ /**
233
+ * Reconcile a disk snapshot into the in-memory state. This is THE merge
234
+ * rule for the two-process seam:
235
+ *
236
+ * - verifications are a grow-only union: a milestone/gate verified by
237
+ * either process is never lost to a stale write from the other;
238
+ * - activeQueuePhase and pendingGateId take the disk value (last writer
239
+ * wins — matches the long-standing refresh semantics, and keeps
240
+ * "delete the snapshot file to clear the HARD BLOCK" working);
241
+ * - verified wins over pending: if the merged verified sets already cover
242
+ * the pending gate (gate id verified, or its depth milestone verified),
243
+ * the pending re-arm is dropped. This generalizes the ad-hoc re-arm
244
+ * guard that previously protected only the tool_execution_start window.
245
+ */
246
+ function mergeSnapshotIntoState(state, disk) {
247
+ for (const milestone of disk.verifiedDepthMilestones)
248
+ state.verifiedDepthMilestones.add(milestone);
249
+ for (const gate of disk.verifiedApprovalGates ?? [])
250
+ state.verifiedApprovalGates.add(gate);
251
+ state.activeQueuePhase = disk.activeQueuePhase;
252
+ state.pendingGateId = disk.pendingGateId;
253
+ dropVerifiedPendingGate(state);
254
+ }
255
+ /** Verified-on-disk wins over a pending re-arm (see mergeSnapshotIntoState). */
256
+ function dropVerifiedPendingGate(state) {
257
+ const pending = state.pendingGateId;
258
+ if (!pending)
259
+ return;
260
+ const milestoneId = extractDepthVerificationMilestoneId(pending);
261
+ if (state.verifiedApprovalGates.has(pending) ||
262
+ (milestoneId !== null && state.verifiedDepthMilestones.has(milestoneId))) {
263
+ state.pendingGateId = null;
216
264
  }
217
265
  }
266
+ function replaceStateFromSnapshot(state, snapshot) {
267
+ state.pendingGateId = snapshot.pendingGateId;
268
+ state.activeQueuePhase = snapshot.activeQueuePhase;
269
+ state.verifiedDepthMilestones = new Set(snapshot.verifiedDepthMilestones);
270
+ state.verifiedApprovalGates = new Set(snapshot.verifiedApprovalGates ?? []);
271
+ }
218
272
  /**
219
- * Merge the persisted write-gate snapshot into the in-process Map entry.
273
+ * Reconcile the persisted write-gate snapshot into the in-process Map entry.
220
274
  * The workflow MCP server runs in a child process and records depth
221
275
  * verification there; without this refresh the extension host keeps stale
222
276
  * pending-gate memory and `activateDeferredApprovalGate` can re-arm a gate
223
277
  * that the subprocess already cleared on disk.
278
+ *
279
+ * Uses the union merge rule (mergeSnapshotIntoState) when a readable
280
+ * snapshot file exists; a missing or unparseable file is a full reset
281
+ * (replace with empty) so deleting the file still clears all gate state,
282
+ * and a corrupt file does not leave stale `pendingGateId` in memory for
283
+ * the next mutation to persist back.
284
+ *
285
+ * Returns the reconciled snapshot so callers that need to inspect it
286
+ * (e.g. re-arm guards) avoid a second disk read.
224
287
  */
225
288
  export function refreshWriteGateStateFromDisk(basePath) {
226
289
  if (!shouldPersistWriteGateSnapshot())
227
- return;
228
- const snapshot = loadWriteGateSnapshot(basePath);
290
+ return currentWriteGateSnapshot(basePath);
229
291
  const state = getWriteGateState(basePath);
230
- state.pendingGateId = snapshot.pendingGateId;
231
- state.activeQueuePhase = snapshot.activeQueuePhase;
232
- state.verifiedDepthMilestones = new Set(snapshot.verifiedDepthMilestones);
233
- state.verifiedApprovalGates = new Set(snapshot.verifiedApprovalGates ?? []);
292
+ const disk = readDiskSnapshot(basePath);
293
+ if (disk) {
294
+ mergeSnapshotIntoState(state, disk);
295
+ }
296
+ else {
297
+ replaceStateFromSnapshot(state, EMPTY_SNAPSHOT);
298
+ }
299
+ return currentWriteGateSnapshot(basePath);
300
+ }
301
+ /**
302
+ * Read-modify-write primitive for gate mutations. Reconciles the disk
303
+ * snapshot into memory (union merge), applies the mutation on top, then
304
+ * persists. The whole sequence is synchronous, so the reconcile read
305
+ * doubles as the pre-persist merge of concurrent writes — there is no
306
+ * version field; the read-merge-write is simply unconditional.
307
+ *
308
+ * The mutate callback sees the already-reconciled state, so policy checks
309
+ * (e.g. host setPending's verified-on-disk-wins guard) can live inside it
310
+ * without a second disk read. Returning `false` from the callback aborts:
311
+ * nothing is persisted and this function returns false.
312
+ *
313
+ * `reconcile: false` skips the disk merge — used for intentional full
314
+ * resets where re-unioning disk verifications would defeat the reset.
315
+ */
316
+ function mutateWriteGateState(basePath, mutate, opts) {
317
+ const state = getWriteGateState(basePath);
318
+ if (shouldPersistWriteGateSnapshot() && (opts?.reconcile ?? true)) {
319
+ const disk = readDiskSnapshot(basePath);
320
+ if (disk) {
321
+ mergeSnapshotIntoState(state, disk);
322
+ }
323
+ else {
324
+ // Missing OR unparseable on disk: treat as a full reset. Keeping
325
+ // stale in-memory state across a corrupt snapshot would persist it
326
+ // back on this very mutation and defeat the documented
327
+ // "delete the file to clear the HARD BLOCK gate" escape hatch.
328
+ replaceStateFromSnapshot(state, EMPTY_SNAPSHOT);
329
+ }
330
+ }
331
+ if (mutate(state) === false)
332
+ return false;
333
+ persistWriteGateSnapshot(basePath, opts?.writer ?? defaultWriteGateWriter());
334
+ return true;
234
335
  }
235
336
  export function isDepthVerified(basePath = process.cwd()) {
236
337
  return getWriteGateState(basePath).verifiedDepthMilestones.size > 0;
@@ -253,31 +354,34 @@ export function isQueuePhaseActive(basePath = process.cwd()) {
253
354
  return getWriteGateState(basePath).activeQueuePhase;
254
355
  }
255
356
  export function setQueuePhaseActive(active, basePath) {
256
- getWriteGateState(basePath).activeQueuePhase = active;
257
- persistWriteGateSnapshot(basePath);
357
+ mutateWriteGateState(basePath, (state) => {
358
+ state.activeQueuePhase = active;
359
+ });
258
360
  }
259
361
  export function resetWriteGateState(basePath) {
260
- const state = getWriteGateState(basePath);
261
- state.verifiedDepthMilestones.clear();
262
- state.verifiedApprovalGates.clear();
263
- state.pendingGateId = null;
264
- persistWriteGateSnapshot(basePath);
362
+ mutateWriteGateState(basePath, (state) => {
363
+ state.verifiedDepthMilestones.clear();
364
+ state.verifiedApprovalGates.clear();
365
+ state.pendingGateId = null;
366
+ }, { reconcile: false });
265
367
  }
266
368
  export function clearDiscussionFlowState(basePath) {
267
369
  writeGateStatesByBasePath.delete(writeGateStateKey(basePath));
268
370
  clearPersistedWriteGateSnapshot(basePath);
269
371
  }
372
+ /**
373
+ * Ambient (env-sniffed) export, reserved for the child's dynamic-import
374
+ * surface (packages/mcp-server) and module-internal use. Host-owned modules
375
+ * (register-hooks, auto-dispatch, …) must call
376
+ * hostWriteGateAdapter.markDepthVerified explicitly so a leaked
377
+ * GSD_WORKFLOW_* env variable cannot silently flip them to child semantics.
378
+ */
270
379
  export function markDepthVerified(milestoneId, basePath = process.cwd()) {
271
- if (!milestoneId)
272
- return;
273
- getWriteGateState(basePath).verifiedDepthMilestones.add(milestoneId);
274
- persistWriteGateSnapshot(basePath);
380
+ defaultWriteGateAdapter().markDepthVerified(milestoneId, basePath);
275
381
  }
382
+ /** Ambient export for the child's dynamic-import surface — see markDepthVerified. */
276
383
  export function markApprovalGateVerified(gateId, basePath = process.cwd()) {
277
- if (!gateId)
278
- return;
279
- getWriteGateState(basePath).verifiedApprovalGates.add(gateId);
280
- persistWriteGateSnapshot(basePath);
384
+ defaultWriteGateAdapter().markApprovalGateVerified(gateId, basePath);
281
385
  }
282
386
  export function isApprovalGateVerifiedInSnapshot(snapshot, gateId) {
283
387
  if (!gateId)
@@ -306,30 +410,147 @@ function extractContextMilestoneId(inputPath) {
306
410
  return match?.[1] ?? null;
307
411
  }
308
412
  /**
309
- * Mark a gate as pending (called when ask_user_questions is invoked with a gate ID).
413
+ * Mark a gate as pending (called when ask_user_questions is invoked with a
414
+ * gate ID). Delegates to the process's default adapter: in the workflow MCP
415
+ * child the arm is unconditional (a fresh question intentionally revokes
416
+ * prior verification); in the host the adapter's verified-on-disk-wins
417
+ * guard applies and a suppressed arm returns false.
418
+ *
419
+ * Ambient (env-sniffed) export, reserved for the child's dynamic-import
420
+ * surface (packages/mcp-server). Host-owned modules must call
421
+ * hostWriteGateAdapter.setPending explicitly.
310
422
  */
311
423
  export function setPendingGate(gateId, basePath) {
312
- const state = getWriteGateState(basePath);
424
+ return defaultWriteGateAdapter().setPending(gateId, basePath);
425
+ }
426
+ /** Arm `gateId` on a reconciled state, revoking its prior verification. */
427
+ function armPendingGate(state, gateId) {
313
428
  state.pendingGateId = gateId;
314
429
  state.verifiedApprovalGates.delete(gateId);
315
430
  const milestoneId = extractDepthVerificationMilestoneId(gateId);
316
431
  if (milestoneId)
317
432
  state.verifiedDepthMilestones.delete(milestoneId);
318
- persistWriteGateSnapshot(basePath);
319
433
  }
320
434
  /**
321
435
  * Clear the pending gate (called when the user confirms).
436
+ * Ambient export for the child's dynamic-import surface — host-owned
437
+ * modules must call hostWriteGateAdapter.clearPending explicitly.
322
438
  */
323
439
  export function clearPendingGate(basePath) {
324
- getWriteGateState(basePath).pendingGateId = null;
325
- persistWriteGateSnapshot(basePath);
440
+ defaultWriteGateAdapter().clearPending(basePath);
326
441
  }
327
442
  /**
328
443
  * Get the currently pending gate, if any.
444
+ * Ambient export for the child's dynamic-import surface — host-owned
445
+ * modules should prefer hostWriteGateAdapter.readState.
329
446
  */
330
447
  export function getPendingGate(basePath = process.cwd()) {
331
- refreshWriteGateStateFromDisk(basePath);
332
- return getWriteGateState(basePath).pendingGateId;
448
+ return defaultWriteGateAdapter().readState(basePath).pendingGateId;
449
+ }
450
+ /**
451
+ * HOST adapter: in-memory state + reconcile-on-read. Disk verifications are
452
+ * never lost (union merge), and a gate verified on disk wins over an
453
+ * in-memory pending re-arm — setPending refuses to clobber a verification
454
+ * the child already recorded. This generalizes the ad-hoc re-arm guard that
455
+ * previously protected only the tool_execution_start window in
456
+ * register-hooks.ts.
457
+ */
458
+ export const hostWriteGateAdapter = {
459
+ writer: "host",
460
+ readState(basePath) {
461
+ return refreshWriteGateStateFromDisk(basePath);
462
+ },
463
+ markDepthVerified(milestoneId, basePath) {
464
+ if (!milestoneId)
465
+ return;
466
+ mutateWriteGateState(basePath, (state) => {
467
+ state.verifiedDepthMilestones.add(milestoneId);
468
+ }, { writer: "host" });
469
+ },
470
+ markApprovalGateVerified(gateId, basePath) {
471
+ if (!gateId)
472
+ return;
473
+ mutateWriteGateState(basePath, (state) => {
474
+ state.verifiedApprovalGates.add(gateId);
475
+ }, { writer: "host" });
476
+ },
477
+ setPending(gateId, basePath) {
478
+ // The verified-check runs inside the mutate callback so the single
479
+ // reconcile read in mutateWriteGateState serves both the guard and the
480
+ // pre-persist merge. A suppressed arm aborts without persisting.
481
+ return mutateWriteGateState(basePath, (state) => {
482
+ if (state.verifiedApprovalGates.has(gateId))
483
+ return false;
484
+ const milestoneId = extractDepthVerificationMilestoneId(gateId);
485
+ if (milestoneId && state.verifiedDepthMilestones.has(milestoneId))
486
+ return false;
487
+ armPendingGate(state, gateId);
488
+ }, { writer: "host" });
489
+ },
490
+ clearPending(basePath) {
491
+ mutateWriteGateState(basePath, (state) => {
492
+ state.pendingGateId = null;
493
+ }, { writer: "host" });
494
+ },
495
+ };
496
+ /**
497
+ * CHILD adapter: write-through with always-fresh reads — load the disk
498
+ * snapshot, mutate, persist. No cross-turn in-memory state is trusted: the
499
+ * in-process Map entry is replaced from disk before every mutation so a
500
+ * long-lived MCP child never resurrects state the host has since changed.
501
+ */
502
+ export const childWriteGateAdapter = {
503
+ writer: "child",
504
+ readState(basePath) {
505
+ return loadWriteGateSnapshot(basePath);
506
+ },
507
+ markDepthVerified(milestoneId, basePath) {
508
+ if (!milestoneId)
509
+ return;
510
+ childMutate(basePath, (state) => {
511
+ state.verifiedDepthMilestones.add(milestoneId);
512
+ });
513
+ },
514
+ markApprovalGateVerified(gateId, basePath) {
515
+ if (!gateId)
516
+ return;
517
+ childMutate(basePath, (state) => {
518
+ state.verifiedApprovalGates.add(gateId);
519
+ });
520
+ },
521
+ setPending(gateId, basePath) {
522
+ childMutate(basePath, (state) => armPendingGate(state, gateId));
523
+ return true;
524
+ },
525
+ clearPending(basePath) {
526
+ childMutate(basePath, (state) => {
527
+ state.pendingGateId = null;
528
+ });
529
+ },
530
+ };
531
+ function childMutate(basePath, mutate) {
532
+ const state = getWriteGateState(basePath);
533
+ if (shouldPersistWriteGateSnapshot()) {
534
+ // Always-fresh: disk is the only truth for the child; discard any
535
+ // cross-turn in-memory residue before mutating.
536
+ replaceStateFromSnapshot(state, readDiskSnapshot(basePath) ?? EMPTY_SNAPSHOT);
537
+ }
538
+ mutate(state);
539
+ persistWriteGateSnapshot(basePath, "child");
540
+ }
541
+ /**
542
+ * Which adapter the module-level convenience exports (markDepthVerified,
543
+ * setPendingGate, …) delegate to. The workflow MCP child is spawned with
544
+ * GSD_WORKFLOW_WRITE_GATE_MODULE / GSD_WORKFLOW_PROJECT_ROOT in its
545
+ * environment (workflow-mcp.ts), so when this module is dynamically imported
546
+ * inside that process the child adapter is selected automatically; the
547
+ * extension host process has neither variable and stays on the host adapter.
548
+ */
549
+ export function defaultWriteGateWriter(env = process.env) {
550
+ return env.GSD_WORKFLOW_WRITE_GATE_MODULE || env.GSD_WORKFLOW_PROJECT_ROOT ? "child" : "host";
551
+ }
552
+ function defaultWriteGateAdapter() {
553
+ return defaultWriteGateWriter() === "child" ? childWriteGateAdapter : hostWriteGateAdapter;
333
554
  }
334
555
  /**
335
556
  * Check whether a tool call should be blocked because a discussion gate
@@ -379,36 +600,15 @@ export function shouldBlockPendingGateBashInSnapshot(snapshot, command, _milesto
379
600
  ].join(" "),
380
601
  };
381
602
  }
382
- /**
383
- * Check whether a depth_verification answer confirms the discussion is complete.
384
- * Uses structural validation: the selected answer must exactly match the first
385
- * option label from the question definition (the confirmation option by convention).
386
- * This rejects free-form "Other" text, decline options, and garbage input without
387
- * coupling to any specific label substring.
388
- *
389
- * @param selected The answer's selected value from details.response.answers[id].selected
390
- * @param options The question's options array from event.input.questions[n].options
391
- */
392
- export function isDepthConfirmationAnswer(selected, options) {
393
- const value = Array.isArray(selected) ? selected[0] : selected;
394
- if (typeof value !== "string" || !value)
395
- return false;
396
- // If options are available, structurally validate: selected must exactly match
397
- // the first option (confirmation) label. Rejects free-form "Other" and decline options.
398
- if (Array.isArray(options) && options.length > 0) {
399
- const confirmLabel = options[0]?.label;
400
- return typeof confirmLabel === "string" && value === confirmLabel;
401
- }
402
- // Fail-closed: no options means we cannot structurally validate the answer.
403
- // Returning false prevents any free-form string from unlocking the gate.
404
- return false;
405
- }
603
+ // The structural depth-confirmation validator lives in the consent-verdict
604
+ // leaf (../consent-verdict.ts) so the write gate and the Consent Question
605
+ // module share one verdict engine without an import cycle. Re-exported here
606
+ // because the workflow MCP child loads this module by dist path and validates
607
+ // the function is present (packages/mcp-server/src/server.ts).
608
+ export { isDepthConfirmationAnswer } from "../consent-verdict.js";
406
609
  function findGateQuestion(questions, gateId) {
407
610
  return questions.find((question) => question?.id === gateId);
408
611
  }
409
- function readSelectedGateAnswer(details, questionId) {
410
- return details.response?.answers?.[questionId]?.selected;
411
- }
412
612
  function verifyAnsweredGate(basePath, question, fallbackMilestoneId) {
413
613
  const gateId = typeof question.id === "string" ? question.id : "";
414
614
  const milestoneId = extractDepthVerificationMilestoneId(gateId) ?? fallbackMilestoneId ?? null;
@@ -417,6 +617,30 @@ function verifyAnsweredGate(basePath, question, fallbackMilestoneId) {
417
617
  clearPendingGate(basePath);
418
618
  return { status: "verified", gateId, milestoneId };
419
619
  }
620
+ /** Map an unresolved (non-verified) gate verdict to the caller-facing result. */
621
+ function unresolvedGateResult(verdict, gateId, details) {
622
+ if (verdict === "declined")
623
+ return { status: "declined", gateId };
624
+ // "waiting" (and the unreachable post-cancel case): an empty selection is
625
+ // not an answer — keep the gate pending and make the caller pause.
626
+ return {
627
+ status: "waiting",
628
+ pendingGateId: gateId,
629
+ interrupted: details.interrupted === true,
630
+ };
631
+ }
632
+ /**
633
+ * Apply an ask_user_questions round to durable gate state. The per-question
634
+ * VERDICT comes from the consent-verdict leaf (evaluateGateAnswer) — the same
635
+ * engine the Consent Question module uses — so write-gate only owns the
636
+ * persistence/arming side effects:
637
+ *
638
+ * - "verified" verdict → markApprovalGateVerified/markDepthVerified/clearPendingGate.
639
+ * - "declined" verdict → no state change; the gate (if armed) stays pending.
640
+ * - "waiting" verdict (empty/missing selection) → no state change; reported as
641
+ * "waiting" so callers pause instead of proceeding (fail-closed; an empty
642
+ * answer is never an answer).
643
+ */
420
644
  export function applyAskUserQuestionsGateResult(options) {
421
645
  const { basePath, questions, details, fallbackMilestoneId } = options;
422
646
  const currentPendingGate = getPendingGate(basePath);
@@ -430,11 +654,11 @@ export function applyAskUserQuestionsGateResult(options) {
430
654
  }
431
655
  const pendingQuestion = findGateQuestion(questions, currentPendingGate);
432
656
  if (pendingQuestion) {
433
- const selected = readSelectedGateAnswer(details, currentPendingGate);
434
- if (isDepthConfirmationAnswer(selected, pendingQuestion.options)) {
657
+ const verdict = evaluateGateAnswer(pendingQuestion, details);
658
+ if (verdict === "verified") {
435
659
  return verifyAnsweredGate(basePath, pendingQuestion, fallbackMilestoneId);
436
660
  }
437
- return { status: "answered", gateId: currentPendingGate };
661
+ return unresolvedGateResult(verdict, currentPendingGate, details);
438
662
  }
439
663
  }
440
664
  if (details.cancelled || !details.response)
@@ -442,12 +666,14 @@ export function applyAskUserQuestionsGateResult(options) {
442
666
  for (const question of questions) {
443
667
  if (typeof question.id !== "string" || !isGateQuestionId(question.id))
444
668
  continue;
445
- const selected = readSelectedGateAnswer(details, question.id);
446
- if (!isDepthConfirmationAnswer(selected, question.options)) {
447
- return { status: "answered", gateId: question.id };
669
+ const verdict = evaluateGateAnswer(question, details);
670
+ if (verdict !== "verified") {
671
+ return unresolvedGateResult(verdict, question.id, details);
448
672
  }
449
673
  if (currentPendingGate && question.id !== currentPendingGate) {
450
- return { status: "answered", gateId: currentPendingGate };
674
+ // A different gate than the armed one was confirmed — the armed gate is
675
+ // still unresolved, so do not verify and let discussion continue.
676
+ return { status: "declined", gateId: currentPendingGate };
451
677
  }
452
678
  return verifyAnsweredGate(basePath, question, fallbackMilestoneId);
453
679
  }
@@ -11,3 +11,5 @@ export const SLICE_BRANCH_RE = /^gsd\/(?:([a-zA-Z0-9_-]+)\/)?(M\d+(?:-[a-z0-9]{6
11
11
  export const QUICK_BRANCH_RE = /^gsd\/quick\//;
12
12
  /** Matches GSD-generated workflow template branches, not arbitrary user gsd/* branches. */
13
13
  export const WORKFLOW_BRANCH_RE = /^gsd\/(?:hotfix|bugfix|small-feature|refactor|spike|security-audit|dep-upgrade|full-project)\//;
14
+ /** Auto-mode milestone branch prefix: milestone/<MID>. */
15
+ export const MILESTONE_BRANCH_PREFIX = "milestone/";
@@ -0,0 +1,83 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ import { resolveAmbientBrowserEngineResolution, resolveBrowserEngineResolution, } from "../browser-tools/engine/selection.js";
4
+ import { resolveGsdBrowserCliAvailability, resolveGsdBrowserDaemonStartInvocation, } from "../shared/gsd-browser-cli.js";
5
+ import { uatTypeIncludesBrowser } from "./uat-policy.js";
6
+ const DEFAULT_DAEMON_START_TIMEOUT_MS = 30_000;
7
+ function isEnvDisabled(value) {
8
+ if (!value)
9
+ return false;
10
+ const normalized = value.trim().toLowerCase();
11
+ return normalized === "0" || normalized === "false" || normalized === "off";
12
+ }
13
+ function isWarmUpDisabled(env = process.env) {
14
+ const value = env.GSD_BROWSER_WARMUP?.trim().toLowerCase();
15
+ return value === "0" || value === "false" || value === "off";
16
+ }
17
+ /** Active engine for warm-up: explicit env override, else session-committed ambient resolution. */
18
+ function resolveActiveBrowserEngine(projectRoot, env) {
19
+ if (env.GSD_BROWSER_ENGINE?.trim()) {
20
+ return resolveBrowserEngineResolution(env, projectRoot).engine;
21
+ }
22
+ return resolveAmbientBrowserEngineResolution(projectRoot).engine;
23
+ }
24
+ export function shouldWarmBrowserDaemonForUat(ctx) {
25
+ if (!uatTypeIncludesBrowser(ctx.uatType))
26
+ return false;
27
+ const env = ctx.env ?? process.env;
28
+ if (isWarmUpDisabled(env))
29
+ return false;
30
+ if (isEnvDisabled(env.GSD_BROWSER_MCP_ENABLED))
31
+ return false;
32
+ const availability = resolveGsdBrowserCliAvailability(env);
33
+ if (!availability.available)
34
+ return false;
35
+ const projectRoot = resolve(ctx.projectRoot);
36
+ return resolveActiveBrowserEngine(projectRoot, env) === "gsd-browser";
37
+ }
38
+ export function ensureBrowserDaemonStarted(projectRoot, options = {}) {
39
+ const env = options.env ?? process.env;
40
+ const availability = resolveGsdBrowserCliAvailability(env);
41
+ if (!availability.available) {
42
+ return { ok: false, error: availability.detail };
43
+ }
44
+ let invocation;
45
+ try {
46
+ invocation = resolveGsdBrowserDaemonStartInvocation(projectRoot, env);
47
+ }
48
+ catch (error) {
49
+ return {
50
+ ok: false,
51
+ error: error instanceof Error ? error.message : String(error),
52
+ };
53
+ }
54
+ try {
55
+ execFileSync(invocation.command, invocation.args, {
56
+ cwd: invocation.cwd,
57
+ env: { ...process.env, ...env, ...(invocation.env ?? {}) },
58
+ stdio: ["ignore", "pipe", "pipe"],
59
+ timeout: options.timeoutMs ?? DEFAULT_DAEMON_START_TIMEOUT_MS,
60
+ encoding: "utf-8",
61
+ });
62
+ return { ok: true };
63
+ }
64
+ catch (error) {
65
+ return {
66
+ ok: false,
67
+ error: error instanceof Error ? error.message : String(error),
68
+ };
69
+ }
70
+ }
71
+ /**
72
+ * Best-effort pre-warm of the gsd-browser session daemon before browser-backed
73
+ * run-uat dispatch. Returns an actionable stop reason when warm-up is required
74
+ * but fails; returns null when warm-up is skipped or succeeds.
75
+ */
76
+ export function prepareBrowserDaemonForUat(ctx) {
77
+ if (!shouldWarmBrowserDaemonForUat(ctx))
78
+ return null;
79
+ const result = ensureBrowserDaemonStarted(ctx.projectRoot, { env: ctx.env });
80
+ if (result.ok)
81
+ return null;
82
+ return `Cannot dispatch browser-backed run-uat: gsd-browser daemon failed to start (${result.error}). Ensure Chrome/Chromium is installed, run \`gsd-browser daemon health\` with the project session flags from .mcp.json, or set GSD_BROWSER_PATH to a Chromium binary.`;
83
+ }
@@ -1,8 +1,14 @@
1
1
  // Project/App: gsd-pi
2
2
  // File Purpose: Shared browser-observable UAT requirement and evidence detection.
3
- export const BROWSER_REQUIREMENT_RE = /\b(?:file:\/\/|localhost|playwright|chrome|screenshot|snapshot|browser_(?:assert|batch|find|verify|snapshot_refs))\b|\b(?:open|launch|navigate|load|visit|serve|start)\b.{0,80}\b(?:browser|page|localhost|file:\/\/)\b|\bbrowser\s+(?:check|session|test|uat|tool|automation|interaction|flow)\b/i;
3
+ import { BROWSER_EVIDENCE_SIGNAL_TOOL_NAMES } from "../shared/browser-contract.js";
4
+ // Alternation fragment over the contract's evidence-signal names, e.g.
5
+ // `browser_(?:assert|batch|...)`. The names are `browser_`-prefixed
6
+ // identifiers (pinned by tests/browser-contract.test.ts), so no escaping is
7
+ // needed.
8
+ const BROWSER_TOOL_SIGNAL = `browser_(?:${BROWSER_EVIDENCE_SIGNAL_TOOL_NAMES.map((name) => name.slice("browser_".length)).join("|")})`;
9
+ export const BROWSER_REQUIREMENT_RE = new RegExp(String.raw `\b(?:file://|localhost|playwright|chrome|screenshot|snapshot|${BROWSER_TOOL_SIGNAL})\b|\b(?:open|launch|navigate|load|visit|serve|start)\b.{0,80}\b(?:browser|page|localhost|file://)\b|\bbrowser\s+(?:check|session|test|uat|tool|automation|interaction|flow)\b`, "i");
4
10
  export const NO_BROWSER_EVIDENCE_RE = /\b(?:no|without|not|wasn'?t|isn'?t)\s+(?:automated\s+)?(?:live\s+)?browser(?:\s+(?:session|test|uat))?|\bno\s+automated\s+browser\b|\bnot\s+conducted\b/i;
5
- export const BROWSER_RUNTIME_RE = /\b(?:browser|playwright|chrome|camoufox|browser_(?:assert|batch|find|verify|snapshot_refs)|screenshot|snapshot|file:\/\/|localhost)\b/i;
11
+ export const BROWSER_RUNTIME_RE = new RegExp(String.raw `\b(?:browser|playwright|chrome|camoufox|${BROWSER_TOOL_SIGNAL}|screenshot|snapshot|file://|localhost)\b`, "i");
6
12
  export const BROWSER_ACTION_RE = /\b(?:open(?:ed)?|navigate(?:d)?|click(?:ed)?|type(?:d)?|reload(?:ed)?|capture(?:d)?|screenshot|snapshot)\b/i;
7
13
  export const BROWSER_ASSERTION_RE = /\b(?:assert(?:ed|ion)?|observed|confirmed|verified|expected|visible|text|count|label|strikethrough|localstorage|screenshot|snapshot|passed)\b/i;
8
14
  const NON_REQUIREMENT_BROWSER_HEADING_RE = /^(?:not\s+proven|not\s+covered|out\s+of\s+scope|deferred|follow-?ups?|known\s+limitations|notes\s+for\s+tester)\b/i;
@@ -11,7 +11,7 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
11
11
  import { join, resolve } from "node:path";
12
12
  import { randomUUID } from "node:crypto";
13
13
  import { gsdRoot } from "./paths.js";
14
- import { findWorktreeSegment } from "./worktree-root.js";
14
+ import { projectRootFromWorktreePath } from "./worktree-root.js";
15
15
  // ─── Constants ────────────────────────────────────────────────────────────────
16
16
  const CAPTURES_FILENAME = "CAPTURES.md";
17
17
  const VALID_CLASSIFICATIONS = [
@@ -30,11 +30,9 @@ const VALID_CLASSIFICATIONS = [
30
30
  * directory that contains `.gsd/worktrees/` — that's the project root.
31
31
  */
32
32
  export function resolveCapturesPath(basePath) {
33
- const resolved = resolve(basePath);
34
- const segment = findWorktreeSegment(resolved.replaceAll("\\", "/"));
35
- if (segment) {
36
- // basePath is inside a worktree — resolve to project root
37
- const projectRoot = resolved.slice(0, segment.gsdIdx);
33
+ // If basePath is inside a worktree, resolve to the project root.
34
+ const projectRoot = projectRootFromWorktreePath(resolve(basePath));
35
+ if (projectRoot) {
38
36
  return join(projectRoot, ".gsd", CAPTURES_FILENAME);
39
37
  }
40
38
  return join(gsdRoot(basePath), CAPTURES_FILENAME);