@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.74e8dd1

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 (232) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +167 -16
  3. package/dist/resources/extensions/gsd/auto/phases.js +4 -3
  4. package/dist/resources/extensions/gsd/auto-dashboard.js +15 -4
  5. package/dist/resources/extensions/gsd/auto-dispatch.js +39 -0
  6. package/dist/resources/extensions/gsd/auto-post-unit.js +113 -7
  7. package/dist/resources/extensions/gsd/auto-prompts.js +9 -0
  8. package/dist/resources/extensions/gsd/auto-recovery.js +4 -4
  9. package/dist/resources/extensions/gsd/auto-start.js +94 -15
  10. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +2 -1
  11. package/dist/resources/extensions/gsd/auto.js +22 -4
  12. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +79 -0
  13. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
  14. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +30 -9
  15. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -10
  16. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  17. package/dist/resources/extensions/gsd/commands/handlers/core.js +6 -2
  18. package/dist/resources/extensions/gsd/commands/handlers/ops.js +7 -3
  19. package/dist/resources/extensions/gsd/commands-maintenance.js +172 -2
  20. package/dist/resources/extensions/gsd/commands-mcp-status.js +107 -59
  21. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
  22. package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
  23. package/dist/resources/extensions/gsd/config-overlay.js +2 -1
  24. package/dist/resources/extensions/gsd/error-classifier.js +2 -1
  25. package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
  26. package/dist/resources/extensions/gsd/gsd-db.js +37 -4
  27. package/dist/resources/extensions/gsd/guided-flow.js +1 -1
  28. package/dist/resources/extensions/gsd/mcp-filter.js +3 -0
  29. package/dist/resources/extensions/gsd/mcp-project-config.js +67 -8
  30. package/dist/resources/extensions/gsd/migration-auto-check.js +2 -2
  31. package/dist/resources/extensions/gsd/prompts/run-uat.md +10 -4
  32. package/dist/resources/extensions/gsd/prompts/system.md +3 -1
  33. package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
  34. package/dist/resources/extensions/gsd/skill-activation.js +20 -3
  35. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +4 -2
  36. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +1 -1
  37. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
  38. package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
  39. package/dist/resources/extensions/gsd/state.js +15 -12
  40. package/dist/resources/extensions/gsd/tool-presentation-plan.js +120 -0
  41. package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
  42. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -9
  43. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  44. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +366 -3
  45. package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
  46. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  47. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -1
  48. package/dist/resources/extensions/gsd/workflow-mcp.js +5 -1
  49. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -0
  50. package/dist/resources/extensions/mcp-client/manager.js +31 -1
  51. package/dist/web/standalone/.next/BUILD_ID +1 -1
  52. package/dist/web/standalone/.next/app-path-routes-manifest.json +4 -4
  53. package/dist/web/standalone/.next/build-manifest.json +2 -2
  54. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  55. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  56. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  64. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/index.html +1 -1
  72. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app-paths-manifest.json +4 -4
  79. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  80. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  82. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  83. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  84. package/package.json +2 -2
  85. package/packages/cloud-mcp-gateway/package.json +2 -2
  86. package/packages/contracts/dist/workflow.d.ts +14 -0
  87. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  88. package/packages/contracts/dist/workflow.js +16 -0
  89. package/packages/contracts/dist/workflow.js.map +1 -1
  90. package/packages/contracts/package.json +1 -1
  91. package/packages/daemon/package.json +4 -4
  92. package/packages/gsd-agent-core/package.json +5 -5
  93. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  94. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  95. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  96. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  97. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
  98. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  99. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +72 -31
  100. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  101. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.d.ts.map +1 -1
  102. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -0
  103. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  104. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
  105. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  106. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
  107. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  108. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  109. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
  110. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  111. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  112. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
  113. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  114. package/packages/gsd-agent-modes/package.json +7 -7
  115. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  116. package/packages/mcp-server/dist/workflow-tools.js +82 -0
  117. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  118. package/packages/mcp-server/package.json +3 -3
  119. package/packages/native/package.json +1 -1
  120. package/packages/pi-agent-core/package.json +1 -1
  121. package/packages/pi-ai/dist/image-models.generated.d.ts +15 -0
  122. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  123. package/packages/pi-ai/dist/image-models.generated.js +15 -0
  124. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  125. package/packages/pi-ai/dist/models.generated.d.ts +338 -17
  126. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  127. package/packages/pi-ai/dist/models.generated.js +412 -112
  128. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  129. package/packages/pi-ai/package.json +1 -1
  130. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  131. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  132. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  133. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  134. package/packages/pi-coding-agent/package.json +7 -7
  135. package/packages/pi-tui/dist/terminal.d.ts +1 -0
  136. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  137. package/packages/pi-tui/dist/terminal.js +8 -4
  138. package/packages/pi-tui/dist/terminal.js.map +1 -1
  139. package/packages/pi-tui/package.json +1 -1
  140. package/packages/rpc-client/package.json +2 -2
  141. package/pkg/package.json +1 -1
  142. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +196 -16
  143. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +239 -63
  144. package/src/resources/extensions/gsd/auto/phases.ts +5 -3
  145. package/src/resources/extensions/gsd/auto-dashboard.ts +16 -4
  146. package/src/resources/extensions/gsd/auto-dispatch.ts +48 -0
  147. package/src/resources/extensions/gsd/auto-post-unit.ts +138 -7
  148. package/src/resources/extensions/gsd/auto-prompts.ts +9 -0
  149. package/src/resources/extensions/gsd/auto-recovery.ts +4 -4
  150. package/src/resources/extensions/gsd/auto-start.ts +112 -17
  151. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +2 -1
  152. package/src/resources/extensions/gsd/auto.ts +35 -3
  153. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +86 -0
  154. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
  155. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +51 -14
  156. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +21 -10
  157. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  158. package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -2
  159. package/src/resources/extensions/gsd/commands/handlers/ops.ts +7 -3
  160. package/src/resources/extensions/gsd/commands-maintenance.ts +197 -2
  161. package/src/resources/extensions/gsd/commands-mcp-status.ts +134 -57
  162. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
  163. package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
  164. package/src/resources/extensions/gsd/config-overlay.ts +3 -1
  165. package/src/resources/extensions/gsd/error-classifier.ts +2 -1
  166. package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
  167. package/src/resources/extensions/gsd/gsd-db.ts +41 -6
  168. package/src/resources/extensions/gsd/guided-flow.ts +1 -1
  169. package/src/resources/extensions/gsd/mcp-filter.ts +3 -0
  170. package/src/resources/extensions/gsd/mcp-project-config.ts +92 -10
  171. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  172. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  173. package/src/resources/extensions/gsd/prompts/run-uat.md +10 -4
  174. package/src/resources/extensions/gsd/prompts/system.md +3 -1
  175. package/src/resources/extensions/gsd/safety/destructive-guard.ts +3 -0
  176. package/src/resources/extensions/gsd/skill-activation.ts +20 -2
  177. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +4 -2
  178. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +1 -1
  179. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
  180. package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
  181. package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
  182. package/src/resources/extensions/gsd/state.ts +16 -12
  183. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +51 -0
  184. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +86 -0
  185. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +143 -2
  186. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +24 -2
  187. package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
  188. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
  189. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
  190. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +50 -13
  191. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +60 -0
  192. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +18 -0
  193. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
  194. package/src/resources/extensions/gsd/tests/gsd-rebuild.test.ts +199 -0
  195. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +75 -0
  196. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +13 -6
  197. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +15 -0
  198. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +68 -0
  199. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +177 -0
  200. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
  201. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
  202. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +39 -1
  203. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -0
  204. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
  205. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
  206. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +35 -0
  207. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
  208. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
  209. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +6 -2
  210. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +52 -0
  211. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
  212. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
  213. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
  214. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
  215. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +21 -0
  216. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +17 -2
  217. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +83 -0
  218. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +25 -0
  219. package/src/resources/extensions/gsd/tool-presentation-plan.ts +167 -0
  220. package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
  221. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -9
  222. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  223. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +440 -2
  224. package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
  225. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  226. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -1
  227. package/src/resources/extensions/gsd/workflow-mcp.ts +5 -1
  228. package/src/resources/extensions/gsd/worktree-lifecycle.ts +26 -0
  229. package/src/resources/extensions/mcp-client/manager.ts +33 -1
  230. package/src/resources/extensions/mcp-client/tests/manager.test.ts +35 -0
  231. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → eRWf-RI9bzbrwEurm_3uI}/_buildManifest.js +0 -0
  232. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → eRWf-RI9bzbrwEurm_3uI}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { setKittyProtocolActive } from \"./keys.js\";\nimport { DISABLE_MOUSE, ENABLE_MOUSE } from \"./mouse.js\";\nimport { StdinBuffer } from \"./stdin-buffer.js\";\n\nconst cjsRequire = createRequire(import.meta.url);\n\nconst TERMINAL_PROGRESS_KEEPALIVE_MS = 1000;\nconst TERMINAL_PROGRESS_ACTIVE_SEQUENCE = \"\\x1b]9;4;3\\x07\";\nconst TERMINAL_PROGRESS_CLEAR_SEQUENCE = \"\\x1b]9;4;0;\\x07\";\n\n/**\n * Minimal terminal interface for TUI\n */\nexport interface Terminal {\n\t// Whether the terminal is interactive\n\treadonly isTTY: boolean;\n\n\t// Start the terminal with input and resize handlers\n\tstart(onInput: (data: string) => void, onResize: () => void): void;\n\n\t// Stop the terminal and restore state\n\tstop(): void;\n\n\t/**\n\t * Drain stdin before exiting to prevent Kitty key release events from\n\t * leaking to the parent shell over slow SSH connections.\n\t * @param maxMs - Maximum time to drain (default: 1000ms)\n\t * @param idleMs - Exit early if no input arrives within this time (default: 50ms)\n\t */\n\tdrainInput(maxMs?: number, idleMs?: number): Promise<void>;\n\n\t// Write output to terminal\n\twrite(data: string): void;\n\n\t// Get terminal dimensions\n\tget columns(): number;\n\tget rows(): number;\n\n\t// Whether Kitty keyboard protocol is active\n\tget kittyProtocolActive(): boolean;\n\n\t// Cursor positioning (relative to current position)\n\tmoveBy(lines: number): void; // Move cursor up (negative) or down (positive) by N lines\n\n\t// Cursor visibility\n\thideCursor(): void; // Hide the cursor\n\tshowCursor(): void; // Show the cursor\n\n\t// Clear operations\n\tclearLine(): void; // Clear current line\n\tclearFromCursor(): void; // Clear from cursor to end of screen\n\tclearScreen(): void; // Clear entire screen and move cursor to (0,0)\n\n\t// Title operations\n\tsetTitle(title: string): void; // Set terminal window title\n\n\t// Progress indicator (OSC 9;4)\n\tsetProgress(active: boolean): void;\n}\n\n/**\n * Real terminal using process.stdin/stdout\n */\nexport class ProcessTerminal implements Terminal {\n\tprivate wasRaw = false;\n\tprivate inputHandler?: (data: string) => void;\n\tprivate resizeHandler?: () => void;\n\tprivate _kittyProtocolActive = false;\n\tprivate _modifyOtherKeysActive = false;\n\tprivate _mouseActive = false;\n\tprivate stdinBuffer?: StdinBuffer;\n\tprivate stdinDataHandler?: (data: string) => void;\n\tprivate progressInterval?: ReturnType<typeof setInterval>;\n\tprivate writeLogPath = (() => {\n\t\tconst env = process.env.PI_TUI_WRITE_LOG || \"\";\n\t\tif (!env) return \"\";\n\t\ttry {\n\t\t\tif (fs.statSync(env).isDirectory()) {\n\t\t\t\tconst now = new Date();\n\t\t\t\tconst ts = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}-${String(now.getDate()).padStart(2, \"0\")}_${String(now.getHours()).padStart(2, \"0\")}-${String(now.getMinutes()).padStart(2, \"0\")}-${String(now.getSeconds()).padStart(2, \"0\")}`;\n\t\t\t\treturn path.join(env, `tui-${ts}-${process.pid}.log`);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not an existing directory - use as-is (file path)\n\t\t}\n\t\treturn env;\n\t})();\n\n\tget kittyProtocolActive(): boolean {\n\t\treturn this._kittyProtocolActive;\n\t}\n\n\tget isTTY(): boolean {\n\t\treturn Boolean(process.stdout.isTTY);\n\t}\n\n\tstart(onInput: (data: string) => void, onResize: () => void): void {\n\t\t// Idempotency guard: if start() is called again without an intervening\n\t\t// stop() (e.g. a mis-paired suspend/resume cycle), detach any stale\n\t\t// listeners first so they don't accumulate on the long-lived\n\t\t// process.stdin/stdout and trip MaxListenersExceededWarning. No-op on a\n\t\t// fresh start since all handles are undefined.\n\t\tif (this.stdinDataHandler) {\n\t\t\tprocess.stdin.removeListener(\"data\", this.stdinDataHandler);\n\t\t\tthis.stdinDataHandler = undefined;\n\t\t}\n\t\tif (this.resizeHandler) {\n\t\t\tprocess.stdout.removeListener(\"resize\", this.resizeHandler);\n\t\t\tthis.resizeHandler = undefined;\n\t\t}\n\t\tif (this.stdinBuffer) {\n\t\t\tthis.stdinBuffer.destroy();\n\t\t\tthis.stdinBuffer = undefined;\n\t\t}\n\n\t\tif (!this.isTTY) {\n\t\t\tthis.inputHandler = onInput;\n\t\t\tthis.resizeHandler = onResize;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.inputHandler = onInput;\n\t\tthis.resizeHandler = onResize;\n\n\t\t// Save previous state and enable raw mode\n\t\tthis.wasRaw = process.stdin.isRaw || false;\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t}\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\tprocess.stdin.resume();\n\n\t\t// Enable bracketed paste mode - terminal will wrap pastes in \\x1b[200~ ... \\x1b[201~\n\t\tprocess.stdout.write(\"\\x1b[?2004h\");\n\n\t\t// Enable mouse reporting so clicks and the wheel reach the TUI. On by\n\t\t// default; set PI_TUI_MOUSE=0 to opt out (preserves native click-drag\n\t\t// text selection without holding Shift).\n\t\tif (process.env.PI_TUI_MOUSE !== \"0\") {\n\t\t\tprocess.stdout.write(ENABLE_MOUSE);\n\t\t\tthis._mouseActive = true;\n\t\t}\n\n\t\t// Set up resize handler immediately\n\t\tprocess.stdout.on(\"resize\", this.resizeHandler);\n\n\t\t// Refresh terminal dimensions - they may be stale after suspend/resume\n\t\t// (SIGWINCH is lost while process is stopped). Unix only.\n\t\tif (process.platform !== \"win32\") {\n\t\t\tprocess.kill(process.pid, \"SIGWINCH\");\n\t\t}\n\n\t\t// On Windows, enable ENABLE_VIRTUAL_TERMINAL_INPUT so the console sends\n\t\t// VT escape sequences (e.g. \\x1b[Z for Shift+Tab) instead of raw console\n\t\t// events that lose modifier information. Must run AFTER setRawMode(true)\n\t\t// since that resets console mode flags.\n\t\tthis.enableWindowsVTInput();\n\n\t\t// Query and enable Kitty keyboard protocol\n\t\t// The query handler intercepts input temporarily, then installs the user's handler\n\t\t// See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n\t\tthis.queryAndEnableKittyProtocol();\n\t}\n\n\t/**\n\t * Set up StdinBuffer to split batched input into individual sequences.\n\t * This ensures components receive single events, making matchesKey/isKeyRelease work correctly.\n\t *\n\t * Also watches for Kitty protocol response and enables it when detected.\n\t * This is done here (after stdinBuffer parsing) rather than on raw stdin\n\t * to handle the case where the response arrives split across multiple events.\n\t */\n\tprivate setupStdinBuffer(): void {\n\t\tthis.stdinBuffer = new StdinBuffer({ timeout: 10 });\n\n\t\t// Kitty protocol response pattern: \\x1b[?<flags>u\n\t\tconst kittyResponsePattern = /^\\x1b\\[\\?(\\d+)u$/;\n\n\t\t// Forward individual sequences to the input handler\n\t\tthis.stdinBuffer.on(\"data\", (sequence) => {\n\t\t\t// Check for Kitty protocol response (only if not already enabled)\n\t\t\tif (!this._kittyProtocolActive) {\n\t\t\t\tconst match = sequence.match(kittyResponsePattern);\n\t\t\t\tif (match) {\n\t\t\t\t\tthis._kittyProtocolActive = true;\n\t\t\t\t\tsetKittyProtocolActive(true);\n\n\t\t\t\t\t// Enable Kitty keyboard protocol (push flags)\n\t\t\t\t\t// Flag 1 = disambiguate escape codes\n\t\t\t\t\t// Flag 2 = report event types (press/repeat/release)\n\t\t\t\t\t// Flag 4 = report alternate keys (shifted key, base layout key)\n\t\t\t\t\t// Base layout key enables shortcuts to work with non-Latin keyboard layouts\n\t\t\t\t\tprocess.stdout.write(\"\\x1b[>7u\");\n\t\t\t\t\treturn; // Don't forward protocol response to TUI\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.inputHandler) {\n\t\t\t\tthis.inputHandler(sequence);\n\t\t\t}\n\t\t});\n\n\t\t// Re-wrap paste content with bracketed paste markers for existing editor handling\n\t\tthis.stdinBuffer.on(\"paste\", (content) => {\n\t\t\tif (this.inputHandler) {\n\t\t\t\tthis.inputHandler(`\\x1b[200~${content}\\x1b[201~`);\n\t\t\t}\n\t\t});\n\n\t\t// Handler that pipes stdin data through the buffer\n\t\tthis.stdinDataHandler = (data: string) => {\n\t\t\tthis.stdinBuffer!.process(data);\n\t\t};\n\t}\n\n\t/**\n\t * Query terminal for Kitty keyboard protocol support and enable if available.\n\t *\n\t * Sends CSI ? u to query current flags. If terminal responds with CSI ? <flags> u,\n\t * it supports the protocol and we enable it with CSI > 1 u.\n\t *\n\t * If no Kitty response arrives shortly after startup, fall back to enabling\n\t * xterm modifyOtherKeys mode 2. This is needed for tmux, which can forward\n\t * modified enter keys as CSI-u when extended-keys is enabled, but may not\n\t * answer the Kitty protocol query.\n\t *\n\t * The response is detected in setupStdinBuffer's data handler, which properly\n\t * handles the case where the response arrives split across multiple stdin events.\n\t */\n\tprivate queryAndEnableKittyProtocol(): void {\n\t\tthis.setupStdinBuffer();\n\t\tprocess.stdin.on(\"data\", this.stdinDataHandler!);\n\t\tprocess.stdout.write(\"\\x1b[?u\");\n\t\tsetTimeout(() => {\n\t\t\tif (!this._kittyProtocolActive && !this._modifyOtherKeysActive) {\n\t\t\t\tprocess.stdout.write(\"\\x1b[>4;2m\");\n\t\t\t\tthis._modifyOtherKeysActive = true;\n\t\t\t}\n\t\t}, 150);\n\t}\n\n\t/**\n\t * On Windows, add ENABLE_VIRTUAL_TERMINAL_INPUT (0x0200) to the stdin\n\t * console handle so the terminal sends VT sequences for modified keys\n\t * (e.g. \\x1b[Z for Shift+Tab). Without this, libuv's ReadConsoleInputW\n\t * discards modifier state and Shift+Tab arrives as plain \\t.\n\t */\n\tprivate enableWindowsVTInput(): void {\n\t\tif (process.platform !== \"win32\") return;\n\t\ttry {\n\t\t\tconst arch = process.arch;\n\t\t\tif (arch !== \"x64\" && arch !== \"arm64\") return;\n\n\t\t\t// Dynamic require so non-Windows and bundled/browser paths never load the\n\t\t\t// native helper. In the npm package native/ is next to dist/; in compiled\n\t\t\t// binary archives native/ is copied next to the executable.\n\t\t\tconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\n\t\t\tconst nativePath = path.join(\"native\", \"win32\", \"prebuilds\", `win32-${arch}`, \"win32-console-mode.node\");\n\t\t\tconst candidates = [\n\t\t\t\tpath.join(moduleDir, \"..\", nativePath),\n\t\t\t\tpath.join(moduleDir, nativePath),\n\t\t\t\tpath.join(path.dirname(process.execPath), nativePath),\n\t\t\t];\n\t\t\tfor (const modulePath of candidates) {\n\t\t\t\ttry {\n\t\t\t\t\tconst helper = cjsRequire(modulePath) as { enableVirtualTerminalInput?: () => boolean };\n\t\t\t\t\thelper.enableVirtualTerminalInput?.();\n\t\t\t\t\treturn;\n\t\t\t\t} catch {\n\t\t\t\t\t// Try the next possible packaging location.\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Native helper not available — Shift+Tab won't be distinguishable from Tab.\n\t\t}\n\t}\n\n\tasync drainInput(maxMs = 1000, idleMs = 50): Promise<void> {\n\t\tif (this._kittyProtocolActive) {\n\t\t\t// Disable Kitty keyboard protocol first so any late key releases\n\t\t\t// do not generate new Kitty escape sequences.\n\t\t\tprocess.stdout.write(\"\\x1b[<u\");\n\t\t\tthis._kittyProtocolActive = false;\n\t\t\tsetKittyProtocolActive(false);\n\t\t}\n\t\tif (this._modifyOtherKeysActive) {\n\t\t\tprocess.stdout.write(\"\\x1b[>4;0m\");\n\t\t\tthis._modifyOtherKeysActive = false;\n\t\t}\n\t\tif (this._mouseActive) {\n\t\t\tprocess.stdout.write(DISABLE_MOUSE);\n\t\t\tthis._mouseActive = false;\n\t\t}\n\n\t\tconst previousHandler = this.inputHandler;\n\t\tthis.inputHandler = undefined;\n\n\t\tlet lastDataTime = Date.now();\n\t\tconst onData = () => {\n\t\t\tlastDataTime = Date.now();\n\t\t};\n\n\t\tprocess.stdin.on(\"data\", onData);\n\t\tconst endTime = Date.now() + maxMs;\n\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst timeLeft = endTime - now;\n\t\t\t\tif (timeLeft <= 0) break;\n\t\t\t\tif (now - lastDataTime >= idleMs) break;\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, Math.min(idleMs, timeLeft)));\n\t\t\t}\n\t\t} finally {\n\t\t\tprocess.stdin.removeListener(\"data\", onData);\n\t\t\tthis.inputHandler = previousHandler;\n\t\t}\n\t}\n\n\tstop(): void {\n\t\tif (this.clearProgressInterval()) {\n\t\t\tprocess.stdout.write(TERMINAL_PROGRESS_CLEAR_SEQUENCE);\n\t\t}\n\n\t\t// Disable bracketed paste mode\n\t\tprocess.stdout.write(\"\\x1b[?2004l\");\n\n\t\t// Disable mouse reporting if not already done by drainInput()\n\t\tif (this._mouseActive) {\n\t\t\tprocess.stdout.write(DISABLE_MOUSE);\n\t\t\tthis._mouseActive = false;\n\t\t}\n\n\t\t// Disable Kitty keyboard protocol if not already done by drainInput()\n\t\tif (this._kittyProtocolActive) {\n\t\t\tprocess.stdout.write(\"\\x1b[<u\");\n\t\t\tthis._kittyProtocolActive = false;\n\t\t\tsetKittyProtocolActive(false);\n\t\t}\n\t\tif (this._modifyOtherKeysActive) {\n\t\t\tprocess.stdout.write(\"\\x1b[>4;0m\");\n\t\t\tthis._modifyOtherKeysActive = false;\n\t\t}\n\n\t\t// Clean up StdinBuffer\n\t\tif (this.stdinBuffer) {\n\t\t\tthis.stdinBuffer.destroy();\n\t\t\tthis.stdinBuffer = undefined;\n\t\t}\n\n\t\t// Remove event handlers\n\t\tif (this.stdinDataHandler) {\n\t\t\tprocess.stdin.removeListener(\"data\", this.stdinDataHandler);\n\t\t\tthis.stdinDataHandler = undefined;\n\t\t}\n\t\tthis.inputHandler = undefined;\n\t\tif (this.resizeHandler) {\n\t\t\tprocess.stdout.removeListener(\"resize\", this.resizeHandler);\n\t\t\tthis.resizeHandler = undefined;\n\t\t}\n\n\t\t// Pause stdin to prevent any buffered input (e.g., Ctrl+D) from being\n\t\t// re-interpreted after raw mode is disabled. This fixes a race condition\n\t\t// where Ctrl+D could close the parent shell over SSH.\n\t\tprocess.stdin.pause();\n\n\t\t// Restore raw mode state\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(this.wasRaw);\n\t\t}\n\t}\n\n\twrite(data: string): void {\n\t\tprocess.stdout.write(data);\n\t\tif (this.writeLogPath) {\n\t\t\ttry {\n\t\t\t\tfs.appendFileSync(this.writeLogPath, data, { encoding: \"utf8\" });\n\t\t\t} catch {\n\t\t\t\t// Ignore logging errors\n\t\t\t}\n\t\t}\n\t}\n\n\tget columns(): number {\n\t\treturn process.stdout.columns || Number(process.env.COLUMNS) || 80;\n\t}\n\n\tget rows(): number {\n\t\treturn process.stdout.rows || Number(process.env.LINES) || 24;\n\t}\n\n\tmoveBy(lines: number): void {\n\t\tif (lines > 0) {\n\t\t\t// Move down\n\t\t\tprocess.stdout.write(`\\x1b[${lines}B`);\n\t\t} else if (lines < 0) {\n\t\t\t// Move up\n\t\t\tprocess.stdout.write(`\\x1b[${-lines}A`);\n\t\t}\n\t\t// lines === 0: no movement\n\t}\n\n\thideCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25l\");\n\t}\n\n\tshowCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25h\");\n\t}\n\n\tclearLine(): void {\n\t\tprocess.stdout.write(\"\\x1b[K\");\n\t}\n\n\tclearFromCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[J\");\n\t}\n\n\tclearScreen(): void {\n\t\tprocess.stdout.write(\"\\x1b[2J\\x1b[H\"); // Clear screen and move to home (1,1)\n\t}\n\n\tsetTitle(title: string): void {\n\t\t// OSC 0;title BEL - set terminal window title\n\t\tprocess.stdout.write(`\\x1b]0;${title}\\x07`);\n\t}\n\n\tsetProgress(active: boolean): void {\n\t\tif (active) {\n\t\t\t// OSC 9;4;3 - indeterminate progress\n\t\t\tprocess.stdout.write(TERMINAL_PROGRESS_ACTIVE_SEQUENCE);\n\t\t\tif (!this.progressInterval) {\n\t\t\t\tthis.progressInterval = setInterval(() => {\n\t\t\t\t\tprocess.stdout.write(TERMINAL_PROGRESS_ACTIVE_SEQUENCE);\n\t\t\t\t}, TERMINAL_PROGRESS_KEEPALIVE_MS);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.clearProgressInterval();\n\t\t\t// OSC 9;4;0 - clear progress\n\t\t\tprocess.stdout.write(TERMINAL_PROGRESS_CLEAR_SEQUENCE);\n\t\t}\n\t}\n\n\tprivate clearProgressInterval(): boolean {\n\t\tif (!this.progressInterval) return false;\n\t\tclearInterval(this.progressInterval);\n\t\tthis.progressInterval = undefined;\n\t\treturn true;\n\t}\n}\n"]}
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { setKittyProtocolActive } from \"./keys.js\";\nimport { DISABLE_MOUSE, ENABLE_MOUSE } from \"./mouse.js\";\nimport { StdinBuffer } from \"./stdin-buffer.js\";\n\nconst cjsRequire = createRequire(import.meta.url);\n\nconst TERMINAL_PROGRESS_KEEPALIVE_MS = 1000;\nconst TERMINAL_PROGRESS_ACTIVE_SEQUENCE = \"\\x1b]9;4;3\\x07\";\nconst TERMINAL_PROGRESS_CLEAR_SEQUENCE = \"\\x1b]9;4;0;\\x07\";\n\nexport function shouldEnableMouseReporting(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn env.PI_TUI_MOUSE === \"1\";\n}\n\n/**\n * Minimal terminal interface for TUI\n */\nexport interface Terminal {\n\t// Whether the terminal is interactive\n\treadonly isTTY: boolean;\n\n\t// Start the terminal with input and resize handlers\n\tstart(onInput: (data: string) => void, onResize: () => void): void;\n\n\t// Stop the terminal and restore state\n\tstop(): void;\n\n\t/**\n\t * Drain stdin before exiting to prevent Kitty key release events from\n\t * leaking to the parent shell over slow SSH connections.\n\t * @param maxMs - Maximum time to drain (default: 1000ms)\n\t * @param idleMs - Exit early if no input arrives within this time (default: 50ms)\n\t */\n\tdrainInput(maxMs?: number, idleMs?: number): Promise<void>;\n\n\t// Write output to terminal\n\twrite(data: string): void;\n\n\t// Get terminal dimensions\n\tget columns(): number;\n\tget rows(): number;\n\n\t// Whether Kitty keyboard protocol is active\n\tget kittyProtocolActive(): boolean;\n\n\t// Cursor positioning (relative to current position)\n\tmoveBy(lines: number): void; // Move cursor up (negative) or down (positive) by N lines\n\n\t// Cursor visibility\n\thideCursor(): void; // Hide the cursor\n\tshowCursor(): void; // Show the cursor\n\n\t// Clear operations\n\tclearLine(): void; // Clear current line\n\tclearFromCursor(): void; // Clear from cursor to end of screen\n\tclearScreen(): void; // Clear entire screen and move cursor to (0,0)\n\n\t// Title operations\n\tsetTitle(title: string): void; // Set terminal window title\n\n\t// Progress indicator (OSC 9;4)\n\tsetProgress(active: boolean): void;\n}\n\n/**\n * Real terminal using process.stdin/stdout\n */\nexport class ProcessTerminal implements Terminal {\n\tprivate wasRaw = false;\n\tprivate inputHandler?: (data: string) => void;\n\tprivate resizeHandler?: () => void;\n\tprivate _kittyProtocolActive = false;\n\tprivate _modifyOtherKeysActive = false;\n\tprivate _mouseActive = false;\n\tprivate stdinBuffer?: StdinBuffer;\n\tprivate stdinDataHandler?: (data: string) => void;\n\tprivate progressInterval?: ReturnType<typeof setInterval>;\n\tprivate writeLogPath = (() => {\n\t\tconst env = process.env.PI_TUI_WRITE_LOG || \"\";\n\t\tif (!env) return \"\";\n\t\ttry {\n\t\t\tif (fs.statSync(env).isDirectory()) {\n\t\t\t\tconst now = new Date();\n\t\t\t\tconst ts = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}-${String(now.getDate()).padStart(2, \"0\")}_${String(now.getHours()).padStart(2, \"0\")}-${String(now.getMinutes()).padStart(2, \"0\")}-${String(now.getSeconds()).padStart(2, \"0\")}`;\n\t\t\t\treturn path.join(env, `tui-${ts}-${process.pid}.log`);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not an existing directory - use as-is (file path)\n\t\t}\n\t\treturn env;\n\t})();\n\n\tget kittyProtocolActive(): boolean {\n\t\treturn this._kittyProtocolActive;\n\t}\n\n\tget isTTY(): boolean {\n\t\treturn Boolean(process.stdout.isTTY);\n\t}\n\n\tstart(onInput: (data: string) => void, onResize: () => void): void {\n\t\t// Idempotency guard: if start() is called again without an intervening\n\t\t// stop() (e.g. a mis-paired suspend/resume cycle), detach any stale\n\t\t// listeners first so they don't accumulate on the long-lived\n\t\t// process.stdin/stdout and trip MaxListenersExceededWarning. No-op on a\n\t\t// fresh start since all handles are undefined.\n\t\tif (this.stdinDataHandler) {\n\t\t\tprocess.stdin.removeListener(\"data\", this.stdinDataHandler);\n\t\t\tthis.stdinDataHandler = undefined;\n\t\t}\n\t\tif (this.resizeHandler) {\n\t\t\tprocess.stdout.removeListener(\"resize\", this.resizeHandler);\n\t\t\tthis.resizeHandler = undefined;\n\t\t}\n\t\tif (this.stdinBuffer) {\n\t\t\tthis.stdinBuffer.destroy();\n\t\t\tthis.stdinBuffer = undefined;\n\t\t}\n\n\t\tif (!this.isTTY) {\n\t\t\tthis.inputHandler = onInput;\n\t\t\tthis.resizeHandler = onResize;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.inputHandler = onInput;\n\t\tthis.resizeHandler = onResize;\n\n\t\t// Save previous state and enable raw mode\n\t\tthis.wasRaw = process.stdin.isRaw || false;\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t}\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\tprocess.stdin.resume();\n\n\t\t// Enable bracketed paste mode - terminal will wrap pastes in \\x1b[200~ ... \\x1b[201~\n\t\tprocess.stdout.write(\"\\x1b[?2004h\");\n\n\t\t// Mouse reporting lets clicks and the wheel reach the TUI, but terminal\n\t\t// mouse capture prevents native click-drag text selection in most\n\t\t// emulators. Keep native selection as the default; set PI_TUI_MOUSE=1 to\n\t\t// opt into mouse reporting.\n\t\tif (shouldEnableMouseReporting()) {\n\t\t\tprocess.stdout.write(ENABLE_MOUSE);\n\t\t\tthis._mouseActive = true;\n\t\t}\n\n\t\t// Set up resize handler immediately\n\t\tprocess.stdout.on(\"resize\", this.resizeHandler);\n\n\t\t// Refresh terminal dimensions - they may be stale after suspend/resume\n\t\t// (SIGWINCH is lost while process is stopped). Unix only.\n\t\tif (process.platform !== \"win32\") {\n\t\t\tprocess.kill(process.pid, \"SIGWINCH\");\n\t\t}\n\n\t\t// On Windows, enable ENABLE_VIRTUAL_TERMINAL_INPUT so the console sends\n\t\t// VT escape sequences (e.g. \\x1b[Z for Shift+Tab) instead of raw console\n\t\t// events that lose modifier information. Must run AFTER setRawMode(true)\n\t\t// since that resets console mode flags.\n\t\tthis.enableWindowsVTInput();\n\n\t\t// Query and enable Kitty keyboard protocol\n\t\t// The query handler intercepts input temporarily, then installs the user's handler\n\t\t// See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/\n\t\tthis.queryAndEnableKittyProtocol();\n\t}\n\n\t/**\n\t * Set up StdinBuffer to split batched input into individual sequences.\n\t * This ensures components receive single events, making matchesKey/isKeyRelease work correctly.\n\t *\n\t * Also watches for Kitty protocol response and enables it when detected.\n\t * This is done here (after stdinBuffer parsing) rather than on raw stdin\n\t * to handle the case where the response arrives split across multiple events.\n\t */\n\tprivate setupStdinBuffer(): void {\n\t\tthis.stdinBuffer = new StdinBuffer({ timeout: 10 });\n\n\t\t// Kitty protocol response pattern: \\x1b[?<flags>u\n\t\tconst kittyResponsePattern = /^\\x1b\\[\\?(\\d+)u$/;\n\n\t\t// Forward individual sequences to the input handler\n\t\tthis.stdinBuffer.on(\"data\", (sequence) => {\n\t\t\t// Check for Kitty protocol response (only if not already enabled)\n\t\t\tif (!this._kittyProtocolActive) {\n\t\t\t\tconst match = sequence.match(kittyResponsePattern);\n\t\t\t\tif (match) {\n\t\t\t\t\tthis._kittyProtocolActive = true;\n\t\t\t\t\tsetKittyProtocolActive(true);\n\n\t\t\t\t\t// Enable Kitty keyboard protocol (push flags)\n\t\t\t\t\t// Flag 1 = disambiguate escape codes\n\t\t\t\t\t// Flag 2 = report event types (press/repeat/release)\n\t\t\t\t\t// Flag 4 = report alternate keys (shifted key, base layout key)\n\t\t\t\t\t// Base layout key enables shortcuts to work with non-Latin keyboard layouts\n\t\t\t\t\tprocess.stdout.write(\"\\x1b[>7u\");\n\t\t\t\t\treturn; // Don't forward protocol response to TUI\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.inputHandler) {\n\t\t\t\tthis.inputHandler(sequence);\n\t\t\t}\n\t\t});\n\n\t\t// Re-wrap paste content with bracketed paste markers for existing editor handling\n\t\tthis.stdinBuffer.on(\"paste\", (content) => {\n\t\t\tif (this.inputHandler) {\n\t\t\t\tthis.inputHandler(`\\x1b[200~${content}\\x1b[201~`);\n\t\t\t}\n\t\t});\n\n\t\t// Handler that pipes stdin data through the buffer\n\t\tthis.stdinDataHandler = (data: string) => {\n\t\t\tthis.stdinBuffer!.process(data);\n\t\t};\n\t}\n\n\t/**\n\t * Query terminal for Kitty keyboard protocol support and enable if available.\n\t *\n\t * Sends CSI ? u to query current flags. If terminal responds with CSI ? <flags> u,\n\t * it supports the protocol and we enable it with CSI > 1 u.\n\t *\n\t * If no Kitty response arrives shortly after startup, fall back to enabling\n\t * xterm modifyOtherKeys mode 2. This is needed for tmux, which can forward\n\t * modified enter keys as CSI-u when extended-keys is enabled, but may not\n\t * answer the Kitty protocol query.\n\t *\n\t * The response is detected in setupStdinBuffer's data handler, which properly\n\t * handles the case where the response arrives split across multiple stdin events.\n\t */\n\tprivate queryAndEnableKittyProtocol(): void {\n\t\tthis.setupStdinBuffer();\n\t\tprocess.stdin.on(\"data\", this.stdinDataHandler!);\n\t\tprocess.stdout.write(\"\\x1b[?u\");\n\t\tsetTimeout(() => {\n\t\t\tif (!this._kittyProtocolActive && !this._modifyOtherKeysActive) {\n\t\t\t\tprocess.stdout.write(\"\\x1b[>4;2m\");\n\t\t\t\tthis._modifyOtherKeysActive = true;\n\t\t\t}\n\t\t}, 150);\n\t}\n\n\t/**\n\t * On Windows, add ENABLE_VIRTUAL_TERMINAL_INPUT (0x0200) to the stdin\n\t * console handle so the terminal sends VT sequences for modified keys\n\t * (e.g. \\x1b[Z for Shift+Tab). Without this, libuv's ReadConsoleInputW\n\t * discards modifier state and Shift+Tab arrives as plain \\t.\n\t */\n\tprivate enableWindowsVTInput(): void {\n\t\tif (process.platform !== \"win32\") return;\n\t\ttry {\n\t\t\tconst arch = process.arch;\n\t\t\tif (arch !== \"x64\" && arch !== \"arm64\") return;\n\n\t\t\t// Dynamic require so non-Windows and bundled/browser paths never load the\n\t\t\t// native helper. In the npm package native/ is next to dist/; in compiled\n\t\t\t// binary archives native/ is copied next to the executable.\n\t\t\tconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\n\t\t\tconst nativePath = path.join(\"native\", \"win32\", \"prebuilds\", `win32-${arch}`, \"win32-console-mode.node\");\n\t\t\tconst candidates = [\n\t\t\t\tpath.join(moduleDir, \"..\", nativePath),\n\t\t\t\tpath.join(moduleDir, nativePath),\n\t\t\t\tpath.join(path.dirname(process.execPath), nativePath),\n\t\t\t];\n\t\t\tfor (const modulePath of candidates) {\n\t\t\t\ttry {\n\t\t\t\t\tconst helper = cjsRequire(modulePath) as { enableVirtualTerminalInput?: () => boolean };\n\t\t\t\t\thelper.enableVirtualTerminalInput?.();\n\t\t\t\t\treturn;\n\t\t\t\t} catch {\n\t\t\t\t\t// Try the next possible packaging location.\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Native helper not available — Shift+Tab won't be distinguishable from Tab.\n\t\t}\n\t}\n\n\tasync drainInput(maxMs = 1000, idleMs = 50): Promise<void> {\n\t\tif (this._kittyProtocolActive) {\n\t\t\t// Disable Kitty keyboard protocol first so any late key releases\n\t\t\t// do not generate new Kitty escape sequences.\n\t\t\tprocess.stdout.write(\"\\x1b[<u\");\n\t\t\tthis._kittyProtocolActive = false;\n\t\t\tsetKittyProtocolActive(false);\n\t\t}\n\t\tif (this._modifyOtherKeysActive) {\n\t\t\tprocess.stdout.write(\"\\x1b[>4;0m\");\n\t\t\tthis._modifyOtherKeysActive = false;\n\t\t}\n\t\tif (this._mouseActive) {\n\t\t\tprocess.stdout.write(DISABLE_MOUSE);\n\t\t\tthis._mouseActive = false;\n\t\t}\n\n\t\tconst previousHandler = this.inputHandler;\n\t\tthis.inputHandler = undefined;\n\n\t\tlet lastDataTime = Date.now();\n\t\tconst onData = () => {\n\t\t\tlastDataTime = Date.now();\n\t\t};\n\n\t\tprocess.stdin.on(\"data\", onData);\n\t\tconst endTime = Date.now() + maxMs;\n\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst timeLeft = endTime - now;\n\t\t\t\tif (timeLeft <= 0) break;\n\t\t\t\tif (now - lastDataTime >= idleMs) break;\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, Math.min(idleMs, timeLeft)));\n\t\t\t}\n\t\t} finally {\n\t\t\tprocess.stdin.removeListener(\"data\", onData);\n\t\t\tthis.inputHandler = previousHandler;\n\t\t}\n\t}\n\n\tstop(): void {\n\t\tif (this.clearProgressInterval()) {\n\t\t\tprocess.stdout.write(TERMINAL_PROGRESS_CLEAR_SEQUENCE);\n\t\t}\n\n\t\t// Disable bracketed paste mode\n\t\tprocess.stdout.write(\"\\x1b[?2004l\");\n\n\t\t// Disable mouse reporting if not already done by drainInput()\n\t\tif (this._mouseActive) {\n\t\t\tprocess.stdout.write(DISABLE_MOUSE);\n\t\t\tthis._mouseActive = false;\n\t\t}\n\n\t\t// Disable Kitty keyboard protocol if not already done by drainInput()\n\t\tif (this._kittyProtocolActive) {\n\t\t\tprocess.stdout.write(\"\\x1b[<u\");\n\t\t\tthis._kittyProtocolActive = false;\n\t\t\tsetKittyProtocolActive(false);\n\t\t}\n\t\tif (this._modifyOtherKeysActive) {\n\t\t\tprocess.stdout.write(\"\\x1b[>4;0m\");\n\t\t\tthis._modifyOtherKeysActive = false;\n\t\t}\n\n\t\t// Clean up StdinBuffer\n\t\tif (this.stdinBuffer) {\n\t\t\tthis.stdinBuffer.destroy();\n\t\t\tthis.stdinBuffer = undefined;\n\t\t}\n\n\t\t// Remove event handlers\n\t\tif (this.stdinDataHandler) {\n\t\t\tprocess.stdin.removeListener(\"data\", this.stdinDataHandler);\n\t\t\tthis.stdinDataHandler = undefined;\n\t\t}\n\t\tthis.inputHandler = undefined;\n\t\tif (this.resizeHandler) {\n\t\t\tprocess.stdout.removeListener(\"resize\", this.resizeHandler);\n\t\t\tthis.resizeHandler = undefined;\n\t\t}\n\n\t\t// Pause stdin to prevent any buffered input (e.g., Ctrl+D) from being\n\t\t// re-interpreted after raw mode is disabled. This fixes a race condition\n\t\t// where Ctrl+D could close the parent shell over SSH.\n\t\tprocess.stdin.pause();\n\n\t\t// Restore raw mode state\n\t\tif (process.stdin.setRawMode) {\n\t\t\tprocess.stdin.setRawMode(this.wasRaw);\n\t\t}\n\t}\n\n\twrite(data: string): void {\n\t\tprocess.stdout.write(data);\n\t\tif (this.writeLogPath) {\n\t\t\ttry {\n\t\t\t\tfs.appendFileSync(this.writeLogPath, data, { encoding: \"utf8\" });\n\t\t\t} catch {\n\t\t\t\t// Ignore logging errors\n\t\t\t}\n\t\t}\n\t}\n\n\tget columns(): number {\n\t\treturn process.stdout.columns || Number(process.env.COLUMNS) || 80;\n\t}\n\n\tget rows(): number {\n\t\treturn process.stdout.rows || Number(process.env.LINES) || 24;\n\t}\n\n\tmoveBy(lines: number): void {\n\t\tif (lines > 0) {\n\t\t\t// Move down\n\t\t\tprocess.stdout.write(`\\x1b[${lines}B`);\n\t\t} else if (lines < 0) {\n\t\t\t// Move up\n\t\t\tprocess.stdout.write(`\\x1b[${-lines}A`);\n\t\t}\n\t\t// lines === 0: no movement\n\t}\n\n\thideCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25l\");\n\t}\n\n\tshowCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[?25h\");\n\t}\n\n\tclearLine(): void {\n\t\tprocess.stdout.write(\"\\x1b[K\");\n\t}\n\n\tclearFromCursor(): void {\n\t\tprocess.stdout.write(\"\\x1b[J\");\n\t}\n\n\tclearScreen(): void {\n\t\tprocess.stdout.write(\"\\x1b[2J\\x1b[H\"); // Clear screen and move to home (1,1)\n\t}\n\n\tsetTitle(title: string): void {\n\t\t// OSC 0;title BEL - set terminal window title\n\t\tprocess.stdout.write(`\\x1b]0;${title}\\x07`);\n\t}\n\n\tsetProgress(active: boolean): void {\n\t\tif (active) {\n\t\t\t// OSC 9;4;3 - indeterminate progress\n\t\t\tprocess.stdout.write(TERMINAL_PROGRESS_ACTIVE_SEQUENCE);\n\t\t\tif (!this.progressInterval) {\n\t\t\t\tthis.progressInterval = setInterval(() => {\n\t\t\t\t\tprocess.stdout.write(TERMINAL_PROGRESS_ACTIVE_SEQUENCE);\n\t\t\t\t}, TERMINAL_PROGRESS_KEEPALIVE_MS);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.clearProgressInterval();\n\t\t\t// OSC 9;4;0 - clear progress\n\t\t\tprocess.stdout.write(TERMINAL_PROGRESS_CLEAR_SEQUENCE);\n\t\t}\n\t}\n\n\tprivate clearProgressInterval(): boolean {\n\t\tif (!this.progressInterval) return false;\n\t\tclearInterval(this.progressInterval);\n\t\tthis.progressInterval = undefined;\n\t\treturn true;\n\t}\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/pi-tui",
3
- "version": "1.1.1-dev.616a1a1",
3
+ "version": "1.1.1-dev.74e8dd1",
4
4
  "description": "Terminal UI library (vendored from earendil-works/pi)",
