@opengsd/gsd-pi 1.2.0-dev.844675c9 → 1.2.0-dev.b1abb545

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 (375) 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/resources/.managed-resources-content-hash +1 -1
  5. package/dist/resources/extensions/ask-user-questions.js +78 -23
  6. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +84 -228
  7. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
  8. package/dist/resources/extensions/github-sync/templates.js +3 -3
  9. package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
  10. package/dist/resources/extensions/gsd/auto/loop.js +74 -56
  11. package/dist/resources/extensions/gsd/auto/orchestrator.js +109 -11
  12. package/dist/resources/extensions/gsd/auto/phases.js +28 -3
  13. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
  14. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  15. package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
  17. package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
  18. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
  19. package/dist/resources/extensions/gsd/auto-prompts.js +81 -8
  20. package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
  21. package/dist/resources/extensions/gsd/auto-runtime-state.js +14 -0
  22. package/dist/resources/extensions/gsd/auto-start.js +12 -23
  23. package/dist/resources/extensions/gsd/auto-timers.js +16 -2
  24. package/dist/resources/extensions/gsd/auto-tool-tracking.js +32 -0
  25. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +4 -29
  26. package/dist/resources/extensions/gsd/auto-verification.js +7 -7
  27. package/dist/resources/extensions/gsd/auto-worktree.js +21 -19
  28. package/dist/resources/extensions/gsd/auto.js +11 -7
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
  30. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -138
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
  34. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
  35. package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
  36. package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
  37. package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
  38. package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
  39. package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
  40. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  41. package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
  42. package/dist/resources/extensions/gsd/db-workspace.js +103 -0
  43. package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
  44. package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
  45. package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  46. package/dist/resources/extensions/gsd/doctor.js +16 -9
  47. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  48. package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
  49. package/dist/resources/extensions/gsd/gsd-db.js +12 -0
  50. package/dist/resources/extensions/gsd/guided-flow.js +34 -468
  51. package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
  52. package/dist/resources/extensions/gsd/markdown-renderer.js +2 -1
  53. package/dist/resources/extensions/gsd/mcp-filter.js +2 -1
  54. package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
  55. package/dist/resources/extensions/gsd/md-importer.js +4 -3
  56. package/dist/resources/extensions/gsd/migrate/safety.js +2 -2
  57. package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
  58. package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
  59. package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
  60. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
  61. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
  62. package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
  63. package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
  64. package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
  65. package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
  66. package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
  67. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
  68. package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
  69. package/dist/resources/extensions/gsd/preferences.js +147 -29
  70. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  71. package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  73. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  74. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  75. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  76. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  77. package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
  78. package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
  79. package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
  80. package/dist/resources/extensions/gsd/question-transport.js +86 -0
  81. package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
  82. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
  83. package/dist/resources/extensions/gsd/state.js +13 -5
  84. package/dist/resources/extensions/gsd/templates/plan.md +7 -0
  85. package/dist/resources/extensions/gsd/templates/project.md +1 -0
  86. package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
  87. package/dist/resources/extensions/gsd/templates/uat.md +5 -1
  88. package/dist/resources/extensions/gsd/tool-contract.js +52 -8
  89. package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
  90. package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
  91. package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
  92. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
  93. package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
  94. package/dist/resources/extensions/gsd/uat-policy.js +16 -10
  95. package/dist/resources/extensions/gsd/uat-run.js +9 -14
  96. package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
  97. package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
  98. package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
  99. package/dist/resources/extensions/gsd/user-input-boundary.js +23 -0
  100. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  101. package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
  102. package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
  103. package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
  104. package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
  105. package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
  106. package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
  107. package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
  108. package/dist/resources/extensions/shared/interview-ui.js +2 -2
  109. package/dist/resources/shared/claude-runtime-floor.js +182 -0
  110. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  111. package/dist/update-cmd.js +20 -0
  112. package/dist/web/standalone/.next/BUILD_ID +1 -1
  113. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  114. package/dist/web/standalone/.next/build-manifest.json +3 -3
  115. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  116. package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
  117. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/index.html +1 -1
  134. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  141. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  142. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  145. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  146. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  147. package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
  148. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
  149. package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
  150. package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
  151. package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
  152. package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
  153. package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
  154. package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
  155. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  156. package/dist/web-mode.d.ts +2 -0
  157. package/dist/web-mode.js +20 -8
  158. package/package.json +2 -1
  159. package/packages/cloud-mcp-gateway/package.json +2 -2
  160. package/packages/contracts/package.json +1 -1
  161. package/packages/daemon/package.json +4 -4
  162. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
  163. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  164. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
  165. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  166. package/packages/gsd-agent-core/package.json +5 -5
  167. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  171. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
  172. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  173. package/packages/gsd-agent-modes/package.json +7 -7
  174. package/packages/mcp-server/dist/server.d.ts +10 -0
  175. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  176. package/packages/mcp-server/dist/server.js +8 -0
  177. package/packages/mcp-server/dist/server.js.map +1 -1
  178. package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
  179. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  180. package/packages/mcp-server/dist/workflow-tools.js +2 -1
  181. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  182. package/packages/mcp-server/package.json +3 -3
  183. package/packages/native/package.json +1 -1
  184. package/packages/pi-agent-core/package.json +1 -1
  185. package/packages/pi-ai/dist/models.generated.d.ts +8 -93
  186. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  187. package/packages/pi-ai/dist/models.generated.js +35 -120
  188. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  189. package/packages/pi-ai/package.json +1 -1
  190. package/packages/pi-coding-agent/package.json +7 -7
  191. package/packages/pi-tui/dist/components/input.js +1 -1
  192. package/packages/pi-tui/dist/components/input.js.map +1 -1
  193. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  194. package/packages/pi-tui/dist/keys.js +39 -30
  195. package/packages/pi-tui/dist/keys.js.map +1 -1
  196. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  197. package/packages/pi-tui/dist/stdin-buffer.js +22 -0
  198. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  199. package/packages/pi-tui/package.json +2 -2
  200. package/packages/rpc-client/package.json +2 -2
  201. package/pkg/package.json +1 -1
  202. package/src/resources/extensions/ask-user-questions.ts +87 -24
  203. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +108 -281
  204. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +240 -0
  205. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
  206. package/src/resources/extensions/github-sync/templates.ts +3 -3
  207. package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
  208. package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
  209. package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
  210. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  211. package/src/resources/extensions/gsd/auto/loop.ts +83 -61
  212. package/src/resources/extensions/gsd/auto/orchestrator.ts +125 -12
  213. package/src/resources/extensions/gsd/auto/phases.ts +35 -3
  214. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
  215. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  216. package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
  217. package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
  218. package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
  219. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -3
  220. package/src/resources/extensions/gsd/auto-prompts.ts +107 -9
  221. package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
  222. package/src/resources/extensions/gsd/auto-runtime-state.ts +26 -0
  223. package/src/resources/extensions/gsd/auto-start.ts +17 -20
  224. package/src/resources/extensions/gsd/auto-timers.ts +16 -2
  225. package/src/resources/extensions/gsd/auto-tool-tracking.ts +35 -0
  226. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +9 -30
  227. package/src/resources/extensions/gsd/auto-verification.ts +7 -8
  228. package/src/resources/extensions/gsd/auto-worktree.ts +33 -26
  229. package/src/resources/extensions/gsd/auto.ts +15 -8
  230. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
  231. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
  232. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  233. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +116 -151
  234. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
  235. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
  236. package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
  237. package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
  238. package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
  239. package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
  240. package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
  241. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  242. package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
  243. package/src/resources/extensions/gsd/db-workspace.ts +170 -0
  244. package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
  245. package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
  246. package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  247. package/src/resources/extensions/gsd/doctor.ts +15 -5
  248. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  249. package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
  250. package/src/resources/extensions/gsd/gsd-db.ts +12 -0
  251. package/src/resources/extensions/gsd/guided-flow.ts +47 -558
  252. package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
  253. package/src/resources/extensions/gsd/markdown-renderer.ts +2 -1
  254. package/src/resources/extensions/gsd/mcp-filter.ts +2 -1
  255. package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
  256. package/src/resources/extensions/gsd/md-importer.ts +3 -3
  257. package/src/resources/extensions/gsd/migrate/safety.ts +2 -2
  258. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  259. package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
  260. package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
  261. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
  262. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
  263. package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
  264. package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
  265. package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
  266. package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
  267. package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
  268. package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
  269. package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
  270. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  271. package/src/resources/extensions/gsd/preferences.ts +173 -28
  272. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  273. package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
  274. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  275. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  276. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  277. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  278. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  279. package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
  280. package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
  281. package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
  282. package/src/resources/extensions/gsd/question-transport.ts +138 -0
  283. package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
  284. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
  285. package/src/resources/extensions/gsd/state.ts +15 -5
  286. package/src/resources/extensions/gsd/templates/plan.md +7 -0
  287. package/src/resources/extensions/gsd/templates/project.md +1 -0
  288. package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
  289. package/src/resources/extensions/gsd/templates/uat.md +5 -1
  290. package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
  291. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
  292. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -5
  293. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
  294. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
  295. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +133 -4
  296. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
  297. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
  298. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  299. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
  300. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
  301. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
  302. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
  303. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
  304. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
  305. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
  306. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
  307. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
  308. package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
  309. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
  310. package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
  311. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
  312. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
  313. package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
  314. package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
  315. package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
  316. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
  317. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  318. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
  319. package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
  320. package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
  321. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +46 -0
  322. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
  323. package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
  324. package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
  325. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +94 -0
  326. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
  327. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
  328. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
  329. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
  330. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
  331. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +2 -1
  332. package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
  333. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
  334. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
  335. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
  336. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +86 -1
  337. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
  338. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
  339. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
  340. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
  341. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +21 -0
  342. package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
  343. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
  344. package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -0
  345. package/src/resources/extensions/gsd/tool-contract.ts +86 -8
  346. package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
  347. package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
  348. package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
  349. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
  350. package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
  351. package/src/resources/extensions/gsd/uat-policy.ts +19 -10
  352. package/src/resources/extensions/gsd/uat-run.ts +10 -14
  353. package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
  354. package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
  355. package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
  356. package/src/resources/extensions/gsd/user-input-boundary.ts +18 -0
  357. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  358. package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
  359. package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
  360. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  361. package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
  362. package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
  363. package/src/resources/extensions/gsd/worktree-lifecycle.ts +7 -16
  364. package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
  365. package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
  366. package/src/resources/extensions/shared/interview-ui.ts +15 -2
  367. package/src/resources/shared/claude-runtime-floor.ts +248 -0
  368. package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
  369. package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
  370. package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
  371. package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
  372. package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
  373. package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
  374. /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_buildManifest.js +0 -0
  375. /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_ssgManifest.js +0 -0
