@opengsd/gsd-pi 1.1.1-dev.b2556262 → 1.2.0-dev.4813ead6

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 (500) hide show
  1. package/dist/cli-web-branch.d.ts +2 -0
  2. package/dist/cli-web-branch.js +9 -2
  3. package/dist/help-text.js +5 -0
  4. package/dist/project-sessions.js +4 -2
  5. package/dist/resources/.managed-resources-content-hash +1 -1
  6. package/dist/resources/extensions/ask-user-questions.js +78 -23
  7. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +101 -237
  8. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
  9. package/dist/resources/extensions/github-sync/templates.js +3 -3
  10. package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
  11. package/dist/resources/extensions/gsd/auto/contracts.js +8 -1
  12. package/dist/resources/extensions/gsd/auto/loop.js +74 -56
  13. package/dist/resources/extensions/gsd/auto/orchestrator.js +763 -63
  14. package/dist/resources/extensions/gsd/auto/phases.js +28 -3
  15. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
  16. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  17. package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
  18. package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
  19. package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
  20. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
  21. package/dist/resources/extensions/gsd/auto-prompts.js +191 -9
  22. package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
  23. package/dist/resources/extensions/gsd/auto-runtime-state.js +17 -0
  24. package/dist/resources/extensions/gsd/auto-start.js +12 -23
  25. package/dist/resources/extensions/gsd/auto-timers.js +16 -2
  26. package/dist/resources/extensions/gsd/auto-tool-tracking.js +37 -0
  27. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +33 -29
  28. package/dist/resources/extensions/gsd/auto-verification.js +7 -7
  29. package/dist/resources/extensions/gsd/auto-worktree.js +45 -36
  30. package/dist/resources/extensions/gsd/auto.js +73 -471
  31. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
  32. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
  33. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +103 -138
  35. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
  36. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
  37. package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
  38. package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
  39. package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
  40. package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
  41. package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
  42. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  43. package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
  44. package/dist/resources/extensions/gsd/db-workspace.js +103 -0
  45. package/dist/resources/extensions/gsd/debug-logger.js +10 -0
  46. package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
  47. package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
  48. package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  49. package/dist/resources/extensions/gsd/doctor-proactive.js +7 -2
  50. package/dist/resources/extensions/gsd/doctor.js +16 -9
  51. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  52. package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
  53. package/dist/resources/extensions/gsd/gsd-db.js +12 -0
  54. package/dist/resources/extensions/gsd/guided-flow.js +36 -470
  55. package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
  56. package/dist/resources/extensions/gsd/markdown-renderer.js +33 -33
  57. package/dist/resources/extensions/gsd/mcp-filter.js +8 -1
  58. package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
  59. package/dist/resources/extensions/gsd/md-importer.js +4 -3
  60. package/dist/resources/extensions/gsd/migrate/safety.js +2 -2
  61. package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
  62. package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
  63. package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
  64. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
  65. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
  66. package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
  67. package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
  68. package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
  69. package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
  70. package/dist/resources/extensions/gsd/native-git-bridge.js +45 -0
  71. package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
  72. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
  73. package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
  74. package/dist/resources/extensions/gsd/preferences.js +147 -29
  75. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  76. package/dist/resources/extensions/gsd/prompts/discuss.md +6 -7
  77. package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
  78. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
  79. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
  80. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
  81. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
  82. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  83. package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -1
  84. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  85. package/dist/resources/extensions/gsd/prompts/research-milestone.md +2 -2
  86. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  87. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -3
  88. package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
  89. package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
  90. package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
  91. package/dist/resources/extensions/gsd/question-transport.js +86 -0
  92. package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
  93. package/dist/resources/extensions/gsd/schemas/parsers.js +6 -1
  94. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
  95. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +21 -1
  96. package/dist/resources/extensions/gsd/state.js +13 -5
  97. package/dist/resources/extensions/gsd/templates/plan.md +7 -0
  98. package/dist/resources/extensions/gsd/templates/project.md +1 -0
  99. package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
  100. package/dist/resources/extensions/gsd/templates/uat.md +5 -1
  101. package/dist/resources/extensions/gsd/tool-contract.js +52 -8
  102. package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
  103. package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
  104. package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
  105. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
  106. package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
  107. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +169 -20
  108. package/dist/resources/extensions/gsd/uat-policy.js +16 -10
  109. package/dist/resources/extensions/gsd/uat-run.js +9 -14
  110. package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
  111. package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
  112. package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
  113. package/dist/resources/extensions/gsd/user-input-boundary.js +65 -4
  114. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  115. package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
  116. package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
  117. package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
  118. package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
  119. package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
  120. package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
  121. package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
  122. package/dist/resources/extensions/shared/interview-ui.js +2 -2
  123. package/dist/resources/shared/claude-runtime-floor.js +182 -0
  124. package/dist/tsconfig.extensions.tsbuildinfo +1 -0
  125. package/dist/update-cmd.js +20 -0
  126. package/dist/web/standalone/.next/BUILD_ID +1 -1
  127. package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
  128. package/dist/web/standalone/.next/build-manifest.json +3 -3
  129. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  130. package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
  131. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  145. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  147. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  156. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  162. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  164. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  168. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  174. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  176. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  178. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  180. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  182. package/dist/web/standalone/.next/server/app/index.html +1 -1
  183. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  184. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  185. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  186. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  187. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  188. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  189. package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
  190. package/dist/web/standalone/.next/server/chunks/5047.js +2 -0
  191. package/dist/web/standalone/.next/server/chunks/5124.js +1 -0
  192. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  193. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  196. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  197. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  198. package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
  199. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
  200. package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
  201. package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
  202. package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
  203. package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
  204. package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
  205. package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
  206. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  207. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  208. package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
  209. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
  210. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  211. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  212. package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
  213. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
  214. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
  215. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
  216. package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
  217. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  218. package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
  219. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  220. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
  221. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  222. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  223. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  224. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
  225. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
  226. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  227. package/dist/web-mode.d.ts +2 -0
  228. package/dist/web-mode.js +20 -8
  229. package/package.json +17 -11
  230. package/packages/cloud-mcp-gateway/package.json +2 -2
  231. package/packages/contracts/package.json +1 -1
  232. package/packages/daemon/package.json +4 -4
  233. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
  234. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  235. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
  236. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  237. package/packages/gsd-agent-core/package.json +5 -5
  238. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  239. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -0
  240. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  241. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +1 -1
  242. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  243. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  244. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
  245. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  246. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  247. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
  248. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  249. package/packages/gsd-agent-modes/package.json +7 -7
  250. package/packages/mcp-server/dist/server.d.ts +10 -0
  251. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  252. package/packages/mcp-server/dist/server.js +8 -0
  253. package/packages/mcp-server/dist/server.js.map +1 -1
  254. package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
  255. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  256. package/packages/mcp-server/dist/workflow-tools.js +2 -1
  257. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  258. package/packages/mcp-server/package.json +3 -3
  259. package/packages/native/package.json +1 -1
  260. package/packages/pi-agent-core/package.json +1 -1
  261. package/packages/pi-ai/dist/image-models.generated.d.ts +30 -0
  262. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  263. package/packages/pi-ai/dist/image-models.generated.js +30 -0
  264. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  265. package/packages/pi-ai/dist/models.generated.d.ts +8 -127
  266. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  267. package/packages/pi-ai/dist/models.generated.js +47 -166
  268. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  269. package/packages/pi-ai/package.json +1 -1
  270. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/auth-storage.js +11 -3
  272. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  273. package/packages/pi-coding-agent/package.json +7 -7
  274. package/packages/pi-tui/dist/components/input.js +1 -1
  275. package/packages/pi-tui/dist/components/input.js.map +1 -1
  276. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  277. package/packages/pi-tui/dist/keys.js +39 -30
  278. package/packages/pi-tui/dist/keys.js.map +1 -1
  279. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  280. package/packages/pi-tui/dist/stdin-buffer.js +22 -0
  281. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  282. package/packages/pi-tui/package.json +2 -2
  283. package/packages/rpc-client/package.json +2 -2
  284. package/pkg/package.json +1 -1
  285. package/scripts/install/deps.js +10 -0
  286. package/scripts/link-workspace-packages.cjs +7 -40
  287. package/src/resources/extensions/ask-user-questions.ts +87 -24
  288. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +126 -289
  289. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +242 -2
  290. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
  291. package/src/resources/extensions/github-sync/templates.ts +3 -3
  292. package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
  293. package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
  294. package/src/resources/extensions/gsd/auto/contracts.ts +40 -121
  295. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  296. package/src/resources/extensions/gsd/auto/loop.ts +83 -61
  297. package/src/resources/extensions/gsd/auto/orchestrator.ts +913 -64
  298. package/src/resources/extensions/gsd/auto/phases.ts +35 -3
  299. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
  300. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  301. package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
  302. package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
  303. package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
  304. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -3
  305. package/src/resources/extensions/gsd/auto-prompts.ts +220 -9
  306. package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
  307. package/src/resources/extensions/gsd/auto-runtime-state.ts +30 -0
  308. package/src/resources/extensions/gsd/auto-start.ts +17 -20
  309. package/src/resources/extensions/gsd/auto-timers.ts +16 -2
  310. package/src/resources/extensions/gsd/auto-tool-tracking.ts +40 -0
  311. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +42 -30
  312. package/src/resources/extensions/gsd/auto-verification.ts +7 -8
  313. package/src/resources/extensions/gsd/auto-worktree.ts +57 -42
  314. package/src/resources/extensions/gsd/auto.ts +96 -508
  315. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
  316. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
  317. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  318. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +120 -151
  319. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
  320. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
  321. package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
  322. package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
  323. package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
  324. package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
  325. package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
  326. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  327. package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
  328. package/src/resources/extensions/gsd/db-workspace.ts +170 -0
  329. package/src/resources/extensions/gsd/debug-logger.ts +11 -0
  330. package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
  331. package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
  332. package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  333. package/src/resources/extensions/gsd/doctor-proactive.ts +8 -2
  334. package/src/resources/extensions/gsd/doctor.ts +15 -5
  335. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  336. package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
  337. package/src/resources/extensions/gsd/gsd-db.ts +12 -0
  338. package/src/resources/extensions/gsd/guided-flow.ts +49 -560
  339. package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
  340. package/src/resources/extensions/gsd/markdown-renderer.ts +40 -20
  341. package/src/resources/extensions/gsd/mcp-filter.ts +9 -1
  342. package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
  343. package/src/resources/extensions/gsd/md-importer.ts +3 -3
  344. package/src/resources/extensions/gsd/migrate/safety.ts +2 -2
  345. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  346. package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
  347. package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
  348. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
  349. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
  350. package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
  351. package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
  352. package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
  353. package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
  354. package/src/resources/extensions/gsd/native-git-bridge.ts +48 -0
  355. package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
  356. package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
  357. package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
  358. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  359. package/src/resources/extensions/gsd/preferences.ts +173 -28
  360. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  361. package/src/resources/extensions/gsd/prompts/discuss.md +6 -7
  362. package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
  363. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
  364. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
  365. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
  366. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
  367. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  368. package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -1
  369. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  370. package/src/resources/extensions/gsd/prompts/research-milestone.md +2 -2
  371. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  372. package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -3
  373. package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
  374. package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
  375. package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
  376. package/src/resources/extensions/gsd/question-transport.ts +138 -0
  377. package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
  378. package/src/resources/extensions/gsd/schemas/parsers.ts +6 -1
  379. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
  380. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +31 -10
  381. package/src/resources/extensions/gsd/state.ts +15 -5
  382. package/src/resources/extensions/gsd/templates/plan.md +7 -0
  383. package/src/resources/extensions/gsd/templates/project.md +1 -0
  384. package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
  385. package/src/resources/extensions/gsd/templates/uat.md +5 -1
  386. package/src/resources/extensions/gsd/tests/artifact-db-drift-memo.test.ts +66 -0
  387. package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
  388. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
  389. package/src/resources/extensions/gsd/tests/auto-dispatch-baseline-harness.test.ts +53 -0
  390. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -5
  391. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
  392. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
  393. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +709 -845
  394. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +38 -10
  395. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
  396. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
  397. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  398. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
  399. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
  400. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +15 -0
  401. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
  402. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
  403. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
  404. package/src/resources/extensions/gsd/tests/execute-summary-save-empty-project.test.ts +64 -1
  405. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
  406. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
  407. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
  408. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
  409. package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +157 -0
  410. package/src/resources/extensions/gsd/tests/markdown-renderer-parse-cache.test.ts +75 -0
  411. package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
  412. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
  413. package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
  414. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
  415. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
  416. package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
  417. package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
  418. package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
  419. package/src/resources/extensions/gsd/tests/native-merge-regular.test.ts +139 -0
  420. package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +127 -0
  421. package/src/resources/extensions/gsd/tests/parse-project-milestone-bridge.test.ts +77 -0
  422. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
  423. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +6 -2
  424. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
  425. package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
  426. package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
  427. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +75 -2
  428. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
  429. package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
  430. package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
  431. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +94 -0
  432. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +65 -0
  433. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
  434. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
  435. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
  436. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
  437. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
  438. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +21 -6
  439. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +38 -0
  440. package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
  441. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
  442. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
  443. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
  444. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +147 -0
  445. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
  446. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
  447. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
  448. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
  449. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +21 -0
  450. package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
  451. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +24 -0
  452. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
  453. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -3
  454. package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -0
  455. package/src/resources/extensions/gsd/tool-contract.ts +86 -8
  456. package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
  457. package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
  458. package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
  459. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
  460. package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
  461. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +183 -21
  462. package/src/resources/extensions/gsd/uat-policy.ts +19 -10
  463. package/src/resources/extensions/gsd/uat-run.ts +10 -14
  464. package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
  465. package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
  466. package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
  467. package/src/resources/extensions/gsd/user-input-boundary.ts +55 -5
  468. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  469. package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
  470. package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
  471. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  472. package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
  473. package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
  474. package/src/resources/extensions/gsd/worktree-lifecycle.ts +7 -16
  475. package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
  476. package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
  477. package/src/resources/extensions/shared/interview-ui.ts +15 -2
  478. package/src/resources/shared/claude-runtime-floor.ts +248 -0
  479. package/dist/web/standalone/.next/server/chunks/678.js +0 -2
  480. package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
  481. package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
  482. package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
  483. package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
  484. package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
  485. package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
  486. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +0 -21
  487. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +0 -1
  488. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +0 -213
  489. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +0 -1
  490. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts +0 -28
  491. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts.map +0 -1
  492. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js +0 -249
  493. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js.map +0 -1
  494. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts +0 -19
  495. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts.map +0 -1
  496. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js +0 -797
  497. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js.map +0 -1
  498. package/scripts/ensure-workspace-builds.cjs +0 -129
  499. /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → tkLHUSzPA2kMmWz4DmGwI}/_buildManifest.js +0 -0
  500. /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → tkLHUSzPA2kMmWz4DmGwI}/_ssgManifest.js +0 -0
