@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
@@ -0,0 +1,209 @@
1
+ // gsd-pi — ADR-032 Unit Closeout module tests (Interactive Closeout adapter path).
2
+ //
3
+ // All git/preference/notification effects go through the injected deps seam —
4
+ // no real repos, no notification store state.
5
+
6
+ import test from "node:test";
7
+ import assert from "node:assert/strict";
8
+
9
+ import {
10
+ closeUnit,
11
+ isUnitCloseoutTool,
12
+ runInteractiveUnitCloseout,
13
+ type UnitCloseoutDeps,
14
+ } from "../unit-closeout.ts";
15
+
16
+ interface DepsLog {
17
+ commits: Array<{ unitType: string; unitId: string }>;
18
+ notices: Array<{ message: string; severity: string }>;
19
+ }
20
+
21
+ function makeDeps(overrides: {
22
+ isolation?: "none" | "worktree" | "branch";
23
+ branch?: string | null;
24
+ commitResult?: string | null | (() => string | null);
25
+ } = {}): { deps: UnitCloseoutDeps; log: DepsLog } {
26
+ const log: DepsLog = { commits: [], notices: [] };
27
+ const deps: UnitCloseoutDeps = {
28
+ isolationMode: () => overrides.isolation ?? "none",
29
+ currentBranch: () => (overrides.branch === undefined ? "main" : overrides.branch),
30
+ commit: (_basePath, unitType, unitId) => {
31
+ log.commits.push({ unitType, unitId });
32
+ const result = overrides.commitResult;
33
+ if (typeof result === "function") return result();
34
+ return result === undefined ? "chore(gsd): closeout" : result;
35
+ },
36
+ notify: (message, severity) => {
37
+ log.notices.push({ message, severity });
38
+ },
39
+ };
40
+ return { deps, log };
41
+ }
42
+
43
+ const BASE = "/tmp/closeout-test-project";
44
+
45
+ test("task boundary commits and stays quiet", () => {
46
+ const { deps, log } = makeDeps({ isolation: "worktree" });
47
+ const result = closeUnit(
48
+ { basePath: BASE, unitType: "execute-task", unitId: "M001/S01/T01", boundary: "task", outcome: "complete" },
49
+ deps,
50
+ );
51
+ assert.equal(result.gitVerdict, "committed");
52
+ assert.equal(result.notice, undefined);
53
+ assert.deepEqual(log.commits, [{ unitType: "execute-task", unitId: "M001/S01/T01" }]);
54
+ assert.equal(log.notices.length, 0);
55
+ });
56
+
57
+ test("milestone boundary under isolation none commits without a notice", () => {
58
+ const { deps, log } = makeDeps({ isolation: "none" });
59
+ const result = closeUnit(
60
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
61
+ deps,
62
+ );
63
+ assert.equal(result.gitVerdict, "committed");
64
+ assert.equal(log.notices.length, 0);
65
+ });
66
+
67
+ test("milestone boundary off-worktree under isolation worktree fails closed loudly", () => {
68
+ const { deps, log } = makeDeps({ isolation: "worktree", branch: "main" });
69
+ const result = closeUnit(
70
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
71
+ deps,
72
+ );
73
+ assert.equal(result.gitVerdict, "isolation-bypassed");
74
+ assert.equal(log.notices.length, 1);
75
+ assert.equal(log.notices[0].severity, "warning");
76
+ assert.match(log.notices[0].message, /isolation preference was not honoured/);
77
+ assert.match(log.notices[0].message, /git\.isolation is "worktree"/);
78
+ assert.match(log.notices[0].message, /committed directly on "main"/);
79
+ });
80
+
81
+ test("milestone boundary on a milestone branch defers the merge to worktree tooling", () => {
82
+ const { deps, log } = makeDeps({ isolation: "worktree", branch: "milestone/M001" });
83
+ const result = closeUnit(
84
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
85
+ deps,
86
+ );
87
+ assert.equal(result.gitVerdict, "milestone-branch");
88
+ assert.equal(log.notices.length, 1);
89
+ assert.equal(log.notices[0].severity, "info");
90
+ assert.match(log.notices[0].message, /worktree merge/);
91
+ });
92
+
93
+ test("clean tree records nothing-to-commit, and the bypass notice says so", () => {
94
+ const { deps, log } = makeDeps({ isolation: "branch", branch: "main", commitResult: null });
95
+ const result = closeUnit(
96
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
97
+ deps,
98
+ );
99
+ assert.equal(result.gitVerdict, "isolation-bypassed");
100
+ assert.equal(result.commitMessage, null);
101
+ assert.match(log.notices[0].message, /nothing left to commit/);
102
+ });
103
+
104
+ test("commit failure is surfaced, never thrown", () => {
105
+ const { deps, log } = makeDeps({
106
+ commitResult: () => {
107
+ throw new Error("index.lock exists");
108
+ },
109
+ });
110
+ const result = closeUnit(
111
+ { basePath: BASE, unitType: "complete-milestone", unitId: "M001", boundary: "milestone", outcome: "complete" },
112
+ deps,
113
+ );
114
+ assert.equal(result.gitVerdict, "commit-failed");
115
+ assert.equal(log.notices[0].severity, "error");
116
+ assert.match(log.notices[0].message, /index\.lock/);
117
+ });
118
+
119
+ test("re-entrancy is safe: a re-fire over an already-clean tree is nothing-to-commit", () => {
120
+ // No result cache — re-entrancy is absorbed by git itself. The second fire
121
+ // sees a clean tree (commit returns null) and records nothing-to-commit.
122
+ let firstFire = true;
123
+ const { deps, log } = makeDeps({
124
+ isolation: "worktree",
125
+ branch: "main",
126
+ commitResult: () => {
127
+ const committed = firstFire;
128
+ firstFire = false;
129
+ return committed ? "chore(gsd): closeout" : null;
130
+ },
131
+ });
132
+ const request = {
133
+ basePath: BASE,
134
+ unitType: "complete-milestone",
135
+ unitId: "M001",
136
+ boundary: "milestone" as const,
137
+ outcome: "complete" as const,
138
+ };
139
+ const first = closeUnit(request, deps);
140
+ const second = closeUnit(request, deps);
141
+ assert.equal(first.gitVerdict, "isolation-bypassed");
142
+ assert.equal(first.commitMessage, "chore(gsd): closeout");
143
+ assert.equal(second.gitVerdict, "isolation-bypassed");
144
+ assert.equal(second.commitMessage, null);
145
+ assert.match(second.notice ?? "", /nothing left to commit/);
146
+ assert.equal(log.commits.length, 2);
147
+ });
148
+
149
+ // ─── Interactive adapter mapping ──────────────────────────────────────────
150
+
151
+ test("isUnitCloseoutTool recognizes exactly the closeout tools", () => {
152
+ assert.equal(isUnitCloseoutTool("gsd_complete_milestone"), true);
153
+ assert.equal(isUnitCloseoutTool("gsd_save_gate_result"), false);
154
+ assert.equal(isUnitCloseoutTool("read"), false);
155
+ });
156
+
157
+ test("interactive adapter is scoped to milestone boundaries — task/slice tools do not commit", () => {
158
+ const { deps, log } = makeDeps();
159
+ assert.equal(isUnitCloseoutTool("gsd_task_complete"), false);
160
+ assert.equal(isUnitCloseoutTool("gsd_slice_complete"), false);
161
+ assert.equal(
162
+ runInteractiveUnitCloseout(
163
+ { basePath: BASE, canonicalToolName: "gsd_task_complete", input: { milestoneId: "M001", sliceId: "S02", taskId: "T03" } },
164
+ deps,
165
+ ),
166
+ null,
167
+ );
168
+ assert.equal(
169
+ runInteractiveUnitCloseout(
170
+ { basePath: BASE, canonicalToolName: "gsd_slice_complete", input: { milestoneId: "M001", sliceId: "S02" } },
171
+ deps,
172
+ ),
173
+ null,
174
+ );
175
+ assert.equal(log.commits.length, 0);
176
+ });
177
+
178
+ test("interactive adapter maps milestone tool input to canonical unit type", () => {
179
+ const { deps, log } = makeDeps();
180
+ const result = runInteractiveUnitCloseout(
181
+ { basePath: BASE, canonicalToolName: "gsd_complete_milestone", input: { milestoneId: "M001" } },
182
+ deps,
183
+ );
184
+ assert.equal(result?.gitVerdict, "committed");
185
+ assert.deepEqual(log.commits, [{ unitType: "complete-milestone", unitId: "M001" }]);
186
+ });
187
+
188
+ test("interactive adapter accepts snake_case ids and milestone-only input", () => {
189
+ const { deps, log } = makeDeps();
190
+ const result = runInteractiveUnitCloseout(
191
+ { basePath: BASE, canonicalToolName: "gsd_complete_milestone", input: { milestone_id: "M007" } },
192
+ deps,
193
+ );
194
+ assert.equal(result?.gitVerdict, "committed");
195
+ assert.deepEqual(log.commits, [{ unitType: "complete-milestone", unitId: "M007" }]);
196
+ });
197
+
198
+ test("interactive adapter declines unidentifiable input instead of guessing", () => {
199
+ const { deps, log } = makeDeps();
200
+ assert.equal(
201
+ runInteractiveUnitCloseout({ basePath: BASE, canonicalToolName: "gsd_complete_milestone", input: {} }, deps),
202
+ null,
203
+ );
204
+ assert.equal(
205
+ runInteractiveUnitCloseout({ basePath: BASE, canonicalToolName: "not_a_closeout_tool", input: { milestoneId: "M001" } }, deps),
206
+ null,
207
+ );
208
+ assert.equal(log.commits.length, 0);
209
+ });
@@ -11,6 +11,7 @@ import {
11
11
  composeContractedUnitContext,
12
12
  composeContextModeInstructions,
13
13
  composeInlinedContext,
14
+ composeToolSurfaceInstructions,
14
15
  composeUnitContext,
15
16
  manifestBudgetChars,
16
17
  type ArtifactResolver,
@@ -24,6 +25,7 @@ import type {
24
25
  UnitContextManifest,
25
26
  } from "../unit-context-manifest.ts";
26
27
  import { KNOWN_UNIT_TYPES, UNIT_MANIFESTS } from "../unit-context-manifest.ts";
28
+ import { getUnitToolSurfaceContract } from "../unit-tool-contracts.ts";
27
29
  import {
28
30
  buildExecuteTaskPrompt,
29
31
  buildGateEvaluatePrompt,
@@ -165,12 +167,32 @@ test("Context Mode composer: every known eligible unit renders its configured la
165
167
  }
166
168
  assert.ok(out.startsWith("## Context Mode"), `${unitType} should render standalone Context Mode heading`);
167
169
  assert.match(out, new RegExp(`Lane: \\*\\*${laneLabelByMode[manifest.contextMode]} lane\\*\\*\\.`, "i"));
168
- assert.match(out, /`gsd_exec`/, `${unitType} should mention gsd_exec`);
169
- assert.match(out, /`gsd_exec_search`/, `${unitType} should mention gsd_exec_search`);
170
+ const forbidden = getUnitToolSurfaceContract(unitType)?.forbiddenGsdTools ?? {};
171
+ if ("gsd_exec" in forbidden) {
172
+ // Units that forbid gsd_exec (run-uat) have it stripped from their
173
+ // Claude Code dispatch surface; guidance steering to it produces
174
+ // "No such tool available" loops in the dispatched agent.
175
+ assert.doesNotMatch(out, /`gsd_exec`/, `${unitType} forbids gsd_exec; guidance must not steer to it`);
176
+ assert.doesNotMatch(out, /`gsd_exec_search`/, `${unitType} guidance must not steer to gsd_exec_search`);
177
+ assert.match(out, /`gsd_uat_exec`/, `${unitType} guidance should steer to gsd_uat_exec instead`);
178
+ } else {
179
+ assert.match(out, /`gsd_exec`/, `${unitType} should mention gsd_exec`);
180
+ assert.match(out, /`gsd_exec_search`/, `${unitType} should mention gsd_exec_search`);
181
+ }
170
182
  assert.match(out, /`gsd_resume`/, `${unitType} should mention gsd_resume`);
171
183
  }
172
184
  });