@@ -7,11 +7,12 @@ import { isToolCallEventType } from "@gsd/pi-coding-agent";
7
7
  import { ALWAYS_PRESERVED_SHIM_TOOL_NAMES } from "@gsd/pi-ai";
8
8
  import { updateSnapshot } from "../ecosystem/gsd-extension-api.js";
9
9
  import { buildMilestoneFileName, clearPathCache, milestonesDir, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
10
- import { canonicalToolName, clearDiscussionFlowState, isDepthConfirmationAnswer, isMilestoneDepthVerified, isQueuePhaseActive, markApprovalGateVerified, markDepthVerified, resetWriteGateState, shouldBlockContextWrite, shouldBlockPlanningUnit, shouldBlockQueueExecution, shouldBlockWorktreeWrite, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
10
+ import { applyAskUserQuestionsGateResult, canonicalToolName, clearDiscussionFlowState, formatPendingAskUserQuestionsGateMessage, isMilestoneDepthVerified, isQueuePhaseActive, markApprovalGateVerified, markDepthVerified, resetWriteGateState, shouldBlockContextWrite, shouldBlockPlanningUnit, shouldBlockQueueExecution, shouldBlockWorktreeWrite, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
11
11
  import { resolveManifest } from "../unit-context-manifest.js";
12
12
  import { isBlockedStateFile, isBashWriteToStateFile, BLOCKED_WRITE_ERROR } from "../write-intercept.js";
13
13
  import { loadFile, saveFile, formatContinue } from "../files.js";
14
- import { clearAutoCompletionStopInProgress, clearToolInvocationError, getAutoRuntimeSnapshot, getSourceObservationStore, isAutoActive, isAutoCompletionStopInProgress, isAutoPaused, markToolEnd, markToolStart, recordToolInvocationError, } from "../auto-runtime-state.js";
14
+ import { clearAutoCompletionStopInProgress, clearToolInvocationError, getAutoRuntimeSnapshot, getSourceObservationStore, isAutoActive, isAutoCompletionStopInProgress, isAutoPaused, isInteractiveElicitationInFlight, markToolEnd, markToolStart, recordAutoToolSurfaceSnapshot, recordToolInvocationError, } from "../auto-runtime-state.js";
15
+ import { applyProviderPayloadPolicy } from "../provider-payload-policy.js";
15
16
  import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
16
17
  import { maybePauseAutoForApprovalGate, resetPendingGatePauseGuard } from "./pending-gate-pause.js";
17
18
  import { saveActivityLog } from "../activity-log.js";
@@ -22,16 +23,18 @@ import { logWarning as safetyLogWarning } from "../workflow-logger.js";
22
23
  import { installNotifyInterceptor } from "./notify-interceptor.js";
23
24
  import { initNotificationStore } from "../notification-store.js";
24
25
  import { initNotificationWidget } from "../notification-widget.js";
26
+ import { notifyPreferenceDiagnostics } from "../preferences-diagnostics.js";
25
27
  import { resolveWorktreeProjectRoot } from "../worktree-root.js";
26
28
  import { extractSubagentAgentClasses } from "./subagent-input.js";
27
- import { approvalGateIdForUnit, isExplicitApprovalResponse, shouldPauseForUserApprovalQuestion } from "../user-input-boundary.js";
29
+ import { approvalGateIdForUnit, isExplicitApprovalResponse, messageHasPendingAskUserQuestionsTool, shouldPauseForUserApprovalQuestion, } from "../user-input-boundary.js";
28
30
  import { applyUnitSkillVisibility, unitHasSkillManifest } from "../skill-scope.js";
29
31
  import { getGuidedUnitContext } from "../guided-unit-context.js";
30
32
  import { registerPlanMilestoneSchemaRecovery } from "./plan-milestone-schema-recovery.js";
31
- import { AUTO_UNIT_SCOPED_TOOLS, RUN_UAT_BROWSER_TOOL_NAMES, isWorkflowAliasTool } from "../auto-unit-tool-scope.js";
33
+ import { AUTO_UNIT_SCOPED_TOOLS, RUN_UAT_BROWSER_TOOL_NAMES, canonicalWorkflowToolName, isWorkflowAliasTool } from "../auto-unit-tool-scope.js";
32
34
  import { filterToolsForProvider } from "../model-router.js";
35
+ import { mcpToolMatchesBaseName } from "../mcp-tool-name.js";
33
36
  import { RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES } from "../tool-presentation-plan.js";
34
- import { injectSourceContextBlockIntoPayload, supportsSourceObservationsForUnit } from "../source-observations.js";
37
+ import { supportsSourceObservationsForUnit } from "../source-observations.js";
35
38
  let approvalQuestionAbortInFlight = false;
36
39
  async function loadWelcomeScreenModule() {
37
40
  const candidates = [];
@@ -165,15 +168,19 @@ function resolveScopedToolNames(activeToolNames, requestedToolNames) {
165
168
  const resolved = new Set();
166
169
  for (const requested of requestedToolNames) {
167
170
  const scopedMatches = [];
171
+ const aliasFallbacks = [];
168
172
  for (const activeName of activeToolNames) {
169
- if (!activeName.startsWith("mcp__"))
170
- continue;
171
- const toolSeparator = activeName.indexOf("__", "mcp__".length);
172
- if (toolSeparator < 0)
173
- continue;
174
- if (activeName.slice(toolSeparator + 2) === requested) {
173
+ if (mcpToolMatchesBaseName(activeName, requested)) {
175
174
  scopedMatches.push(activeName);
176
175
  }
176
+ else if (isWorkflowAliasTool(activeName) && canonicalWorkflowToolName(activeName) === requested) {
177
+ aliasFallbacks.push(activeName);
178
+ }
179
+ }
180
+ // Only use alias as fallback when canonical is absent — not directly and not via MCP scoping.
181
+ // Prevents the alias from resurfacing alongside the canonical when both are in the active set.
182
+ if (!exact.has(requested) && scopedMatches.length === 0) {
183
+ scopedMatches.push(...aliasFallbacks);
177
184
  }
178
185
  if (requested.startsWith("browser_") && scopedMatches.length > 0) {
179
186
  for (const match of scopedMatches)
@@ -214,7 +221,7 @@ export function buildRunUatGsdToolSet(activeToolNames, registeredToolNames = act
214
221
  ...RUN_UAT_BROWSER_TOOL_NAMES,
215
222
  ]);
216
223
  const resolved = [...new Set(scoped)];
217
- const unresolved = RUN_UAT_WORKFLOW_TOOL_NAMES.filter((tool) => !resolved.some((name) => name === tool || (name.startsWith("mcp__") && name.endsWith(`__${tool}`))));
224
+ const unresolved = RUN_UAT_WORKFLOW_TOOL_NAMES.filter((tool) => !resolved.some((name) => name === tool || mcpToolMatchesBaseName(name, tool)));
218
225
  if (unresolved.length > 0) {
219
226
  safetyLogWarning("bootstrap", `buildRunUatGsdToolSet: required run-uat workflow tool(s) not found in active/registered surface: ${unresolved.join(", ")}. Session may lack gsd-workflow MCP connection.`);
220
227
  }
@@ -271,7 +278,17 @@ function applyMinimalGsdToolSurface(pi) {
271
278
  return;
272
279
  const dash = getAutoRuntimeSnapshot();
273
280
  if (dash.active && dash.currentUnit) {
274
- pi.setActiveTools(buildMinimalAutoGsdToolSet(pi.getActiveTools(), dash.currentUnit.type, resolveRegisteredToolNames(pi, pi.getActiveTools())));
281
+ const currentToolNames = pi.getActiveTools();
282
+ const registeredToolNames = resolveRegisteredToolNames(pi, currentToolNames);
283
+ const scopedToolNames = buildMinimalAutoGsdToolSet(currentToolNames, dash.currentUnit.type, registeredToolNames);
284
+ recordAutoToolSurfaceSnapshot({
285
+ source: "runtime-scope",
286
+ unitType: dash.currentUnit.type,
287
+ modelFacingToolNames: scopedToolNames,
288
+ registeredToolNames,
289
+ scopedToolNames,
290
+ });
291
+ pi.setActiveTools(scopedToolNames);
275
292
  return;
276
293
  }
277
294
  if (!isGeneralGsdToolScopingRequested())
@@ -286,6 +303,13 @@ export function scopeGsdWorkflowToolsForDispatch(pi, unitType) {
286
303
  const scoped = unitType
287
304
  ? buildMinimalAutoGsdToolSet(current, unitType, registeredToolNames)
288
305
  : buildMinimalGsdWorkflowToolSet(current, registeredToolNames);
306
+ recordAutoToolSurfaceSnapshot({
307
+ source: "dispatch-scope",
308
+ unitType,
309
+ modelFacingToolNames: scoped,
310
+ registeredToolNames,
311
+ scopedToolNames: scoped,
312
+ });
289
313
  const toolsChanged = !(scoped.length === current.length && scoped.every((name, index) => name === current[index]));
290
314
  const canScopeSkills = unitHasSkillManifest(unitType) && pi.getVisibleSkills && pi.setVisibleSkills;
291
315
  if (!toolsChanged && !canScopeSkills) {
@@ -540,6 +564,7 @@ function initSessionNotifications(ctx) {
540
564
  initNotificationStore(resolveNotificationStoreBasePath(contextBasePath(ctx)));
541
565
  installNotifyInterceptor(ctx);
542
566
  initNotificationWidget(ctx);
567
+ notifyPreferenceDiagnostics(ctx, contextBasePath(ctx), { surface: "session-start" });
543
568
  }
544
569
  async function prepareWorkflowMcpForHookContext(ctx, basePath) {
545
570
  // Skip MCP auto-prep when running inside an auto-worktree. The worktree
@@ -803,6 +828,20 @@ export function registerHooks(pi, ecosystemHandlers) {
803
828
  pi.on("message_update", async (event, ctx) => {
804
829
  if (approvalQuestionAbortInFlight)
805
830
  return;
831
+ // If the model asked via ask_user_questions, that in-flight elicitation IS
832
+ // the human boundary. Arming the pause/gate here (and emitting the "waiting
833
+ // for your approval - pausing" notice) would tear it down and trigger the
834
+ // foreground self-cancel/re-ask loop. The marker is set only by the
835
+ // claude-code-cli SDK elicitation handler and is ungated, so it is true in
836
+ // foreground; under the native-TUI provider it is always false and this path
837
+ // runs unchanged (#cc-elicitation-self-cancel).
838
+ if (isInteractiveElicitationInFlight())
839
+ return;
840
+ // Prose with "?" can stream before the MCP tool/elicitation starts. When the
841
+ // structured ask_user_questions call is already in the partial message, the
842
+ // tool IS the human boundary — do not arm the text-based approval pause.
843
+ if (messageHasPendingAskUserQuestionsTool(event.message))
844
+ return;
806
845
  const dash = getAutoRuntimeSnapshot();
807
846
  if (dash.active)
808
847
  return;
@@ -1071,77 +1110,32 @@ export function registerHooks(pi, ecosystemHandlers) {
1071
1110
  const basePath = contextBasePath(ctx);
1072
1111
  const milestoneId = await getDiscussionMilestoneIdFor(basePath);
1073
1112
  const details = event.details;
1074
- // ── Discussion gate enforcement: handle gate question responses ──
1075
- // If the result is cancelled or has no response, the pending gate stays active
1076
- // so the model is blocked from non-read-only tools until it re-asks.
1077
- // If the user responded at all (even "needs adjustment"), clear the pending gate
1078
- // because the user engaged — the prompt handles the re-ask-after-adjustment flow.
1079
1113
  const questions = event.input?.questions ?? [];
1080
- const currentPendingGate = getPendingGate(basePath);
1081
- if (currentPendingGate) {
1082
- if (details?.cancelled || !details?.response) {
1083
- // Gate stays pending. Direct the agent to the most reliable recovery
1084
- // path — re-calling ask_user_questions with the same gate id — without
1085
- // misrepresenting the plain-text path. The plain-text path also works
1086
- // (isExplicitApprovalResponse on the next before_agent_start clears
1087
- // the gate when the user replies with an approval keyword), but the
1088
- // structured re-ask is more deterministic and gives the user a clear UI.
1089
- resetToolCallLoopGuard();
1090
- const interrupted = details?.interrupted === true;
1091
- if (ctx) {
1092
- await maybePauseAutoForApprovalGate(ctx, pi, true, interrupted
1093
- ? "Depth confirmation was interrupted — pausing auto-mode until you respond."
1094
- : "Depth confirmation is waiting for your answer — pausing auto-mode.");
1095
- }
1096
- return {
1097
- content: [{
1098
- type: "text",
1099
- text: [
1100
- `Waiting for depth confirmation on gate "${currentPendingGate}".`,
1101
- interrupted
1102
- ? "The confirmation question was interrupted before a response was recorded."
1103
- : "No user response was received for the confirmation question.",
1104
- "Do not infer approval from earlier or prior messages.",
1105
- "Do not proceed, write files, save artifacts, or call other tools.",
1106
- `Re-call ask_user_questions with the same gate question id ("${currentPendingGate}") and wait for the user's response.`,
1107
- ].join(" "),
1108
- }],
1109
- };
1110
- }
1111
- else {
1112
- const pendingQuestion = questions.find((question) => question?.id === currentPendingGate);
1113
- if (pendingQuestion) {
1114
- const answer = details.response?.answers?.[currentPendingGate];
1115
- if (isDepthConfirmationAnswer(answer?.selected, pendingQuestion.options)) {
1116
- markApprovalGateVerified(currentPendingGate, basePath);
1117
- const milestoneIdFromGate = extractDepthVerificationMilestoneId(currentPendingGate);
1118
- if (milestoneIdFromGate)
1119
- markDepthVerified(milestoneIdFromGate, basePath);
1120
- clearPendingGate(basePath);
1121
- clearDeferredApprovalGate(basePath);
1122
- }
1123
- }
1114
+ const gateResult = applyAskUserQuestionsGateResult({
1115
+ basePath,
1116
+ questions,
1117
+ details,
1118
+ fallbackMilestoneId: milestoneId,
1119
+ });
1120
+ if (gateResult.status === "waiting") {
1121
+ resetToolCallLoopGuard();
1122
+ if (ctx) {
1123
+ await maybePauseAutoForApprovalGate(ctx, pi, true, gateResult.interrupted
1124
+ ? "Depth confirmation was interrupted pausing auto-mode until you respond."
1125
+ : "Depth confirmation is waiting for your answer — pausing auto-mode.");
1124
1126
  }
1127
+ return {
1128
+ content: [{
1129
+ type: "text",
1130
+ text: formatPendingAskUserQuestionsGateMessage(gateResult.pendingGateId, gateResult.interrupted),
1131
+ }],
1132
+ };
1133
+ }
1134
+ if (gateResult.status === "verified") {
1135
+ clearDeferredApprovalGate(basePath);
1125
1136
  }
1126
1137
  if (details?.cancelled || !details?.response)
1127
1138
  return;
1128
- for (const question of questions) {
1129
- if (typeof question.id === "string" && question.id.includes("depth_verification")) {
1130
- // Only unlock the gate if the user selected the first option (confirmation).
1131
- // Cross-references against the question's defined options to reject free-form "Other" text.
1132
- const answer = details.response?.answers?.[question.id];
1133
- const inferredMilestoneId = extractDepthVerificationMilestoneId(question.id) ?? milestoneId;
1134
- if (isDepthConfirmationAnswer(answer?.selected, question.options)) {
1135
- if (currentPendingGate && question.id !== currentPendingGate)
1136
- break;
1137
- markApprovalGateVerified(question.id, basePath);
1138
- markDepthVerified(inferredMilestoneId, basePath);
1139
- clearPendingGate(basePath);
1140
- clearDeferredApprovalGate(basePath);
1141
- }
1142
- break;
1143
- }
1144
- }
1145
1139
  if (!milestoneId)
1146
1140
  return;
1147
1141
  await saveDiscussionQuestionRound(basePath, milestoneId, questions, details);
@@ -1196,61 +1190,10 @@ export function registerHooks(pi, ecosystemHandlers) {
1196
1190
  const payload = event.payload;
1197
1191
  if (!payload || typeof payload !== "object")
1198
1192
  return;
1199
- // ── Context Management ──────────────────────────────────────────────
1200
- // Load preferences once for both masking and truncation.
1201
- try {
1202
- const { loadEffectiveGSDPreferences } = await import("../preferences.js");
1203
- const { createObservationMask, createResponsesInputObservationMask, truncateContextResultMessages, truncateResponsesInputResultItems, } = await import("../context-masker.js");
1204
- const prefs = loadEffectiveGSDPreferences();
1205
- const cmConfig = prefs?.preferences.context_management;
1206
- // Observation masking: replace old tool results with placeholders.
1207
- // Only active during auto-mode when context_management.observation_masking is enabled.
1208
- if (isAutoActive() && cmConfig?.observation_masking !== false) {
1209
- const keepTurns = cmConfig?.observation_mask_turns ?? 8;
1210
- const messages = payload.messages;
1211
- if (Array.isArray(messages)) {
1212
- payload.messages = createObservationMask(keepTurns)(messages);
1213
- }
1214
- const input = payload.input;
1215
- if (Array.isArray(input)) {
1216
- payload.input = createResponsesInputObservationMask(keepTurns)(input);
1217
- }
1218
- }
1219
- // Tool result truncation: cap individual tool result content length.
1220
- // Applies in ALL modes (auto + interactive) to prevent context bloat.
1221
- // In pi-ai format, toolResult messages have role: "toolResult" and content: TextContent[].
1222
- // Creates new objects to avoid mutating shared conversation state.
1223
- const maxChars = cmConfig?.tool_result_max_chars ?? 800;
1224
- const msgs = payload.messages;
1225
- if (Array.isArray(msgs)) {
1226
- payload.messages = truncateContextResultMessages(msgs, maxChars);
1227
- }
1228
- const input = payload.input;
1229
- if (Array.isArray(input)) {
1230
- payload.input = truncateResponsesInputResultItems(input, maxChars);
1231
- }
1232
- }
1233
- catch { /* non-fatal */ }
1234
- try {
1235
- if (isAutoActive()) {
1236
- const sourceContextBlock = getSourceObservationStore().renderActiveBlock();
1237
- if (sourceContextBlock) {
1238
- const nextPayload = injectSourceContextBlockIntoPayload(payload, sourceContextBlock);
1239
- Object.assign(payload, nextPayload);
1240
- }
1241
- }
1242
- }
1243
- catch { /* non-fatal */ }
1244
- // ── Service Tier ────────────────────────────────────────────────────
1245
- const modelId = event.model?.id;
1246
- if (!modelId)
1247
- return payload;
1248
- const { getEffectiveServiceTier, supportsServiceTier } = await import("../service-tier.js");
1249
- const tier = getEffectiveServiceTier();
1250
- if (!tier || !supportsServiceTier(modelId))
1251
- return payload;
1252
- payload.service_tier = tier;
1253
- return payload;
1193
+ return applyProviderPayloadPolicy({
1194
+ payload,
1195
+ modelId: event.model?.id,
1196
+ });
1254
1197
  });
1255
1198
  // Capability-aware model routing hook (ADR-004)
1256
1199
  // Extensions can override model selection by returning { modelId: "..." }
@@ -1282,16 +1225,35 @@ export function registerHooks(pi, ecosystemHandlers) {
1282
1225
  const registeredToolNames = resolveRegisteredToolNames(pi, event.activeToolNames);
1283
1226
  const compatibleRegisteredToolNames = filterToolsForProvider(registeredToolNames, event.selectedModelApi, event.selectedModelProvider).compatible.filter((name) => !(dropAliases && isWorkflowAliasTool(name)));
1284
1227
  const guidedUnit = getGuidedUnitContext();
1285
- const requestScoped = buildRequestScopedGsdToolSet(guidedUnit?.unitType === "run-uat" ? aliasFilteredCompatible : providerCompatible, event.requestCustomMessages, guidedUnit?.unitType === "run-uat" ? compatibleRegisteredToolNames : registeredToolNames, guidedUnit?.unitType);
1228
+ const requestRegisteredToolNames = guidedUnit?.unitType === "run-uat"
1229
+ ? compatibleRegisteredToolNames
1230
+ : registeredToolNames;
1231
+ const requestScoped = buildRequestScopedGsdToolSet(guidedUnit?.unitType === "run-uat" ? aliasFilteredCompatible : providerCompatible, event.requestCustomMessages, requestRegisteredToolNames, guidedUnit?.unitType);
1286
1232
  if (requestScoped) {
1233
+ recordAutoToolSurfaceSnapshot({
1234
+ source: "provider-adjustment",
1235
+ unitType: guidedUnit?.unitType,
1236
+ modelFacingToolNames: requestScoped,
1237
+ registeredToolNames: requestRegisteredToolNames,
1238
+ scopedToolNames: requestScoped,
1239
+ });
1287
1240
  return { toolNames: requestScoped };
1288
1241
  }
1289
1242
  const dash = getAutoRuntimeSnapshot();
1290
1243
  if (dash.active && dash.currentUnit) {
1244
+ const registeredForUnit = dash.currentUnit.type === "run-uat"
1245
+ ? compatibleRegisteredToolNames
1246
+ : resolveRegisteredToolNames(pi, event.activeToolNames);
1247
+ const scopedToolNames = buildMinimalAutoGsdToolSet(dash.currentUnit.type === "run-uat" ? aliasFilteredCompatible : providerCompatible, dash.currentUnit.type, registeredForUnit);
1248
+ recordAutoToolSurfaceSnapshot({
1249
+ source: "provider-adjustment",
1250
+ unitType: dash.currentUnit.type,
1251
+ modelFacingToolNames: scopedToolNames,
1252
+ registeredToolNames: registeredForUnit,
1253
+ scopedToolNames,
1254
+ });
1291
1255
  return {
1292
- toolNames: buildMinimalAutoGsdToolSet(dash.currentUnit.type === "run-uat" ? aliasFilteredCompatible : providerCompatible, dash.currentUnit.type, dash.currentUnit.type === "run-uat"
1293
- ? compatibleRegisteredToolNames
1294
- : resolveRegisteredToolNames(pi, event.activeToolNames)),
1256
+ toolNames: scopedToolNames,
1295
1257
  };
1296
1258
  }
1297
1259
  if (isGeneralGsdToolScopingRequested()) {
@@ -3,6 +3,7 @@ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readlinkS
3
3
  import { isAbsolute, join, relative, resolve, sep } from "node:path";
4
4
  import { minimatch } from "minimatch";
5
5
  import { GSD_PHASE_SCOPE_DISPLAY_REASON, shouldBlockAutoUnitToolCall } from "../auto-unit-tool-scope.js";
6
+ import { stripMcpToolPrefix } from "../mcp-tool-name.js";
6
7
  import { getIsolationMode } from "../preferences.js";
7
8
  import { compileSubagentPermissionContract } from "../unit-context-manifest.js";
8
9
  import { logWarning } from "../workflow-logger.js";
@@ -102,10 +103,7 @@ const GATE_SAFE_TOOLS = new Set([
102
103
  "ask_user_questions",
103
104
  ]);
104
105
  export function canonicalToolName(toolName) {
105
- if (!toolName.startsWith("mcp__"))
106
- return toolName;
107
- const toolSeparator = toolName.indexOf("__", "mcp__".length);
108
- return toolSeparator >= 0 ? toolName.slice(toolSeparator + 2) : toolName;
106
+ return stripMcpToolPrefix(toolName);
109
107
  }
110
108
  /**
111
109
  * Persistence is ON by default (opt-out).
@@ -385,6 +383,67 @@ export function isDepthConfirmationAnswer(selected, options) {
385
383
  // Returning false prevents any free-form string from unlocking the gate.
386
384
  return false;
387
385
  }
386
+ function findGateQuestion(questions, gateId) {
387
+ return questions.find((question) => question?.id === gateId);
388
+ }
389
+ function readSelectedGateAnswer(details, questionId) {
390
+ return details.response?.answers?.[questionId]?.selected;
391
+ }
392
+ function verifyAnsweredGate(basePath, question, fallbackMilestoneId) {
393
+ const gateId = typeof question.id === "string" ? question.id : "";
394
+ const milestoneId = extractDepthVerificationMilestoneId(gateId) ?? fallbackMilestoneId ?? null;
395
+ markApprovalGateVerified(gateId, basePath);
396
+ markDepthVerified(milestoneId, basePath);
397
+ clearPendingGate(basePath);
398
+ return { status: "verified", gateId, milestoneId };
399
+ }
400
+ export function applyAskUserQuestionsGateResult(options) {
401
+ const { basePath, questions, details, fallbackMilestoneId } = options;
402
+ const currentPendingGate = getPendingGate(basePath);
403
+ if (currentPendingGate) {
404
+ if (details.cancelled || !details.response) {
405
+ return {
406
+ status: "waiting",
407
+ pendingGateId: currentPendingGate,
408
+ interrupted: details.interrupted === true,
409
+ };
410
+ }
411
+ const pendingQuestion = findGateQuestion(questions, currentPendingGate);
412
+ if (pendingQuestion) {
413
+ const selected = readSelectedGateAnswer(details, currentPendingGate);
414
+ if (isDepthConfirmationAnswer(selected, pendingQuestion.options)) {
415
+ return verifyAnsweredGate(basePath, pendingQuestion, fallbackMilestoneId);
416
+ }
417
+ return { status: "answered", gateId: currentPendingGate };
418
+ }
419
+ }
420
+ if (details.cancelled || !details.response)
421
+ return { status: "not-gate" };
422
+ for (const question of questions) {
423
+ if (typeof question.id !== "string" || !isGateQuestionId(question.id))
424
+ continue;
425
+ const selected = readSelectedGateAnswer(details, question.id);
426
+ if (!isDepthConfirmationAnswer(selected, question.options)) {
427
+ return { status: "answered", gateId: question.id };
428
+ }
429
+ if (currentPendingGate && question.id !== currentPendingGate) {
430
+ return { status: "answered", gateId: currentPendingGate };
431
+ }
432
+ return verifyAnsweredGate(basePath, question, fallbackMilestoneId);
433
+ }
434
+ return { status: "not-gate" };
435
+ }
436
+ export function formatPendingAskUserQuestionsGateMessage(pendingGateId, interrupted) {
437
+ return [
438
+ `Waiting for depth confirmation on gate "${pendingGateId}".`,
439
+ interrupted
440
+ ? "The confirmation question was interrupted before a response was recorded."
441
+ : "No user response was received for the confirmation question.",
442
+ "Do not infer approval from earlier or prior messages.",
443
+ "Do not proceed, write files, save artifacts, or call other tools.",
444
+ `Re-call ask_user_questions with the same gate question id ("${pendingGateId}") and wait for the user's response.`,
445
+ ].join(" ");
446
+ }
388
447
  export function shouldBlockContextWrite(toolName, inputPath, milestoneId, _queuePhaseActive, basePath = process.cwd()) {
389
448
  if (toolName !== "write")
390
449
  return { block: false };
@@ -1,7 +1,10 @@
1
1
  // Project/App: gsd-pi
2
2
  // File Purpose: Shared DB-backed guard for milestone closeout finalization.
3
- import { getDbPath, getLatestAssessmentByScope, getMilestone, getMilestoneSlices, getPendingGates, getSliceTasks, isDbAvailable, refreshOpenDatabaseFromDisk, } from "./gsd-db.js";
3
+ import { dirname } from "node:path";
4
+ import { getLatestAssessmentByScope, getMilestone, getMilestoneSlices, getPendingGates, getSliceTasks, isDbAvailable, } from "./gsd-db.js";
5
+ import { getWorkflowDatabasePath, refreshWorkflowDatabaseFromDisk, } from "./db-workspace.js";
4
6
  import { isClosedStatus } from "./status-guards.js";
7
+ import { closeQualityGatesFromEvidence } from "./quality-gate-closure.js";
5
8
  export const CLOSEOUT_CONSISTENCY_BLOCKED_REASON = "closeout-consistency-blocked";
6
9
  function blocked(reason, message) {
7
10
  return {
@@ -14,22 +17,30 @@ function blocked(reason, message) {
14
17
  function isFileBackedDbPath(path) {
15
18
  return Boolean(path && path !== ":memory:");
16
19
  }
20
+ function artifactBasePathFromDb() {
21
+ const dbPath = getWorkflowDatabasePath();
22
+ if (!isFileBackedDbPath(dbPath))
23
+ return undefined;
24
+ return dirname(dirname(dbPath));
25
+ }
17
26
  export function checkCloseoutConsistencyGate(milestoneId, options = {}) {
18
27
  if (!isDbAvailable()) {
19
28
  return blocked("db-unavailable", `Closeout consistency blocked for ${milestoneId}: canonical DB is unavailable.`);
20
29
  }
21
- if (options.refreshFromDisk && isFileBackedDbPath(getDbPath()) && !refreshOpenDatabaseFromDisk()) {
30
+ if (options.refreshFromDisk && isFileBackedDbPath(getWorkflowDatabasePath()) && !refreshWorkflowDatabaseFromDisk()) {
22
31
  return blocked("db-refresh-failed", `Closeout consistency blocked for ${milestoneId}: canonical DB refresh failed.`);
23
32
  }
24
33
  const milestone = getMilestone(milestoneId);
25
34
  if (!milestone) {
26
35
  return blocked("milestone-missing", `Closeout consistency blocked for ${milestoneId}: milestone is missing from canonical DB.`);
27
36
  }
28
- if (!isClosedStatus(milestone.status)) {
37
+ if (!isClosedStatus(milestone.status) && !options.allowOpenMilestone) {
29
38
  return blocked("milestone-open", `Closeout consistency blocked for ${milestoneId}: canonical DB milestone status is "${milestone.status}".`);
30
39
  }
40
+ const validation = milestone.status === "skipped"
41
+ ? null
42
+ : getLatestAssessmentByScope(milestoneId, "milestone-validation");
31
43
  if (milestone.status !== "skipped") {
32
- const validation = getLatestAssessmentByScope(milestoneId, "milestone-validation");
33
44
  if (validation?.status !== "pass") {
34
45
  return blocked("validation-not-pass", `Closeout consistency blocked for ${milestoneId}: latest milestone validation is "${validation?.status ?? "absent"}".`);
35
46
  }
@@ -38,6 +49,12 @@ export function checkCloseoutConsistencyGate(milestoneId, options = {}) {
38
49
  if (slices.length === 0 && milestone.status !== "skipped") {
39
50
  return blocked("slice-missing", `Closeout consistency blocked for ${milestoneId}: no slices exist in canonical DB.`);
40
51
  }
52
+ if (milestone.status !== "skipped") {
53
+ closeQualityGatesFromEvidence(milestoneId, {
54
+ artifactBasePath: options.artifactBasePath ?? artifactBasePathFromDb(),
55
+ milestoneValidationPassed: validation?.status === "pass",
56
+ });
57
+ }
41
58
  for (const slice of slices) {
42
59
  if (!isClosedStatus(slice.status)) {
43
60
  return blocked("slice-open", `Closeout consistency blocked for ${milestoneId}: slice ${slice.id} status is "${slice.status}".`);
@@ -330,15 +330,19 @@ export function ensureCodebaseMapFresh(basePath, options, ensureOptions) {
330
330
  const ttlMs = ensureOptions?.ttlMs ?? DEFAULT_REFRESH_TTL_MS;
331
331
  const force = ensureOptions?.force === true;
332
332
  const now = Date.now();
333
+ // Enumerate files and compute fingerprint before the TTL check so that
334
+ // file changes are always detected, even within the TTL window.
335
+ const existing = readCodebaseMap(basePath);
336
+ const listed = enumerateFiles(basePath, resolved.excludes, resolved.maxFiles);
337
+ const fingerprint = computeCodebaseFingerprint(listed.files, resolved, listed.truncated);
338
+ // TTL short-circuit: only bypass regeneration when the fingerprint matches,
339
+ // confirming that no tracked files changed since the last check.
333
340
  if (!force && ttlMs > 0) {
334
341
  const cached = freshnessCache.get(cacheKey);
335
- if (cached && now - cached.checkedAt < ttlMs) {
342
+ if (cached && now - cached.checkedAt < ttlMs && cached.result.fingerprint === fingerprint) {
336
343
  return cached.result;
337
344
  }
338
345
  }
339
- const existing = readCodebaseMap(basePath);
340
- const listed = enumerateFiles(basePath, resolved.excludes, resolved.maxFiles);
341
- const fingerprint = computeCodebaseFingerprint(listed.files, resolved, listed.truncated);
342
346
  const cacheAndReturn = (result) => {
343
347
  freshnessCache.set(cacheKey, { checkedAt: now, result });
344
348
  return result;
@@ -3,6 +3,7 @@ import { resolve } from "node:path";
3
3
  import { enableDebug } from "../../debug-logger.js";
4
4
  import { isAutoActive, isAutoPaused, pauseAuto, startAutoDetached, stopAuto, stopAutoRemote } from "../../auto.js";
5
5
  import { handleRate } from "../../commands-rate.js";
6
+ import { notifyPreferenceDiagnostics } from "../../preferences-diagnostics.js";
6
7
  import { setSessionModelOverride } from "../../session-model-override.js";
7
8
  import { guardRemoteSession, projectRoot } from "../context.js";
8
9
  import { findMilestoneIds } from "../../milestone-id-utils.js";
@@ -82,6 +83,7 @@ export async function handleAutoCommand(trimmed, ctx, pi) {
82
83
  const basePath = projectRoot();
83
84
  if (await hasUnresolvedCloseoutBlocker(ctx, basePath))
84
85
  return true;
86
+ notifyPreferenceDiagnostics(ctx, basePath, { surface: "auto-preflight" });
85
87
  // Validate the milestone target exists and is not already complete.
86
88
  if (milestoneId) {
87
89
  const allIds = findMilestoneIds(basePath);
@@ -109,6 +111,7 @@ export async function handleAutoCommand(trimmed, ctx, pi) {
109
111
  const basePath = projectRoot();
110
112
  if (await hasUnresolvedCloseoutBlocker(ctx, basePath))
111
113
  return true;
114
+ notifyPreferenceDiagnostics(ctx, basePath, { surface: "auto-preflight" });
112
115
  // Validate the milestone target exists and is not already complete.
113
116
  if (milestoneId) {
114
117
  const allIds = findMilestoneIds(basePath);
@@ -19,6 +19,7 @@ import { isAutoActive, checkRemoteAutoSession } from "./auto.js";
19
19
  import { getAutoWorktreePath } from "./auto-worktree.js";
20
20
  import { currentDirectoryRoot, projectRoot } from "./commands/context.js";
21
21
  import { loadPrompt } from "./prompt-loader.js";
22
+ import { buildClaudeRuntimeFloorAdvisory } from "../../shared/claude-runtime-floor.js";
22
23
  import { isPnpmInstall } from "../../shared/package-manager-detection.js";
23
24
  import { buildDoctorHealIssuePayload, buildDoctorHealSummary, buildWorkflowDispatchContent, } from "./workflow-protocol.js";
24
25
  import { restoreGsdWorkflowTools, scopeGsdWorkflowToolsForDispatch, } from "./bootstrap/register-hooks.js";
@@ -52,6 +53,21 @@ function resolveInstallCommand(pkg) {
52
53
  return `pnpm add -g ${pkg}`;
53
54
  return `npm install -g ${pkg}`;
54
55
  }
56
+ function notifyClaudeRuntimeFloorAdvisory(ctx) {
57
+ let advisory = null;
58
+ try {
59
+ advisory = buildClaudeRuntimeFloorAdvisory({
60
+ agentDir: join(gsdHome(), "agent"),
61
+ cwd: process.cwd(),
62
+ });
63
+ }
64
+ catch {
65
+ return;
66
+ }
67
+ if (advisory) {
68
+ ctx.ui.notify(advisory, "warning");
69
+ }
70
+ }
55
71
  async function fetchLatestVersionForCommand(registryUrl = UPDATE_REGISTRY_URL) {
56
72
  const controller = new AbortController();
57
73
  const timeout = setTimeout(() => controller.abort(), UPDATE_FETCH_TIMEOUT_MS);
@@ -458,6 +474,8 @@ export async function handleUpdate(ctx, args = "") {
458
474
  }
459
475
  if (current && compareSemverLocal(latest, current) <= 0) {
460
476
  ctx.ui.notify(`Already up to date (${formatCommandVersion(current)}).`, "info");
477
+ if (!browserUpdate)
478
+ notifyClaudeRuntimeFloorAdvisory(ctx);
461
479
  return;
462
480
  }
463
481
  ctx.ui.notify(`Updating: ${formatCommandVersion(current)} → v${latest}...`, "info");
@@ -472,6 +490,8 @@ export async function handleUpdate(ctx, args = "") {
472
490
  ? `Updated gsd-browser to v${latest}. Restart your GSD session to use the new browser automation version.` +
473
491
  (pathReady ? "" : "\nNote: Ensure the npm global bin directory is on your PATH so MCP automation uses the updated binary.")
474
492
  : `Updated to v${latest}. Restart your GSD session to use the new version.`, "info");
493
+ if (!browserUpdate)
494
+ notifyClaudeRuntimeFloorAdvisory(ctx);
475
495
  }
476
496
  catch {
477
497
  ctx.ui.notify(`Update failed. Try manually: ${installCmd}`, "error");
@@ -3,9 +3,7 @@
3
3
  *
4
4
  * Contains: InspectData type, formatInspectOutput, handleInspect
5
5
  */
6
- import { existsSync } from "node:fs";
7
- import { join } from "node:path";
8
- import { gsdRoot } from "./paths.js";
6
+ import { isWorkflowDatabaseOpen, openExistingWorkflowDatabase, } from "./db-workspace.js";
9
7
  import { logWarning } from "./workflow-logger.js";
10
8
  import { getErrorMessage } from "./error-utils.js";
11
9
  export function formatInspectOutput(data) {
@@ -34,11 +32,9 @@ export function formatInspectOutput(data) {
34
32
  }
35
33
  export async function handleInspect(ctx) {
36
34
  try {
37
- const { isDbAvailable, _getAdapter, openDatabase } = await import("./gsd-db.js");
38
- if (!isDbAvailable()) {
39
- const gsdDir = gsdRoot(process.cwd());
40
- const dbPath = join(gsdDir, "gsd.db");
41
- if (!existsSync(gsdDir) || !existsSync(dbPath) || !openDatabase(dbPath)) {
35
+ const { _getAdapter } = await import("./gsd-db.js");
36
+ if (!isWorkflowDatabaseOpen()) {
37
+ if (!openExistingWorkflowDatabase(process.cwd()).ok) {
42
38
  ctx.ui.notify("No GSD database available. Run /gsd auto to create one.", "info");
43
39
  return;
44
40
  }