5
5
  "type": "module",
6
6
  "gsd": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengsd/rpc-client",
3
- "version": "1.1.1-dev.616a1a1",
3
+ "version": "1.1.1-dev.74e8dd1",
4
4
  "description": "Standalone RPC client SDK for GSD — zero internal dependencies",
5
5
  "license": "MIT",
6
6
  "gsd": {
@@ -34,7 +34,7 @@
34
34
  "test": "node --test dist/rpc-client.test.js"
35
35
  },
36
36
  "dependencies": {
37
- "@opengsd/contracts": "^1.1.1-dev.616a1a1"
37
+ "@opengsd/contracts": "^1.1.1-dev.74e8dd1"
38
38
  },
39
39
  "engines": {
40
40
  "node": ">=22.0.0"
package/pkg/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glittercowboy/gsd",
3
- "version": "1.1.1-dev.616a1a1",
3
+ "version": "1.1.1-dev.74e8dd1",
4
4
  "piConfig": {
5
5
  "name": "gsd",
6
6
  "configDir": ".gsd"
@@ -27,10 +27,21 @@ import { homedir } from "node:os";
27
27
  import { createRequire } from "node:module";
28
28
  import { dirname, join } from "node:path";
29
29
  import { PartialMessageBuilder, ZERO_USAGE, mapUsage } from "./partial-builder.js";
30
- import { buildWorkflowMcpServers, resolveWorkflowMcpProjectRoot } from "../gsd/workflow-mcp.js";
31
- import { buildProjectGsdMcpServers } from "../gsd/mcp-project-config.js";
30
+ import {
31
+ buildWorkflowMcpServers,
32
+ getRequiredWorkflowToolsForAutoUnit,
33
+ resolveWorkflowMcpProjectRoot,
34
+ } from "../gsd/workflow-mcp.js";
35
+ import { buildProjectGsdMcpServers, ensureProjectWorkflowMcpConfig } from "../gsd/mcp-project-config.js";
32
36
  import { loadProjectGSDPreferences } from "../gsd/preferences.js";
33
- import { discoverBrowserMcpServerName, discoverMcpServerNames, discoverWorkflowMcpServerName, computeMcpDisallowedTools } from "../gsd/mcp-filter.js";
37
+ import {
38
+ discoverBrowserMcpServerName,
39
+ discoverMcpServers,
40
+ discoverMcpServerNames,
41
+ discoverWorkflowMcpServerName,
42
+ computeMcpDisallowedTools,
43
+ } from "../gsd/mcp-filter.js";
44
+ import { RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES, RUN_UAT_FORBIDDEN_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES, resolveToolPresentationPlan } from "../gsd/tool-presentation-plan.js";
34
45
  import { showInterviewRound, type Question, type RoundResult } from "../shared/tui.js";
35
46
  import type {
36
47
  BetaRawMessageStreamEvent,
@@ -324,6 +335,33 @@ function extractMessageText(msg: { role: string; content: unknown }): string {
324
335
  return "";
325
336
  }
326
337
 
338
+ const GSD_PHASE_PATTERNS: Array<[string, RegExp]> = [
339
+ ["run-uat", /\b(?:UNIT:\s*Run UAT|run-uat)\b/i],
340
+ ["complete-milestone", /\b(?:UNIT:\s*Complete Milestone|complete-milestone)\b/i],
341
+ ["validate-milestone", /\b(?:UNIT:\s*Validate Milestone|validate-milestone)\b/i],
342
+ ["reassess-roadmap", /\b(?:UNIT:\s*Reassess Roadmap|reassess-roadmap)\b/i],
343
+ ["complete-slice", /\b(?:UNIT:\s*Complete Slice|complete-slice)\b/i],
344
+ ["replan-slice", /\b(?:UNIT:\s*Replan Slice|replan-slice)\b/i],
345
+ ["plan-slice", /\b(?:UNIT:\s*Plan Slice|plan-slice|gsd_plan_slice)\b/i],
346
+ ["plan-milestone", /\b(?:UNIT:\s*Plan Milestone|plan-milestone|gsd_plan_milestone)\b/i],
347
+ ["execute-task", /\b(?:UNIT:\s*Execute Task|execute-task|execute-task-simple|reactive-execute)\b/i],
348
+ ["gate-evaluate", /\b(?:UNIT:\s*Gate Evaluate|gate-evaluate|gsd_save_gate_result)\b/i],
349
+ ["research-milestone", /\b(?:UNIT:\s*Research Milestone|research-milestone)\b/i],
350
+ ["research-slice", /\b(?:UNIT:\s*Research Slice|research-slice)\b/i],
351
+ ["discuss-milestone", /\b(?:Discuss milestone|discuss-milestone)\b/i],
352
+ ];
353
+
354
+ export function inferGsdPhaseFromContext(context: Context): string | undefined {
355
+ const text = [
356
+ context.systemPrompt ?? "",
357
+ ...context.messages.map((message) => extractMessageText(message)),
358
+ ].join("\n");
359
+ for (const [phase, pattern] of GSD_PHASE_PATTERNS) {
360
+ if (pattern.test(text)) return phase;
361
+ }
362
+ return undefined;
363
+ }
364
+
327
365
  /**
328
366
  * Build a full conversational prompt from GSD's context messages.
329
367
  *
@@ -1462,19 +1500,113 @@ function mapThinkingLevelToAnthropicEffort(level: ThinkingLevel | undefined, mod
1462
1500
  }
1463
1501
  }
1464
1502
 
1465
- function workflowMcpServerNameFromAllowedTools(allowedTools: unknown): string | undefined {
1503
+ function parseAllowedMcpToolName(toolName: string): { server: string; tool: string } | undefined {
1504
+ const match = /^mcp__(.+)__(\*|[^*]+)$/.exec(toolName);
1505
+ return match?.[1] && match[2] ? { server: match[1], tool: match[2] } : undefined;
1506
+ }
1507
+
1508
+ function browserMcpServerNameFromAllowedTools(allowedTools: unknown): string | undefined {
1466
1509
  if (!Array.isArray(allowedTools)) return undefined;
1467
1510
  for (const toolName of allowedTools) {
1468
1511
  if (typeof toolName !== "string") continue;
1469
- const match = /^mcp__(.+)__\*$/.exec(toolName);
1470
- if (match?.[1] && match[1] !== "gsd-browser") return match[1];
1512
+ const parsed = parseAllowedMcpToolName(toolName);
1513
+ if (!parsed) continue;
1514
+ if (parsed.server === "gsd-browser" || parsed.tool.startsWith("browser_")) {
1515
+ return parsed.server;
1516
+ }
1471
1517
  }
1472
1518
  return undefined;
1473
1519
  }
1474
1520
 
1475
- function browserMcpServerNameFromAllowedTools(allowedTools: unknown): string | undefined {
1521
+ function workflowMcpServerNameFromAllowedTools(allowedTools: unknown): string | undefined {
1476
1522
  if (!Array.isArray(allowedTools)) return undefined;
1477
- return allowedTools.includes("mcp__gsd-browser__*") ? "gsd-browser" : undefined;
1523
+ const browserServerName = browserMcpServerNameFromAllowedTools(allowedTools);
1524
+ for (const toolName of allowedTools) {
1525
+ if (typeof toolName !== "string") continue;
1526
+ const parsed = parseAllowedMcpToolName(toolName);
1527
+ if (!parsed || parsed.server === browserServerName || parsed.tool.startsWith("browser_")) continue;
1528
+ return parsed.server;
1529
+ }
1530
+ return undefined;
1531
+ }
1532
+
1533
+ function isRecord(value: unknown): value is Record<string, unknown> {
1534
+ return !!value && typeof value === "object" && !Array.isArray(value);
1535
+ }
1536
+
1537
+ function isStringRecord(value: unknown): value is Record<string, string> {
1538
+ return isRecord(value) && Object.values(value).every((entry) => typeof entry === "string");
1539
+ }
1540
+
1541
+ function cloneSdkMcpServerConfig(config: unknown): Record<string, unknown> | undefined {
1542
+ if (!isRecord(config)) return undefined;
1543
+ const cloned: Record<string, unknown> = {};
1544
+ for (const key of ["type", "command", "cwd", "url"] as const) {
1545
+ if (typeof config[key] === "string") cloned[key] = config[key];
1546
+ }
1547
+ if (Array.isArray(config.args)) {
1548
+ cloned.args = config.args.filter((arg): arg is string => typeof arg === "string");
1549
+ }
1550
+ if (isStringRecord(config.env)) cloned.env = { ...config.env };
1551
+ if (isStringRecord(config.headers)) cloned.headers = { ...config.headers };
1552
+ if (isRecord(config.oauth)) cloned.oauth = { ...config.oauth };
1553
+ return Object.keys(cloned).length > 0 ? cloned : undefined;
1554
+ }
1555
+
1556
+ function resolveProjectMcpServerConfig(
1557
+ projectRoot: string,
1558
+ serverName: string | undefined,
1559
+ fallbackServers?: Record<string, unknown>,
1560
+ ): Record<string, unknown> | undefined {
1561
+ if (!serverName) return undefined;
1562
+ const projectServer = discoverMcpServers(projectRoot).find((server) => server.name === serverName);
1563
+ return cloneSdkMcpServerConfig(projectServer?.config) ?? cloneSdkMcpServerConfig(fallbackServers?.[serverName]);
1564
+ }
1565
+
1566
+ function resolveProjectMcpServerConfigs(
1567
+ projectRoot: string,
1568
+ serverNames: readonly (string | undefined)[],
1569
+ fallbackServers?: Record<string, unknown>,
1570
+ ): Record<string, Record<string, unknown>> | undefined {
1571
+ const resolved: Record<string, Record<string, unknown>> = {};
1572
+ for (const serverName of serverNames) {
1573
+ const serverConfig = resolveProjectMcpServerConfig(projectRoot, serverName, fallbackServers);
1574
+ if (serverName && serverConfig) resolved[serverName] = serverConfig;
1575
+ }
1576
+ return Object.keys(resolved).length > 0 ? resolved : undefined;
1577
+ }
1578
+
1579
+ function resolveExactWorkflowMcpToolsForPhase(
1580
+ gsdPhase: string | undefined,
1581
+ workflowServerName: string | undefined,
1582
+ workflowExplicitlyBlocked: boolean,
1583
+ ): string[] {
1584
+ if (!gsdPhase || !workflowServerName || workflowExplicitlyBlocked) return [];
1585
+ const requiredTools = gsdPhase === "run-uat"
1586
+ ? [...RUN_UAT_WORKFLOW_TOOL_NAMES]
1587
+ : getRequiredWorkflowToolsForAutoUnit(gsdPhase);
1588
+ const supportTools = gsdPhase === "run-uat" ? [] : ["gsd_milestone_status"];
1589
+ const requestedToolNames = [...new Set([...requiredTools, ...supportTools])];
1590
+ if (requestedToolNames.length === 0) return [];
1591
+ return resolveToolPresentationPlan({
1592
+ phase: gsdPhase,
1593
+ surface: "claude-code-sdk",
1594
+ workflowMcpServerName: workflowServerName,
1595
+ requestedToolNames,
1596
+ }).presentedToolNames;
1597
+ }
1598
+
1599
+ export function autoInitClaudeCodeWorkflowMcp(cwd: string): void {
1600
+ const projectRoot = resolveWorkflowMcpProjectRoot(cwd);
1601
+ try {
1602
+ ensureProjectWorkflowMcpConfig(projectRoot);
1603
+ } catch (err) {
1604
+ if (process.env.GSD_DEBUG === "1") {
1605
+ console.warn(
1606
+ `[claude-code] workflow MCP auto-init failed: ${err instanceof Error ? err.message : String(err)}`,
1607
+ );
1608
+ }
1609
+ }
1478
1610
  }
1479
1611
 
1480
1612
  /**
@@ -1492,9 +1624,9 @@ export function buildSdkOptions(
1492
1624
  modelId: string,
1493
1625
  prompt: string,
1494
1626
  overrides?: { permissionMode?: "bypassPermissions" | "acceptEdits" | "default" | "plan" },
1495
- extraOptions: Record<string, unknown> & { reasoning?: ThinkingLevel } = {},
1627
+ extraOptions: Record<string, unknown> & { reasoning?: ThinkingLevel; gsdPhase?: string } = {},
1496
1628
  ): Record<string, unknown> {
1497
- const { reasoning, cwd, ...sdkExtraOptions } = extraOptions;
1629
+ const { reasoning, cwd, gsdPhase, ...sdkExtraOptions } = extraOptions;
1498
1630
  const sdkCwd = typeof cwd === "string" && cwd.trim().length > 0 ? cwd : process.cwd();
1499
1631
  // Claude Code runs in the milestone worktree for file/shell work, but workflow MCP
1500
1632
  // config (.mcp.json) and server discovery live at the project root.
@@ -1578,13 +1710,46 @@ export function buildSdkOptions(
1578
1710
  const browserMcpTools = !browserExplicitlyBlocked && browserServerName
1579
1711
  ? [`mcp__${browserServerName}__*`]
1580
1712
  : [];
1581
- const gsdMcpTools = [...workflowMcpTools, ...browserMcpTools];
1713
+ const phaseUsesBrowserMcp = !gsdPhase || gsdPhase === "run-uat";
1714
+ const allowedBrowserMcpTools = phaseUsesBrowserMcp ? browserMcpTools : [];
1715
+ const inlinePhaseMcpServers = gsdPhase
1716
+ ? resolveProjectMcpServerConfigs(
1717
+ projectRoot,
1718
+ [
1719
+ workflowExplicitlyBlocked ? undefined : workflowServerName,
1720
+ phaseUsesBrowserMcp && !browserExplicitlyBlocked ? browserServerName : undefined,
1721
+ ],
1722
+ defaultMcpServers.servers,
1723
+ )
1724
+ : undefined;
1725
+ const sdkMcpServers = inlinePhaseMcpServers ?? filteredMcpServers;
1726
+ const strictMcpConfig = !!inlinePhaseMcpServers;
1727
+ // Strict phase configs inline the exact MCP servers GSD needs. Loading
1728
+ // project/local settings at the same time can duplicate those servers and
1729
+ // leave allowed mcp__... tools with no registered backing tool.
1730
+ const settingSources = strictMcpConfig ? [] : ["project", "local"];
1731
+ const exactWorkflowMcpTools = resolveExactWorkflowMcpToolsForPhase(
1732
+ gsdPhase,
1733
+ workflowServerName,
1734
+ workflowExplicitlyBlocked,
1735
+ );
1736
+ const runUatDisallowedTools = gsdPhase === "run-uat" && workflowServerName
1737
+ ? [
1738
+ ...RUN_UAT_FORBIDDEN_TOOL_NAMES.filter((toolName) => !toolName.startsWith("mcp__")),
1739
+ "WebFetch",
1740
+ "Agent",
1741
+ `mcp__${workflowServerName}__gsd_exec`,
1742
+ `mcp__${workflowServerName}__gsd_summary_save`,
1743
+ `mcp__${workflowServerName}__gsd_save_gate_result`,
1744
+ ]
1745
+ : [];
1582
1746
  const disallowedTools: string[] = [...new Set([
1583
1747
  "ToolSearch",
1584
- ...(workflowMcpTools.length > 0 ? ["AskUserQuestion"] : []),
1748
+ ...(workflowMcpTools.length > 0 || exactWorkflowMcpTools.length > 0 ? ["AskUserQuestion"] : []),
1749
+ ...runUatDisallowedTools,
1585
1750
  ...extraDisallowedTools,
1586
1751
  ])];
1587
- const allowedTools = [
1752
+ const standardClaudeTools = [
1588
1753
  "Read",
1589
1754
  "Write",
1590
1755
  "Edit",
@@ -1594,8 +1759,19 @@ export function buildSdkOptions(
1594
1759
  "Agent",
1595
1760
  "WebFetch",
1596
1761
  "WebSearch",
1597
- ...(workflowMcpTools.length > 0 ? gsdMcpTools : ["AskUserQuestion", ...browserMcpTools]),
1598
1762
  ];
1763
+ const allowedTools = gsdPhase === "run-uat"
1764
+ ? [
1765
+ ...RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES,
1766
+ ...(exactWorkflowMcpTools.length > 0 ? exactWorkflowMcpTools : []),
1767
+ ...allowedBrowserMcpTools,
1768
+ ]
1769
+ : [
1770
+ ...standardClaudeTools,
1771
+ ...exactWorkflowMcpTools,
1772
+ ...(workflowMcpTools.length > 0 ? workflowMcpTools : ["AskUserQuestion"]),
1773
+ ...allowedBrowserMcpTools,
1774
+ ];
1599
1775
  const supportsAdaptive = modelSupportsAdaptiveThinking(modelId);
1600
1776
  const effort =
1601
1777
  reasoning && supportsAdaptive
@@ -1619,11 +1795,12 @@ export function buildSdkOptions(
1619
1795
  cwd: sdkCwd,
1620
1796
  permissionMode,
1621
1797
  allowDangerouslySkipPermissions: permissionMode === "bypassPermissions",
1622
- settingSources: ["project"],
1798
+ settingSources,
1623
1799
  systemPrompt: { type: "preset", preset: "claude_code" },
1624
1800
  disallowedTools,
1625
1801
  ...(allowedTools.length > 0 ? { allowedTools } : {}),
1626
- ...(filteredMcpServers ? { mcpServers: filteredMcpServers } : {}),
1802
+ ...(sdkMcpServers ? { mcpServers: sdkMcpServers } : {}),
1803
+ ...(strictMcpConfig ? { strictMcpConfig: true } : {}),
1627
1804
  betas: (
1628
1805
  modelId.includes("sonnet")
1629
1806
  || modelId.includes("opus-4-7")
@@ -1954,6 +2131,8 @@ async function pumpSdkMessages(
1954
2131
  const onExternalToolCall = (options as ClaudeCodeStreamOptions | undefined)?.onExternalToolCall;
1955
2132
  const onExternalToolResult = (options as ClaudeCodeStreamOptions | undefined)?.onExternalToolResult;
1956
2133
  const cwd = resolveClaudeCodeCwd(options);
2134
+ autoInitClaudeCodeWorkflowMcp(cwd);
2135
+ const gsdPhase = inferGsdPhaseFromContext(context);
1957
2136
  const canUseToolHandler = createClaudeCodeCanUseToolHandler(uiContext);
1958
2137
  // When no UI is available (headless / auto-mode), auto-approve all
1959
2138
  // tool requests. This replaces the old bypassPermissions workaround.
@@ -1966,6 +2145,7 @@ async function pumpSdkMessages(
1966
2145
  { permissionMode },
1967
2146
  {
1968
2147
  cwd,
2148
+ gsdPhase,
1969
2149
  reasoning: options?.reasoning,
1970
2150
  canUseTool: canUseToolFallback,
1971
2151
  ...(uiContext