173
185
 
186
+ test("Context Mode composer: run-uat guidance steers to gsd_uat_exec in both render modes", () => {
187
+ const nested = composeContextModeInstructions("run-uat", { enabled: true, renderMode: "nested" });
188
+ assert.match(nested, /^Context Mode \(verification lane\): /);
189
+ assert.match(nested, /`gsd_uat_exec`/);
190
+ assert.doesNotMatch(nested, /`gsd_exec`/);
191
+ const standalone = composeContextModeInstructions("run-uat", { enabled: true, renderMode: "standalone" });
192
+ assert.match(standalone, /`gsd_uat_exec`/);
193
+ assert.doesNotMatch(standalone, /`gsd_exec`/);
194
+ });
195
+
174
196
  test("Context Mode composer: workflow-preferences and research-decision render no Context Mode block", () => {
175
197
  assert.strictEqual(
176
198
  composeContextModeInstructions("workflow-preferences", { enabled: true, renderMode: "standalone" }),
@@ -182,6 +204,49 @@ test("Context Mode composer: workflow-preferences and research-decision render n
182
204
  );
183
205
  });
184
206
 
207
+ test("Tool Surface composer: run-uat forbids gsd_exec and Bash", () => {
208
+ const out = composeToolSurfaceInstructions("run-uat", { renderMode: "standalone" });
209
+ assert.match(out, /^## Tool Surface/);
210
+ assert.match(out, /Do not call `gsd_exec`/);
211
+ assert.match(out, /`Bash`/);
212
+ assert.match(out, /`gsd_uat_exec`/);
213
+ assert.match(out, /`gsd_save_gate_result`/);
214
+ assert.match(out, /`gsd_summary_save`/);
215
+ });
216
+
217
+ test("Tool Surface composer: complete-slice steers verification to gsd_exec", () => {
218
+ const out = composeToolSurfaceInstructions("complete-slice", { renderMode: "standalone" });
219
+ assert.match(out, /`gsd_exec`/);
220
+ assert.match(out, /not direct `bash`/);
221
+ assert.match(out, /`gsd_uat_result_save`/);
222
+ });
223
+
224
+ test("Tool Surface composer: planning units restrict writes to .gsd", () => {
225
+ const out = composeToolSurfaceInstructions("discuss-milestone", { renderMode: "standalone" });
226
+ assert.match(out, /restricted to `\.gsd\/\*\*`/);
227
+ assert.match(out, /`ask_user_questions`/);
228
+ });
229
+
230
+ test("Tool Surface composer: planning-dispatch lists allowed subagents", () => {
231
+ const out = composeToolSurfaceInstructions("plan-slice", { renderMode: "standalone" });
232
+ assert.match(out, /\*\*scout\*\*/);
233
+ assert.match(out, /\*\*planner\*\*/);
234
+ });
235
+
236
+ test("Tool Surface composer: execute-task warns against slice/milestone closeout tools", () => {
237
+ const out = composeToolSurfaceInstructions("execute-task", { renderMode: "nested" });
238
+ assert.match(out, /^Tool surface: /);
239
+ assert.match(out, /`gsd_task_complete`/);
240
+ assert.match(out, /Do not call `gsd_slice_complete`/);
241
+ });
242
+
243
+ test("Tool Surface composer: unknown unit renders empty block", () => {
244
+ assert.strictEqual(
245
+ composeToolSurfaceInstructions("never-dispatched", { renderMode: "standalone" }),
246
+ "",
247
+ );
248
+ });
249
+
185
250
  // ─── Integration: migrated buildReassessRoadmapPrompt ─────────────────────
186
251
 
187
252
  function makeFixtureBase(): string {
@@ -0,0 +1,163 @@
1
+ // gsd-pi — ADR-033 Unit Registry parity guard.
2
+ //
3
+ // Pins every view derived from UNIT_REGISTRY to the exact values the
4
+ // hand-maintained tables held before the registry existed. A failure here
5
+ // means a registry edit changed a derived surface — intended changes update
6
+ // the pinned expectation in the same diff.
7
+
8
+ import test from "node:test";
9
+ import assert from "node:assert/strict";
10
+
11
+ import {
12
+ KNOWN_UNIT_TYPES,
13
+ UNIT_REGISTRY,
14
+ EXECUTE_TASK_UNIT_TYPES,
15
+ SECTION_CLOSE_GATE_UNIT_TYPES,
16
+ getUnitDescriptor,
17
+ getUnitPhaseChain,
18
+ } from "../unit-registry.ts";
19
+ import {
20
+ AUTO_UNIT_SCOPED_TOOLS,
21
+ UNIT_TOOL_CONTRACTS,
22
+ getUnitToolSurfaceContract,
23
+ } from "../unit-tool-contracts.ts";
24
+ import { UNIT_MANIFESTS } from "../unit-context-manifest.ts";
25
+ import { phaseChainForUnit } from "../preferences-models.ts";
26
+
27
+ // ─── Pinned pre-registry values ───────────────────────────────────────────
28
+
29
+ const EXPECTED_KNOWN_UNIT_TYPES = [
30
+ "research-milestone",
31
+ "plan-milestone",
32
+ "discuss-milestone",
33
+ "validate-milestone",
34
+ "complete-milestone",
35
+ "research-slice",
36
+ "plan-slice",
37
+ "refine-slice",
38
+ "replan-slice",
39
+ "complete-slice",
40
+ "reassess-roadmap",
41
+ "execute-task",
42
+ "reactive-execute",
43
+ "run-uat",
44
+ "gate-evaluate",
45
+ "rewrite-docs",
46
+ "triage-captures",
47
+ "quick-task",
48
+ "workflow-preferences",
49
+ "discuss-project",
50
+ "discuss-requirements",
51
+ "research-decision",
52
+ "research-project",
53
+ ];
54
+
55
+ // The contract table carried two keys KNOWN_UNIT_TYPES never had (variants)
56
+ // and lacked two it did have (sidecars without contracts).
57
+ const EXPECTED_CONTRACT_ONLY_TYPES = ["discuss-slice", "execute-task-simple"];
58
+ const EXPECTED_CONTRACT_LESS_TYPES = ["triage-captures", "quick-task"];
59
+
60
+ const EXPECTED_EXECUTE_TASK_SET = ["execute-task", "execute-task-simple", "reactive-execute"];
61
+ const EXPECTED_SECTION_CLOSE_SET = [
62
+ ...EXPECTED_EXECUTE_TASK_SET,
63
+ "complete-slice",
64
+ "validate-milestone",
65
+ ];
66
+
67
+ const EXPECTED_PHASE_CHAINS: Record<string, string[] | undefined> = {
68
+ "research-milestone": ["research"],
69
+ "research-slice": ["research"],
70
+ "research-project": ["research"],
71
+ "plan-milestone": ["planning"],
72
+ "plan-slice": ["planning"],
73
+ "refine-slice": ["planning"],
74
+ "replan-slice": ["planning"],
75
+ "discuss-milestone": ["discuss", "planning"],
76
+ "discuss-slice": ["discuss", "planning"],
77
+ "discuss-project": ["discuss", "planning"],
78
+ "discuss-requirements": ["discuss", "planning"],
79
+ "workflow-preferences": ["discuss", "planning"],
80
+ "research-decision": ["discuss", "planning"],
81
+ "execute-task": ["execution"],
82
+ "reactive-execute": ["execution"],
83
+ "execute-task-simple": ["execution_simple", "execution"],
84
+ "complete-slice": ["completion"],
85
+ "complete-milestone": ["completion"],
86
+ "worktree-merge": ["completion"],
87
+ "run-uat": ["uat", "completion"],
88
+ "reassess-roadmap": ["validation", "planning"],
89
+ "rewrite-docs": ["validation", "planning"],
90
+ "gate-evaluate": ["validation", "planning"],
91
+ "validate-milestone": ["validation", "planning"],
92
+ "triage-captures": undefined,
93
+ "quick-task": undefined,
94
+ subagent: ["subagent"],
95
+ "subagent/scout": ["subagent"],
96
+ "no-such-unit": undefined,
97
+ };
98
+
99
+ // ─── Derived-view parity ──────────────────────────────────────────────────
100
+
101
+ test("KNOWN_UNIT_TYPES derives exactly the pre-registry list, in order", () => {
102
+ assert.deepEqual([...KNOWN_UNIT_TYPES], EXPECTED_KNOWN_UNIT_TYPES);
103
+ });
104
+
105
+ test("UNIT_TOOL_CONTRACTS keeps the pre-registry key set, asymmetries included", () => {
106
+ const contractKeys = Object.keys(UNIT_TOOL_CONTRACTS);
107
+ for (const variant of EXPECTED_CONTRACT_ONLY_TYPES) {
108
+ assert.ok(contractKeys.includes(variant), `variant ${variant} must keep its contract`);
109
+ assert.ok(!KNOWN_UNIT_TYPES.includes(variant as never), `${variant} must stay out of KNOWN_UNIT_TYPES`);
110
+ }
111
+ for (const sidecar of EXPECTED_CONTRACT_LESS_TYPES) {
112
+ assert.ok(!contractKeys.includes(sidecar), `${sidecar} must stay contract-less`);
113
+ assert.equal(getUnitToolSurfaceContract(sidecar), undefined);
114
+ }
115
+ const expectedKeys = [
116
+ ...EXPECTED_KNOWN_UNIT_TYPES.filter((t) => !EXPECTED_CONTRACT_LESS_TYPES.includes(t)),
117
+ ...EXPECTED_CONTRACT_ONLY_TYPES,
118
+ ].sort();
119
+ assert.deepEqual([...contractKeys].sort(), expectedKeys);
120
+ });
121
+
122
+ test("scope-class Sets match the pre-registry hand-maintained Sets", () => {
123
+ assert.deepEqual([...EXECUTE_TASK_UNIT_TYPES].sort(), [...EXPECTED_EXECUTE_TASK_SET].sort());
124
+ assert.deepEqual([...SECTION_CLOSE_GATE_UNIT_TYPES].sort(), [...EXPECTED_SECTION_CLOSE_SET].sort());
125
+ });
126
+
127
+ test("phaseChainForUnit matches the pre-registry switch for every known input", () => {
128
+ for (const [unitType, expected] of Object.entries(EXPECTED_PHASE_CHAINS)) {
129
+ assert.deepEqual(
130
+ phaseChainForUnit(unitType),
131
+ expected,
132
+ `phase chain for ${unitType}`,
133
+ );
134
+ }
135
+ });
136
+
137
+ test("AUTO_UNIT_SCOPED_TOOLS mirrors each contract's allowed tools", () => {
138
+ for (const [unitType, contract] of Object.entries(UNIT_TOOL_CONTRACTS)) {
139
+ assert.deepEqual(AUTO_UNIT_SCOPED_TOOLS[unitType], contract.allowedGsdTools);
140
+ }
141
+ assert.deepEqual(
142
+ Object.keys(AUTO_UNIT_SCOPED_TOOLS).sort(),
143
+ Object.keys(UNIT_TOOL_CONTRACTS).sort(),
144
+ );
145
+ });
146
+
147
+ // ─── Registry-internal coherence ──────────────────────────────────────────
148
+
149
+ test("every primary unit type has a manifest; manifests cover nothing else", () => {
150
+ const manifestKeys = Object.keys(UNIT_MANIFESTS).sort();
151
+ assert.deepEqual(manifestKeys, [...KNOWN_UNIT_TYPES].sort());
152
+ });
153
+
154
+ test("every registry row is reachable through the descriptor accessor", () => {
155
+ for (const unitType of Object.keys(UNIT_REGISTRY)) {
156
+ const descriptor = getUnitDescriptor(unitType);
157
+ assert.ok(descriptor, `descriptor for ${unitType}`);
158
+ assert.ok(["primary", "variant"].includes(descriptor.kind));
159
+ assert.ok(["execute-task", "section-close", "standard"].includes(descriptor.scopeClass));
160
+ assert.equal(getUnitPhaseChain(unitType), descriptor.phaseChain);
161
+ }
162
+ assert.equal(getUnitDescriptor("no-such-unit"), undefined);
163
+ });
@@ -15,6 +15,10 @@ function scaffoldProject(root: string, pkg: Record<string, unknown>): void {
15
15
  writeFileSync(join(root, "package.json"), JSON.stringify(pkg, null, 2));
16
16
  }
17
17
 
18
+ const LEGACY_ENGINE = { engine: "legacy", source: "probe", reason: "test" } as const;
19
+ const MANAGED_ENGINE = { engine: "gsd-browser", source: "probe", reason: "test" } as const;
20
+ const OFF_ENGINE = { engine: "off", source: "env", reason: "test" } as const;
21
+
18
22
  describe("web-app-uat guidance", () => {
19
23
  test("returns null for non-web projects", () => {
20
24
  const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
@@ -36,15 +40,54 @@ describe("web-app-uat guidance", () => {
36
40
  scripts: { dev: "vite" },
37
41
  });
38
42
  assert.equal(detectWebApp(root), true);
39
- const block = buildWebAppUatGuidanceBlock(root);
43
+ const block = buildWebAppUatGuidanceBlock(root, LEGACY_ENGINE);
40
44
  assert.ok(block);
41
45
  assert.match(block!, /browser-executable/);
46
+ assert.match(block!, /Playwright-backed `browser_\*` tools/);
42
47
  assert.match(block!, /Playwright scaffolding/);
43
48
  } finally {
44
49
  rmSync(root, { recursive: true, force: true });
45
50
  }
46
51
  });
47
52
 
53
+ test("describes the managed gsd-browser engine when it is the resolved backing", () => {
54
+ const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
55
+ try {
56
+ scaffoldProject(root, {
57
+ dependencies: { react: "19.0.0" },
58
+ scripts: { dev: "vite" },
59
+ });
60
+ const block = buildWebAppUatGuidanceBlock(root, MANAGED_ENGINE);
61
+ assert.ok(block);
62
+ assert.match(block!, /managed gsd-browser engine/);
63
+ assert.match(block!, /browser-executable/);
64
+ assert.doesNotMatch(block!, /Playwright-backed/);
65
+ } finally {
66
+ rmSync(root, { recursive: true, force: true });
67
+ }
68
+ });
69
+
70
+ test("steers to runtime-executable UAT when browser tools are off", () => {
71
+ const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
72
+ try {
73
+ scaffoldProject(root, {
74
+ dependencies: { react: "19.0.0" },
75
+ scripts: { dev: "vite" },
76
+ });
77
+ const block = buildWebAppUatGuidanceBlock(root, OFF_ENGINE);
78
+ assert.ok(block);
79
+ assert.match(block!, /browser tools are disabled/);
80
+ assert.doesNotMatch(block!, /- `browser-executable`/);
81
+ // mixed/live-runtime require browser tools per UAT_MODE_POLICIES, so the
82
+ // bullet must drop out too — recommending them would dead-end at dispatch.
83
+ assert.doesNotMatch(block!, /- `mixed`/);
84
+ assert.doesNotMatch(block!, /interactive `browser_\*` checks/);
85
+ assert.match(block!, /runtime-executable/);
86
+ } finally {
87
+ rmSync(root, { recursive: true, force: true });
88
+ }
89
+ });
90
+
48
91
  test("detects existing Playwright and npm script", () => {
49
92
  const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
50
93
  try {
@@ -495,8 +495,8 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
495
495
  estimate: "10m",
496
496
  files: ["src/resources/extensions/gsd/workflow-mcp.ts"],
497
497
  verify: "node --test",
498
- inputs: [".gsd/milestones/M001/M001-ROADMAP.md"],
499
- expectedOutput: ["S01-PLAN.md", "T01-PLAN.md"],
498
+ inputs: [],
499
+ expectedOutput: ["src/bridge-status.md"],
500
500
  },
501
501
  ],
502
502
  },
@@ -528,8 +528,8 @@ test("executePlanSlice writes task planning state and rendered plan artifacts",
528
528
  estimate: "15m",
529
529
  files: ["src/resources/extensions/gsd/tools/workflow-tool-executors.ts"],
530
530
  verify: "node --test",
531
- inputs: [".gsd/milestones/M001/M001-ROADMAP.md"],
532
- expectedOutput: ["S01-PLAN.md", "T01-PLAN.md"],
531
+ inputs: [],
532
+ expectedOutput: ["src/bridge-status.md"],
533
533
  },
534
534
  ],
535
535
  }, base));