@@ -0,0 +1,109 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Canonical quality-gate closure from durable DB and artifact evidence.
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { extractSection } from "./files.js";
5
+ import { getGateDefinition } from "./gate-registry.js";
6
+ import { getMilestoneSlices, getPendingGates, saveGateResult } from "./gsd-db.js";
7
+ import { resolveSliceFile, resolveTaskFile } from "./paths.js";
8
+ const GATE_SECTION_HEADINGS = {
9
+ Q3: ["Threat Surface", "Abuse Surface"],
10
+ Q4: ["Requirement Impact", "Broken Promises"],
11
+ Q5: ["Failure Modes"],
12
+ Q6: ["Load Profile"],
13
+ Q7: ["Negative Tests"],
14
+ Q8: ["Operational Readiness"],
15
+ };
16
+ function readFile(path) {
17
+ if (!path || !existsSync(path))
18
+ return null;
19
+ return readFileSync(path, "utf-8");
20
+ }
21
+ function firstSection(content, gateId) {
22
+ if (!content)
23
+ return null;
24
+ for (const heading of GATE_SECTION_HEADINGS[gateId] ?? []) {
25
+ const section = extractSection(content, heading);
26
+ if (section)
27
+ return section;
28
+ }
29
+ return null;
30
+ }
31
+ function evidenceArtifactContent(row, basePath) {
32
+ const def = getGateDefinition(row.gate_id);
33
+ switch (def?.ownerTurn) {
34
+ case "gate-evaluate":
35
+ return readFile(resolveSliceFile(basePath, row.milestone_id, row.slice_id, "PLAN"));
36
+ case "execute-task":
37
+ return readFile(resolveTaskFile(basePath, row.milestone_id, row.slice_id, row.task_id, "SUMMARY"));
38
+ case "complete-slice":
39
+ return readFile(resolveSliceFile(basePath, row.milestone_id, row.slice_id, "SUMMARY"));
40
+ default:
41
+ return null;
42
+ }
43
+ }
44
+ function closureEvidence(row, options) {
45
+ const def = getGateDefinition(row.gate_id);
46
+ if (!def)
47
+ return null;
48
+ if (def.ownerTurn === "validate-milestone" && options.milestoneValidationPassed) {
49
+ return {
50
+ verdict: "pass",
51
+ rationale: `${def.promptSection} covered by passing milestone validation`,
52
+ findings: "",
53
+ };
54
+ }
55
+ if (!options.artifactBasePath)
56
+ return null;
57
+ const section = firstSection(evidenceArtifactContent(row, options.artifactBasePath), row.gate_id);
58
+ if (section) {
59
+ return {
60
+ verdict: "pass",
61
+ rationale: `${def.promptSection} evidence found in durable artifact`,
62
+ findings: section,
63
+ };
64
+ }
65
+ if (!options.milestoneValidationPassed)
66
+ return null;
67
+ return {
68
+ verdict: "omitted",
69
+ rationale: `${def.promptSection} has no durable artifact section; milestone validation passed`,
70
+ findings: "",
71
+ };
72
+ }
73
+ function closeGate(row, evidence) {
74
+ saveGateResult({
75
+ milestoneId: row.milestone_id,
76
+ sliceId: row.slice_id,
77
+ gateId: row.gate_id,
78
+ taskId: row.task_id,
79
+ verdict: evidence.verdict,
80
+ rationale: evidence.rationale,
81
+ findings: evidence.findings,
82
+ });
83
+ }
84
+ export function closeQualityGatesFromEvidence(milestoneId, options = {}) {
85
+ const repaired = [];
86
+ const unresolved = [];
87
+ for (const slice of getMilestoneSlices(milestoneId)) {
88
+ const sliceId = slice.id;
89
+ for (const row of getPendingGates(milestoneId, sliceId)) {
90
+ if (!getGateDefinition(row.gate_id)) {
91
+ unresolved.push(row);
92
+ continue;
93
+ }
94
+ const evidence = closureEvidence(row, options);
95
+ if (!evidence) {
96
+ unresolved.push(row);
97
+ continue;
98
+ }
99
+ closeGate(row, evidence);
100
+ repaired.push({
101
+ gateId: row.gate_id,
102
+ sliceId: row.slice_id,
103
+ ...(row.task_id ? { taskId: row.task_id } : {}),
104
+ verdict: evidence.verdict,
105
+ });
106
+ }
107
+ }
108
+ return { repaired, unresolved };
109
+ }
@@ -0,0 +1,86 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Resolve how workflow units should ask the user for input.
3
+ import { parseMcpToolName, toMcpToolName } from "./mcp-tool-name.js";
4
+ function isWorkflowMcpServerName(serverName) {
5
+ const normalized = serverName.toLowerCase();
6
+ return normalized === "gsd" || normalized.includes("workflow");
7
+ }
8
+ export function usesWorkflowMcpTransport(authMode, baseUrl) {
9
+ return authMode === "externalCli" && typeof baseUrl === "string" && baseUrl.startsWith("local://");
10
+ }
11
+ export function hasAskUserQuestionsTool(activeTools) {
12
+ return activeTools.some((toolName) => {
13
+ if (toolName === "ask_user_questions")
14
+ return true;
15
+ const mcp = parseMcpToolName(toolName);
16
+ if (!mcp)
17
+ return false;
18
+ if (mcp.toolName === "ask_user_questions")
19
+ return true;
20
+ return mcp.toolName === "*" && isWorkflowMcpServerName(mcp.serverName);
21
+ });
22
+ }
23
+ function workflowMcpStructuredQuestionsEnabled(env = process.env) {
24
+ const value = env.GSD_WORKFLOW_MCP_STRUCTURED_QUESTIONS?.trim().toLowerCase();
25
+ return value !== "0" && value !== "false" && value !== "off";
26
+ }
27
+ export function resolveQuestionTransport(options) {
28
+ const questionToolAvailable = hasAskUserQuestionsTool(options.activeTools);
29
+ const usesWorkflowMcp = usesWorkflowMcpTransport(options.authMode, options.baseUrl);
30
+ if (!questionToolAvailable) {
31
+ return {
32
+ structuredQuestionsAvailable: "false",
33
+ questionToolAvailable,
34
+ usesWorkflowMcp,
35
+ reason: "question-tool-missing",
36
+ };
37
+ }
38
+ if (options.authMode === "externalCli" && !workflowMcpStructuredQuestionsEnabled(options.env)) {
39
+ return {
40
+ structuredQuestionsAvailable: "false",
41
+ questionToolAvailable,
42
+ usesWorkflowMcp,
43
+ reason: "workflow-mcp-disabled",
44
+ };
45
+ }
46
+ return {
47
+ structuredQuestionsAvailable: "true",
48
+ questionToolAvailable,
49
+ usesWorkflowMcp,
50
+ reason: "question-tool-available",
51
+ };
52
+ }
53
+ export function supportsStructuredQuestions(activeTools, options = {}) {
54
+ return resolveQuestionTransport({
55
+ ...options,
56
+ activeTools,
57
+ }).structuredQuestionsAvailable === "true";
58
+ }
59
+ export function resolveWorkflowQuestionToolSurface(options) {
60
+ const questionToolName = options.workflowServerName && !options.workflowExplicitlyBlocked
61
+ ? toMcpToolName(options.workflowServerName, "ask_user_questions")
62
+ : undefined;
63
+ const activeTools = [
64
+ ...options.exactWorkflowMcpTools,
65
+ ...options.workflowMcpTools,
66
+ ...(questionToolName ? [questionToolName] : []),
67
+ ];
68
+ const transport = resolveQuestionTransport({
69
+ activeTools,
70
+ authMode: "externalCli",
71
+ baseUrl: "local://claude-code",
72
+ env: options.env,
73
+ });
74
+ const exactQuestionToolAllowed = !!questionToolName && options.exactWorkflowMcpTools.includes(questionToolName);
75
+ const workflowQuestionsEnabled = transport.structuredQuestionsAvailable === "true" &&
76
+ (options.workflowMcpTools.length > 0 || exactQuestionToolAllowed);
77
+ const disallowedTools = options.workflowServerName && transport.questionToolAvailable && !workflowQuestionsEnabled
78
+ ? [toMcpToolName(options.workflowServerName, "ask_user_questions")]
79
+ : [];
80
+ return {
81
+ ...transport,
82
+ questionToolName,
83
+ workflowQuestionsEnabled,
84
+ disallowedTools,
85
+ };
86
+ }
@@ -191,9 +191,15 @@ export function parseRoadmapSlices(content) {
191
191
  const riskMatch = rest.match(/`risk:(\w+)`/);
192
192
  const risk = (riskMatch ? riskMatch[1] : "low");
193
193
  const depsMatch = rest.match(/`depends:\[([^\]]*)\]`/);
194
- const depends = depsMatch && depsMatch[1].trim()
195
- ? expandDependencies(depsMatch[1].split(",").map(s => s.trim()))
194
+ // Recovery fallback: double-bracket form `[[id]]` from serialized bracket-wrapped IDs
195
+ const fallbackDepsMatch = depsMatch ? null : rest.match(/`depends:\[(\[(?:[^\]]*)\](?:,\[(?:[^\]]*)\])*)\]`/);
196
+ const rawDepContent = (depsMatch ?? fallbackDepsMatch)?.[1] ?? "";
197
+ const SLICE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
198
+ const RANGE_RE = /^[A-Za-z]+\d+(?:-|\.\.)[A-Za-z]+\d+$/;
199
+ const rawDepParts = rawDepContent.trim()
200
+ ? rawDepContent.replace(/\[|\]/g, "").split(",").map(s => s.trim()).filter(s => SLICE_ID_RE.test(s) || RANGE_RE.test(s))
196
201
  : [];
202
+ const depends = expandDependencies(rawDepParts);
197
203
  // ADR-011: the renderer writes a `[sketch]` badge for sketch slices.
198
204
  // Parse it back so the is_sketch flag survives a markdown → DB re-import
199
205
  // (e.g. /gsd recover); otherwise the flag was silently lost.
@@ -6,7 +6,12 @@
6
6
  const TEMPLATE_TOKEN_RE = /\{\{[^}]+\}\}/;
7
7
  const H2_RE = /^##\s+(.+)$/gm;
8
8
  const H3_RE = /^###\s+(.+)$/gm;
9
- const MILESTONE_LINE_RE = /^-\s+\[([ x])\]\s+(M\d{3}):\s+(.+?)\s+(?:—|--|-)\s+(.+)$/gm;
9
+ // A milestone line is single-line by construction. Every inter-token gap uses
10
+ // horizontal-whitespace classes (`[^\S\n]`) rather than `\s`, because `\s`
11
+ // matches newlines: a line missing a valid separator would otherwise let the
12
+ // `\s+(?:—|--|-)\s+` clause "bridge" onto the NEXT bullet's `- `, consuming it
13
+ // as the separator and silently swallowing the following well-formed milestone.
14
+ const MILESTONE_LINE_RE = /^-[^\S\n]+\[([ x])\][^\S\n]+(M\d{3}):[^\S\n]+(.+?)[^\S\n]+(?:—|--|-)[^\S\n]+(.+)$/gm;
10
15
  const SLICE_HEADER_RE = /^###\s+(S\d{2})\s*(?:—|--|-)\s+(.+)$/m;
11
16
  const REQUIREMENT_HEADER_RE = /^###\s+(R\d{3})\s*(?:—|--|-)\s+(.+)$/m;
12
17
  function splitH2Sections(content) {
@@ -19,7 +19,8 @@ import { isAbsolute, join, dirname, resolve } from "node:path";
19
19
  import { fileURLToPath } from "node:url";
20
20
  import { gsdRoot } from "./paths.js";
21
21
  import { createWorktree, worktreePath, removeWorktree } from "./worktree-manager.js";
22
- import { runWorktreePostCreateHook, syncGsdStateToWorktree } from "./auto-worktree.js";
22
+ import { runWorktreePostCreateHook, syncGsdStateToWorktreeByScope } from "./auto-worktree.js";
23
+ import { createWorkspace, scopeMilestone } from "./workspace.js";
23
24
  import { writeSessionStatus, } from "./session-status-io.js";
24
25
  import { hasFileConflict } from "./slice-parallel-conflict.js";
25
26
  import { getErrorMessage } from "./error-utils.js";
@@ -108,7 +109,7 @@ function createSliceWorktree(basePath, milestoneId, sliceId) {
108
109
  if (hookError) {
109
110
  throw new Error(`slice worktree post-create hook failed (${wtName}): ${hookError}`);
110
111
  }
111
- syncGsdStateToWorktree(basePath, wtPath);
112
+ syncGsdStateToWorktreeByScope(scopeMilestone(createWorkspace(basePath), milestoneId), scopeMilestone(createWorkspace(wtPath), milestoneId));
112
113
  if (!existsSync(join(wtPath, ".gsd"))) {
113
114
  throw new Error(`slice worktree preflight failed (${wtName}): missing .gsd in worktree`);
114
115
  }
@@ -250,7 +250,27 @@ function detectDiskSliceIdDivergenceForMilestone(basePath, milestoneId) {
250
250
  }
251
251
  return drifts;
252
252
  }
253
- export function detectArtifactDbDrift(_state, ctx) {
253
+ // #442 Phase 1.6: the three artifact/DB drift handlers (disk-slice-id,
254
+ // artifact-db-status, completed-milestone-reopened) each call
255
+ // detectArtifactDbDrift and then filter for their own kind — so the full
256
+ // milestone→slice→task walk + artifact SQL + disk scan would run THREE times
257
+ // per detection pass and discard 2/3 of the work. Memoize the result per
258
+ // DriftContext so the three handlers share one computation. The key is the
259
+ // ctx object, which detectAllDrift rebuilds for every pass (and which is
260
+ // unreferenced once the pass ends, so the WeakMap entry is GC'd) — DB/disk
261
+ // state is immutable within a single pass (repairs run only after detection),
262
+ // so this is behavior-preserving. A fresh ctx (e.g. the maintenance command's
263
+ // inline { basePath, state }) always recomputes.
264
+ const _artifactDbDriftMemo = new WeakMap();
265
+ export function detectArtifactDbDrift(state, ctx) {
266
+ const cached = _artifactDbDriftMemo.get(ctx);
267
+ if (cached)
268
+ return cached;
269
+ const computed = computeArtifactDbDrift(state, ctx);
270
+ _artifactDbDriftMemo.set(ctx, computed);
271
+ return computed;
272
+ }
273
+ function computeArtifactDbDrift(_state, ctx) {
254
274
  if (!isDbAvailable())
255
275
  return [];
256
276
  const drifts = [];
@@ -18,8 +18,10 @@ import { logWarning } from './workflow-logger.js';
18
18
  import { extractVerdict } from './verdict-parser.js';
19
19
  import { detectPendingEscalation } from './escalation.js';
20
20
  import { isTerminalMilestoneSummaryContent } from './milestone-summary-classifier.js';
21
- import { isDbAvailable, wasDbOpenAttempted, getAllMilestones, getMilestone, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, getRequirementCounts, getLatestAssessmentByScope, getPendingGateCountForTurn, } from './gsd-db.js';
21
+ import { isDbAvailable, getAllMilestones, getMilestone, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, getRequirementCounts, getLatestAssessmentByScope, getPendingGateCountForTurn, } from './gsd-db.js';
22
+ import { wasWorkflowDatabaseOpenAttempted } from './db-workspace.js';
22
23
  import { formatCompletePhaseNextAction, countUnmappedActiveRequirements } from './requirements-backlog.js';
24
+ import { classifyMilestoneReadiness, readinessNeedsDiscussion, } from './milestone-readiness.js';
23
25
  function formatNeedsAttentionBlocker(milestoneId) {
24
26
  return [
25
27
  `Milestone ${milestoneId} is blocked because milestone validation returned needs-attention.`,
@@ -301,7 +303,7 @@ export async function deriveState(basePath, opts) {
301
303
  _telemetry.dbDeriveCount++;
302
304
  }
303
305
  else {
304
- if (wasDbOpenAttempted()) {
306
+ if (wasWorkflowDatabaseOpenAttempted()) {
305
307
  logWarning("state", "DB unavailable — refusing implicit markdown state derivation");
306
308
  }
307
309
  result = {
@@ -396,6 +398,12 @@ async function buildRegistryAndFindActive(basePath, milestones, completeMileston
396
398
  const title = stripMilestonePrefix(m.title) || m.id;
397
399
  const hasContext = !!resolveMilestoneFile(basePath, m.id, "CONTEXT");
398
400
  const hasDraftContext = !hasContext && !!resolveMilestoneFile(basePath, m.id, "CONTEXT-DRAFT");
401
+ const readiness = classifyMilestoneReadiness({
402
+ status: m.status,
403
+ hasContext,
404
+ hasDraftContext,
405
+ sliceCount: slices.length,
406
+ });
399
407
  if (!activeMilestoneFound) {
400
408
  const deps = m.depends_on;
401
409
  const depsUnmet = deps.some(dep => !completeMilestoneIds.has(dep));
@@ -403,9 +411,9 @@ async function buildRegistryAndFindActive(basePath, milestones, completeMileston
403
411
  registry.push({ id: m.id, title, status: 'pending', dependsOn: deps });
404
412
  continue;
405
413
  }
406
- if (m.status === 'queued' && slices.length === 0 && !hasContext) {
414
+ if (readiness.kind === 'queued-shell') {
407
415
  if (!firstDeferredQueuedShell) {
408
- firstDeferredQueuedShell = { id: m.id, title, deps, hasDraftContext };
416
+ firstDeferredQueuedShell = { id: m.id, title, deps, hasDraftContext: readiness.hasDraftContext };
409
417
  }
410
418
  registry.push({ id: m.id, title, status: 'pending', ...(deps.length > 0 ? { dependsOn: deps } : {}) });
411
419
  continue;
@@ -417,7 +425,7 @@ async function buildRegistryAndFindActive(basePath, milestones, completeMileston
417
425
  registry.push({ id: m.id, title, status: 'active', ...(deps.length > 0 ? { dependsOn: deps } : {}) });
418
426
  continue;
419
427
  }
420
- if ((m.status === 'needs-discussion' && !hasContext) || hasDraftContext)
428
+ if (readinessNeedsDiscussion(readiness))
421
429
  activeMilestoneHasDraft = true;
422
430
  activeMilestone = { id: m.id, title };
423
431
  activeMilestoneSlices = slices;
@@ -46,6 +46,13 @@
46
46
  For simple projects or scripts:
47
47
  - Executable verification commands (bash assertions, curl checks, etc.) are sufficient
48
48
 
49
+ For browser-facing web apps (React, Next, Vue, Vite, static HTML, etc.):
50
+ - Prefer `npx playwright test <spec>` in Verification when `@playwright/test` exists
51
+ - If Playwright is not set up yet, the first UI slice should add `playwright.config.ts`,
52
+ a minimal smoke spec (for example `e2e/smoke.spec.ts`), and a safe verify command
53
+ - Slice closeout UAT must declare `browser-executable` or `runtime-executable` — not
54
+ `artifact-driven` — when checks navigate to localhost or exercise the live UI
55
+
49
56
  If the project has no test framework and the work is non-trivial,
50
57
  the first task should set one up. A test runner costs 2 minutes
51
58
  and pays for itself immediately.
@@ -20,6 +20,7 @@
20
20
 
21
21
  - **Complexity:** {{simple | complex}}
22
22
  - **Why:** {{one-line rationale citing the signals that decided it}}
23
+ - **Web stack:** {{browser-facing framework or "not a web UI" — e.g. Next.js + Playwright, static HTML, N/A for CLI/API-only}}
23
24
 
24
25
  ## Current State
25
26
 
@@ -42,7 +42,7 @@
42
42
  - Contract verification: {{tests / shell verifiers / fixtures / artifact checks}}
43
43
  - Integration verification: {{real subsystem interaction that must be exercised, or none}}
44
44
  - Operational verification: {{service lifecycle / restart / reconnect / supervision / deploy-install behavior, or none}}
45
- - UAT / human verification: {{what needs real human judgment, or none}}
45
+ - UAT / human verification: {{what needs real human judgment, or none — for web apps prefer browser-executable / runtime-executable Playwright checks over deferring UI proof to humans}}
46
46
 
47
47
  ## Milestone Definition of Done
48
48
 
@@ -5,9 +5,13 @@
5
5
 
6
6
  ## UAT Type
7
7
 
8
- - UAT mode: {{artifact-driven | live-runtime | human-experience | mixed}}
8
+ - UAT mode: {{artifact-driven | browser-executable | runtime-executable | live-runtime | human-experience | mixed}}
9
9
  - Why this mode is sufficient: {{reason}}
10
10
 
11
+ <!-- Web apps: never use artifact-driven when steps open a browser, navigate to localhost,
12
+ or capture screenshots. Use browser-executable (browser_* tools) or runtime-executable
13
+ (npx playwright test). Name dev-server preconditions below. -->
14
+
11
15
  ## Preconditions
12
16
 
13
17
  {{whatMustBeTrueBeforeTesting — server running, data seeded, etc.}}
@@ -4,6 +4,17 @@ import { resolveManifest, } from "./unit-context-manifest.js";
4
4
  import { getRequiredWorkflowToolsForAutoUnit } from "./workflow-mcp.js";
5
5
  import { getUnitToolSurfaceContract } from "./unit-tool-contracts.js";
6
6
  import { WHOLE_FILE_OBSERVATION_MAX_BYTES, WHOLE_FILE_OBSERVATION_MAX_LINES, } from "./source-observations.js";
7
+ export function compileUnitContextContract(unitType) {
8
+ const manifest = resolveManifest(unitType);
9
+ if (!manifest) {
10
+ return {
11
+ ok: false,
12
+ reason: "unknown-unit-type",
13
+ detail: `No Unit manifest is registered for ${unitType}`,
14
+ };
15
+ }
16
+ return { ok: true, contract: buildPromptContextContract(unitType, manifest) };
17
+ }
7
18
  export function compileUnitToolContract(unitType) {
8
19
  const manifest = resolveManifest(unitType);
9
20
  const surfaceContract = getUnitToolSurfaceContract(unitType);
@@ -25,6 +36,7 @@ export function compileUnitToolContract(unitType) {
25
36
  detail: `${unitType} has no closeout workflow tool`,
26
37
  };
27
38
  }
39
+ const promptContext = buildPromptContextContract(unitType, manifest);
28
40
  return {
29
41
  ok: true,
30
42
  contract: {
@@ -33,10 +45,8 @@ export function compileUnitToolContract(unitType) {
33
45
  toolsPolicy: manifest.tools,
34
46
  requiredWorkflowTools,
35
47
  forbiddenWorkflowTools,
36
- promptObligations: [
37
- `context-mode:${manifest.contextMode}`,
38
- `tools-policy:${manifest.tools.mode}`,
39
- ],
48
+ promptObligations: promptContext.obligations,
49
+ promptContext,
40
50
  validationRules: [
41
51
  "unit-manifest-present",
42
52
  "workflow-tool-surface-present",
@@ -44,15 +54,49 @@ export function compileUnitToolContract(unitType) {
44
54
  ...(unitType === "execute-task" ? ["source-observation-contract-present"] : []),
45
55
  ],
46
56
  closeoutTools,
47
- sourceObservations: sourceObservationContractForUnit(unitType),
57
+ sourceObservations: promptContext.sourceObservations,
48
58
  artifacts: {
49
- inline: manifest.artifacts.inline,
50
- excerpt: manifest.artifacts.excerpt,
51
- onDemand: manifest.artifacts.onDemand,
59
+ inline: promptContext.artifacts.inline,
60
+ excerpt: promptContext.artifacts.excerpt,
61
+ onDemand: promptContext.artifacts.onDemand,
52
62
  },
53
63
  },
54
64
  };
55
65
  }
66
+ function buildPromptContextContract(unitType, manifest) {
67
+ const sourceObservations = sourceObservationContractForUnit(unitType);
68
+ return {
69
+ unitType,
70
+ contextMode: manifest.contextMode,
71
+ toolsPolicy: manifest.tools,
72
+ obligations: promptContextObligations(manifest, sourceObservations),
73
+ sourceObservations,
74
+ artifacts: {
75
+ inline: manifest.artifacts.inline,
76
+ excerpt: manifest.artifacts.excerpt,
77
+ onDemand: manifest.artifacts.onDemand,
78
+ computed: manifest.artifacts.computed ?? [],
79
+ prepend: manifest.prepend ?? [],
80
+ },
81
+ maxSystemPromptChars: manifest.maxSystemPromptChars,
82
+ };
83
+ }
84
+ function promptContextObligations(manifest, sourceObservations) {
85
+ const obligations = [
86
+ `context-mode:${manifest.contextMode}`,
87
+ `tools-policy:${manifest.tools.mode}`,
88
+ artifactObligation("context-inline", manifest.artifacts.inline),
89
+ artifactObligation("context-excerpt", manifest.artifacts.excerpt),
90
+ artifactObligation("context-on-demand", manifest.artifacts.onDemand),
91
+ ];
92
+ if (sourceObservations.mode !== "none") {
93
+ obligations.push(`source-observations:${sourceObservations.mode}`);
94
+ }
95
+ return obligations;
96
+ }
97
+ function artifactObligation(label, artifacts) {
98
+ return `${label}:${artifacts.length > 0 ? artifacts.join(",") : "none"}`;
99
+ }
56
100
  function sourceObservationContractForUnit(unitType) {
57
101
  if (unitType !== "execute-task")
58
102
  return { mode: "none" };
@@ -1,7 +1,10 @@
1
1
  // Project/App: gsd-pi
2
2
  // File Purpose: Resolve phase-aware tool surfaces for GSD model presentations.
3
3
  import { RUN_UAT_BROWSER_TOOL_NAMES, RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_TOOL_PRESENTATION_PLAN_ID, RUN_UAT_WORKFLOW_TOOL_NAMES, } from "./unit-tool-contracts.js";
4
+ import { toMcpToolName } from "./mcp-tool-name.js";
5
+ import { createToolSurfaceSnapshot } from "./tool-surface-snapshot.js";
4
6
  import { uatTypeIncludesBrowser } from "./uat-policy.js";
7
+ import { canonicalWorkflowSurfaceToolName } from "./workflow-tool-surface.js";
5
8
  export { RUN_UAT_BROWSER_TOOL_NAMES, RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_TOOL_PRESENTATION_PLAN_ID, RUN_UAT_WORKFLOW_TOOL_NAMES, } from "./unit-tool-contracts.js";
6
9
  export const RUN_UAT_FORBIDDEN_TOOL_NAMES = [
7
10
  "edit",
@@ -21,43 +24,12 @@ export const RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES = [
21
24
  "Glob",
22
25
  "Grep",
23
26
  ];
24
- const WORKFLOW_ALIAS_TO_CANONICAL = {
25
- gsd_save_decision: "gsd_decision_save",
26
- gsd_update_requirement: "gsd_requirement_update",
27
- gsd_save_requirement: "gsd_requirement_save",
28
- gsd_save_summary: "gsd_summary_save",
29
- gsd_generate_milestone_id: "gsd_milestone_generate_id",
30
- gsd_milestone_plan: "gsd_plan_milestone",
31
- gsd_slice_plan: "gsd_plan_slice",
32
- gsd_task_plan: "gsd_plan_task",
33
- gsd_slice_replan: "gsd_replan_slice",
34
- gsd_complete_slice: "gsd_slice_complete",
35
- gsd_milestone_complete: "gsd_complete_milestone",
36
- gsd_milestone_validate: "gsd_validate_milestone",
37
- gsd_roadmap_reassess: "gsd_reassess_roadmap",
38
- gsd_complete_task: "gsd_task_complete",
39
- gsd_reopen_task: "gsd_task_reopen",
40
- gsd_reopen_slice: "gsd_slice_reopen",
41
- gsd_reopen_milestone: "gsd_milestone_reopen",
42
- };
43
27
  export function canonicalWorkflowToolName(toolName) {
44
- const mcp = parseMcpToolName(toolName);
45
- const baseName = mcp?.tool ?? toolName;
46
- return WORKFLOW_ALIAS_TO_CANONICAL[baseName] ?? baseName;
47
- }
48
- export function parseMcpToolName(toolName) {
49
- if (!toolName.startsWith("mcp__"))
50
- return null;
51
- const toolSeparator = toolName.indexOf("__", "mcp__".length);
52
- if (toolSeparator < 0)
53
- return null;
54
- return {
55
- server: toolName.slice("mcp__".length, toolSeparator),
56
- tool: toolName.slice(toolSeparator + 2),
57
- };
28
+ return canonicalWorkflowSurfaceToolName(toolName);
58
29
  }
30
+ export { parseMcpToolName } from "./mcp-tool-name.js";
59
31
  export function toWorkflowMcpToolName(serverName, toolName) {
60
- return `mcp__${serverName}__${canonicalWorkflowToolName(toolName)}`;
32
+ return toMcpToolName(serverName, canonicalWorkflowToolName(toolName));
61
33
  }
62
34
  function dedupe(values) {
63
35
  return [...new Set(values)];
@@ -134,6 +106,14 @@ export function resolveToolPresentationPlan(options) {
134
106
  ? toWorkflowMcpToolName(workflowServerName, name)
135
107
  : name)
136
108
  : allowedToolNames;
109
+ const toolSurface = createToolSurfaceSnapshot({
110
+ source: "presentation-plan",
111
+ phase: options.phase,
112
+ modelFacingToolNames: options.availableToolNames ?? requested,
113
+ registeredToolNames: options.availableToolNames ?? requested,
114
+ scopedToolNames: allowedToolNames,
115
+ presentedToolNames,
116
+ });
137
117
  if (options.phase === "run-uat") {
138
118
  for (const forbidden of RUN_UAT_FORBIDDEN_TOOL_NAMES) {
139
119
  addBlockedTool(blockedToolNames, forbidden, "forbidden during run-uat");
@@ -148,5 +128,6 @@ export function resolveToolPresentationPlan(options) {
148
128
  blockedToolNames,
149
129
  aliases,
150
130
  diagnostics: [],
131
+ toolSurface,
151
132
  };
152
133
  }
@@ -0,0 +1,17 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Typed snapshots for model-facing, registered, scoped, and presented tool surfaces.
3
+ function dedupeToolNames(toolNames) {
4
+ return [...new Set(toolNames ?? [])];
5
+ }
6
+ export function createToolSurfaceSnapshot(input) {
7
+ return {
8
+ source: input.source,
9
+ unitType: input.unitType,
10
+ phase: input.phase,
11
+ modelFacingToolNames: dedupeToolNames(input.modelFacingToolNames),
12
+ registeredToolNames: dedupeToolNames(input.registeredToolNames),
13
+ scopedToolNames: dedupeToolNames(input.scopedToolNames),
14
+ presentedToolNames: dedupeToolNames(input.presentedToolNames),
15
+ capturedAt: input.capturedAt ?? Date.now(),
16
+ };
17
+ }