@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.eed73bea

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 (183) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
  3. package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
  4. package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
  5. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -14
  6. package/dist/resources/extensions/gsd/auto-prompts.js +43 -12
  7. package/dist/resources/extensions/gsd/auto-recovery.js +13 -6
  8. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
  9. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +6 -1
  10. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
  11. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +8 -3
  12. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
  13. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +75 -1
  14. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  15. package/dist/resources/extensions/gsd/commands-context.js +19 -1
  16. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -10
  17. package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
  18. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
  19. package/dist/resources/extensions/gsd/db/queries.js +60 -0
  20. package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
  21. package/dist/resources/extensions/gsd/exec-sandbox.js +45 -9
  22. package/dist/resources/extensions/gsd/forensics.js +2 -32
  23. package/dist/resources/extensions/gsd/git-service.js +4 -4
  24. package/dist/resources/extensions/gsd/guided-flow-queue.js +59 -5
  25. package/dist/resources/extensions/gsd/health-widget.js +55 -29
  26. package/dist/resources/extensions/gsd/markdown-renderer.js +6 -2
  27. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
  28. package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
  29. package/dist/resources/extensions/gsd/quick.js +45 -2
  30. package/dist/resources/extensions/gsd/session-forensics.js +11 -1
  31. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +52 -3
  32. package/dist/resources/extensions/gsd/tools/complete-slice.js +34 -3
  33. package/dist/resources/extensions/gsd/tools/complete-task.js +78 -16
  34. package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
  35. package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
  36. package/dist/resources/extensions/gsd/unit-registry.js +25 -3
  37. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
  38. package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
  39. package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
  40. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  41. package/dist/web/standalone/.next/BUILD_ID +1 -1
  42. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  43. package/dist/web/standalone/.next/build-manifest.json +3 -3
  44. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  45. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  46. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  47. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  55. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  63. package/dist/web/standalone/.next/server/app/index.html +1 -1
  64. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  71. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  74. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  75. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  76. package/dist/web/standalone/.next/static/chunks/{796.e0bdc932325d7e03.js → 796.3976108148518f7d.js} +3 -3
  77. package/dist/web/standalone/.next/static/chunks/{webpack-f46ea08200a0227e.js → webpack-7c1d97e39be2da11.js} +1 -1
  78. package/package.json +1 -1
  79. package/packages/cloud-mcp-gateway/package.json +2 -2
  80. package/packages/contracts/dist/workflow.d.ts +1 -0
  81. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  82. package/packages/contracts/dist/workflow.js +2 -0
  83. package/packages/contracts/dist/workflow.js.map +1 -1
  84. package/packages/contracts/package.json +1 -1
  85. package/packages/daemon/package.json +4 -4
  86. package/packages/gsd-agent-core/package.json +5 -5
  87. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  88. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +21 -9
  89. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  90. package/packages/gsd-agent-modes/package.json +7 -7
  91. package/packages/mcp-server/README.md +1 -1
  92. package/packages/mcp-server/dist/server.d.ts +1 -1
  93. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  94. package/packages/mcp-server/dist/server.js +3 -3
  95. package/packages/mcp-server/dist/server.js.map +1 -1
  96. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  97. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  98. package/packages/mcp-server/dist/workflow-tools.js +34 -20
  99. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  100. package/packages/mcp-server/package.json +4 -4
  101. package/packages/native/package.json +1 -1
  102. package/packages/pi-agent-core/package.json +1 -1
  103. package/packages/pi-ai/package.json +1 -1
  104. package/packages/pi-coding-agent/package.json +7 -7
  105. package/packages/pi-tui/package.json +2 -2
  106. package/packages/rpc-client/package.json +2 -2
  107. package/pkg/package.json +1 -1
  108. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
  109. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
  110. package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
  111. package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
  112. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -17
  113. package/src/resources/extensions/gsd/auto-prompts.ts +54 -12
  114. package/src/resources/extensions/gsd/auto-recovery.ts +13 -6
  115. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
  116. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +6 -1
  117. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
  118. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +9 -3
  119. package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
  120. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +82 -1
  121. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  122. package/src/resources/extensions/gsd/commands-context.ts +18 -1
  123. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +14 -9
  124. package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
  125. package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
  126. package/src/resources/extensions/gsd/db/queries.ts +79 -0
  127. package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
  128. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  129. package/src/resources/extensions/gsd/forensics.ts +2 -33
  130. package/src/resources/extensions/gsd/git-service.ts +5 -5
  131. package/src/resources/extensions/gsd/guided-flow-queue.ts +82 -4
  132. package/src/resources/extensions/gsd/health-widget.ts +69 -32
  133. package/src/resources/extensions/gsd/markdown-renderer.ts +6 -1
  134. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
  135. package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
  136. package/src/resources/extensions/gsd/quick.ts +43 -2
  137. package/src/resources/extensions/gsd/session-forensics.ts +11 -1
  138. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +76 -8
  139. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -1
  140. package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
  141. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
  142. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
  143. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
  144. package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
  145. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
  146. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
  147. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
  148. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
  149. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
  150. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
  151. package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
  152. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
  153. package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
  154. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +119 -1
  155. package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
  156. package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
  157. package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
  158. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
  159. package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
  160. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
  161. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
  162. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
  163. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
  164. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
  165. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
  166. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +76 -0
  167. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +68 -0
  168. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +26 -0
  169. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
  170. package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
  171. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
  172. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
  173. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
  174. package/src/resources/extensions/gsd/tools/complete-slice.ts +30 -3
  175. package/src/resources/extensions/gsd/tools/complete-task.ts +86 -16
  176. package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
  177. package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
  178. package/src/resources/extensions/gsd/unit-registry.ts +25 -3
  179. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
  180. package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
  181. package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
  182. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → SzEuqWX37DR9MEpEuQjP1}/_buildManifest.js +0 -0
  183. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → SzEuqWX37DR9MEpEuQjP1}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengsd/mcp-server",
3
- "version": "1.3.0-dev.65546769",
3
+ "version": "1.3.0-dev.eed73bea",
4
4
  "description": "MCP server exposing GSD orchestration tools for compatible clients",
5
5
  "license": "MIT",
6
6
  "gsd": {
@@ -50,9 +50,9 @@
50
50
  "test": "pnpm run build:test && node --test dist/mcp-server.test.js dist/remote-questions.test.js dist/moonshot-tool-schema.test.js dist/pid-registry.test.js dist/probe-mode.test.js dist/stdio-watchdog.test.js dist/cli-runner.test.js dist/readers/graph.test.js dist/readers/paths.test.js dist/readers/readers.test.js"
51
51
  },
52
52
  "dependencies": {
53
- "@gsd/pi-ai": "^1.3.0-dev.65546769",
54
- "@opengsd/contracts": "^1.3.0-dev.65546769",
55
- "@opengsd/rpc-client": "^1.3.0-dev.65546769",
53
+ "@gsd/pi-ai": "^1.3.0-dev.eed73bea",
54
+ "@opengsd/contracts": "^1.3.0-dev.eed73bea",
55
+ "@opengsd/rpc-client": "^1.3.0-dev.eed73bea",
56
56
  "@modelcontextprotocol/sdk": "^1.27.1",
57
57
  "zod": "^4.0.0"
58
58
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/native",
3
- "version": "1.3.0-dev.65546769",
3
+ "version": "1.3.0-dev.eed73bea",
4
4
  "description": "Native Rust bindings for GSD — high-performance native modules via N-API",
5
5
  "type": "commonjs",
6
6
  "gsd": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/pi-agent-core",
3
- "version": "1.3.0-dev.65546769",
3
+ "version": "1.3.0-dev.eed73bea",
4
4
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
5
5
  "type": "module",
6
6
  "gsd": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/pi-ai",
3
- "version": "1.3.0-dev.65546769",
3
+ "version": "1.3.0-dev.eed73bea",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "type": "module",
6
6
  "gsd": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/pi-coding-agent",
3
- "version": "1.3.0-dev.65546769",
3
+ "version": "1.3.0-dev.eed73bea",
4
4
  "description": "Coding agent CLI (vendored from earendil-works/pi)",
5
5
  "type": "module",
6
6
  "gsd": {
@@ -33,7 +33,7 @@
33
33
  "copy-assets": "node scripts/copy-assets.cjs"
34
34
  },
35
35
  "dependencies": {
36
- "@opengsd/contracts": "^1.3.0-dev.65546769",
36
+ "@opengsd/contracts": "^1.3.0-dev.eed73bea",
37
37
  "@mariozechner/jiti": "^2.6.2",
38
38
  "@silvia-odwyer/photon-node": "0.3.4",
39
39
  "chalk": "5.6.2",
@@ -53,11 +53,11 @@
53
53
  "typebox": "1.1.38",
54
54
  "undici": "7.28.0",
55
55
  "yaml": "2.9.0",
56
- "@gsd/agent-core": "^1.3.0-dev.65546769",
57
- "@gsd/native": "^1.3.0-dev.65546769",
58
- "@gsd/pi-agent-core": "^1.3.0-dev.65546769",
59
- "@gsd/pi-ai": "^1.3.0-dev.65546769",
60
- "@gsd/pi-tui": "^1.3.0-dev.65546769",
56
+ "@gsd/agent-core": "^1.3.0-dev.eed73bea",
57
+ "@gsd/native": "^1.3.0-dev.eed73bea",
58
+ "@gsd/pi-agent-core": "^1.3.0-dev.eed73bea",
59
+ "@gsd/pi-ai": "^1.3.0-dev.eed73bea",
60
+ "@gsd/pi-tui": "^1.3.0-dev.eed73bea",
61
61
  "@sinclair/typebox": "^0.34.41"
62
62
  },
63
63
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/pi-tui",
3
- "version": "1.3.0-dev.65546769",
3
+ "version": "1.3.0-dev.eed73bea",
4
4
  "description": "Terminal UI library (vendored from earendil-works/pi)",
5
5
  "type": "module",
6
6
  "gsd": {
@@ -21,7 +21,7 @@
21
21
  "build": "node ../../scripts/clean-package-dist.cjs && tsc -p tsconfig.json --incremental false"
22
22
  },
23
23
  "dependencies": {
24
- "@gsd/native": "^1.3.0-dev.65546769",
24
+ "@gsd/native": "^1.3.0-dev.eed73bea",
25
25
  "get-east-asian-width": "1.6.0",
26
26
  "marked": "15.0.12",
27
27
  "@sinclair/typebox": "^0.34.41"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengsd/rpc-client",
3
- "version": "1.3.0-dev.65546769",
3
+ "version": "1.3.0-dev.eed73bea",
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.3.0-dev.65546769"
37
+ "@opengsd/contracts": "^1.3.0-dev.eed73bea"
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.3.0-dev.65546769",
3
+ "version": "1.3.0-dev.eed73bea",
4
4
  "piConfig": {
5
5
  "name": "gsd",
6
6
  "configDir": ".gsd"
@@ -101,6 +101,7 @@ export type {
101
101
  interface PromptToolContextOptions {
102
102
  workflowMcpServerName?: string | null;
103
103
  browserMcpServerName?: string | null;
104
+ questionToolAvailable?: boolean;
104
105
  }
105
106
 
106
107
  /** `SimpleStreamOptions` extended with an optional extension UI context for elicitation dialogs. */
@@ -480,8 +481,10 @@ export function buildPromptFromContext(context: Context, toolContext: PromptTool
480
481
  ? "- GSD workflow tools (gsd_exec, gsd_slice_complete, gsd_task_complete, gsd_plan_slice, gsd_save_gate_result, etc.) " +
481
482
  `are MCP tools — call them as mcp__${toolContext.workflowMcpServerName}__<tool_name> ` +
482
483
  `(e.g. mcp__${toolContext.workflowMcpServerName}__gsd_exec, mcp__${toolContext.workflowMcpServerName}__gsd_save_gate_result)\n` +
483
- `- Structured user input: call mcp__${toolContext.workflowMcpServerName}__ask_user_questions. ` +
484
- "Do not call bare ask_user_questions. Do not call native AskUserQuestion.\n"
484
+ (toolContext.questionToolAvailable !== false
485
+ ? `- Structured user input: call mcp__${toolContext.workflowMcpServerName}__ask_user_questions. ` +
486
+ "Do not call bare ask_user_questions. Do not call native AskUserQuestion.\n"
487
+ : "")
485
488
  : "- GSD workflow MCP tools are unavailable in this Claude Code run.\n";
486
489
  const toolSearchLine = toolContext.workflowMcpServerName
487
490
  ? "- ToolSearch is available only for Claude Code deferred workflow MCP hydration. " +
@@ -1753,6 +1756,16 @@ function workflowMcpServerNameFromAllowedTools(allowedTools: unknown): string |
1753
1756
  return undefined;
1754
1757
  }
1755
1758
 
1759
+ function workflowQuestionToolAvailableFromAllowedTools(
1760
+ allowedTools: unknown,
1761
+ workflowMcpServerName: string | undefined,
1762
+ gsdPhase: string | undefined,
1763
+ ): boolean | undefined {
1764
+ if (!workflowMcpServerName || !gsdPhase) return undefined;
1765
+ return Array.isArray(allowedTools)
1766
+ && allowedTools.includes(`mcp__${workflowMcpServerName}__ask_user_questions`);
1767
+ }
1768
+
1756
1769
  function isRecord(value: unknown): value is Record<string, unknown> {
1757
1770
  return !!value && typeof value === "object" && !Array.isArray(value);
1758
1771
  }
@@ -2257,6 +2270,11 @@ async function pumpSdkMessages(
2257
2270
  const prompt = buildPromptFromContext(context, {
2258
2271
  workflowMcpServerName,
2259
2272
  browserMcpServerName: browserMcpServerNameFromAllowedTools(sdkOpts.allowedTools),
2273
+ questionToolAvailable: workflowQuestionToolAvailableFromAllowedTools(
2274
+ sdkOpts.allowedTools,
2275
+ workflowMcpServerName,
2276
+ gsdPhase,
2277
+ ),
2260
2278
  });
2261
2279
  const queryPrompt = buildSdkQueryPrompt(context, prompt);
2262
2280
 
@@ -2001,6 +2001,86 @@ describe("stream-adapter — session persistence (#2859)", () => {
2001
2001
  });
2002
2002
 
2003
2003
  describe("stream-adapter — workflow MCP readiness", () => {
2004
+ test("strict slice phase prompt omits workflow MCP question guidance when allowedTools omit it", async () => {
2005
+ const cwd = realpathSync(mkdtempSync(join(tmpdir(), "claude-sdk-strict-question-prompt-")));
2006
+ const restore = setWorkflowMcpEnv({
2007
+ GSD_WORKFLOW_MCP_COMMAND: process.execPath,
2008
+ GSD_WORKFLOW_MCP_NAME: "gsd-workflow",
2009
+ GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["-e", ""]),
2010
+ GSD_WORKFLOW_MCP_CWD: cwd,
2011
+ });
2012
+ const phases = [
2013
+ { type: "research-slice", label: "Research Slice", expectedTool: "mcp__gsd-workflow__gsd_summary_save" },
2014
+ { type: "plan-slice", label: "Plan Slice", expectedTool: "mcp__gsd-workflow__gsd_plan_slice" },
2015
+ { type: "refine-slice", label: "Refine Slice", expectedTool: "mcp__gsd-workflow__gsd_plan_slice" },
2016
+ ] as const;
2017
+ clearGuidedUnitContext();
2018
+ _setAutoActiveForTest(true);
2019
+ try {
2020
+ for (const phase of phases) {
2021
+ let capturedPrompt: unknown;
2022
+ let capturedAllowedTools: string[] | undefined;
2023
+ autoSession.currentUnit = { type: phase.type, id: "M001/S001", startedAt: 0, workspaceRoot: cwd } as never;
2024
+ const stream = streamViaClaudeCode(
2025
+ { id: "claude-sonnet-4-6" } as any,
2026
+ {
2027
+ systemPrompt: `UNIT: ${phase.label}`,
2028
+ messages: [{ role: "user", content: "Complete the strict slice phase." } as Message],
2029
+ },
2030
+ {
2031
+ cwd,
2032
+ _skipWorkflowMcpPreflightForTest: true,
2033
+ async *_sdkQueryForTest(args: {
2034
+ prompt: string | AsyncIterable<unknown>;
2035
+ options?: Record<string, unknown>;
2036
+ }) {
2037
+ capturedPrompt = args.prompt;
2038
+ capturedAllowedTools = args.options?.allowedTools as string[] | undefined;
2039
+ yield {
2040
+ type: "result",
2041
+ subtype: "success",
2042
+ uuid: `result-${phase.type}`,
2043
+ session_id: `session-${phase.type}`,
2044
+ duration_ms: 1,
2045
+ duration_api_ms: 1,
2046
+ is_error: false,
2047
+ num_turns: 1,
2048
+ result: "completed",
2049
+ stop_reason: "end_turn",
2050
+ total_cost_usd: 0,
2051
+ usage: {
2052
+ input_tokens: 0,
2053
+ output_tokens: 0,
2054
+ cache_read_input_tokens: 0,
2055
+ cache_creation_input_tokens: 0,
2056
+ },
2057
+ };
2058
+ },
2059
+ } as any,
2060
+ );
2061
+
2062
+ await stream.result();
2063
+
2064
+ assert.equal(typeof capturedPrompt, "string", phase.type);
2065
+ const prompt = capturedPrompt as string;
2066
+ assert.ok(capturedAllowedTools?.includes(phase.expectedTool), phase.type);
2067
+ assert.ok(!capturedAllowedTools?.includes("mcp__gsd-workflow__ask_user_questions"), phase.type);
2068
+ assert.ok(!prompt.includes("mcp__gsd-workflow__ask_user_questions"), phase.type);
2069
+ assert.ok(!prompt.includes("Do not call bare ask_user_questions"), phase.type);
2070
+ assert.ok(
2071
+ prompt.includes("ToolSearch is available only for Claude Code deferred workflow MCP hydration"),
2072
+ phase.type,
2073
+ );
2074
+ }
2075
+ } finally {
2076
+ autoSession.currentUnit = null;
2077
+ _setAutoActiveForTest(false);
2078
+ restore();
2079
+ rmSync(cwd, { recursive: true, force: true });
2080
+ clearMcpConfigCache();
2081
+ }
2082
+ });
2083
+
2004
2084
  test("resolves the workflow MCP preflight config from SDK mcpServers", () => {
2005
2085
  const workflowConfig = { command: "node", args: ["workflow-server.js"] };
2006
2086
  const browserConfig = { command: "gsd-browser" };
@@ -20,7 +20,13 @@ const ZERO_USAGE = {
20
20
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
21
21
  };
22
22
 
23
- type GoogleCliProviderId = "google-gemini-cli" | "google-antigravity";
23
+ export type GoogleCliProviderId = "google-gemini-cli" | "google-antigravity";
24
+
25
+ export interface GoogleCliRunPlan {
26
+ command: string;
27
+ args: string[];
28
+ stdin?: string;
29
+ }
24
30
 
25
31
  interface CliRunResult {
26
32
  stdout: string;
@@ -29,6 +35,71 @@ interface CliRunResult {
29
35
  signal: NodeJS.Signals | null;
30
36
  }
31
37
 
38
+ const WINDOWS_CHILD_ENV_KEYS = new Set([
39
+ "ALLUSERSPROFILE",
40
+ "APPDATA",
41
+ "COMSPEC",
42
+ "COMMONPROGRAMFILES",
43
+ "COMMONPROGRAMFILES(X86)",
44
+ "FORCE_COLOR",
45
+ "HOME",
46
+ "HOMEDRIVE",
47
+ "HOMEPATH",
48
+ "LANG",
49
+ "LC_ALL",
50
+ "LOCALAPPDATA",
51
+ "NODE_EXTRA_CA_CERTS",
52
+ "NO_COLOR",
53
+ "NO_PROXY",
54
+ "PATHEXT",
55
+ "PATH",
56
+ "PROGRAMDATA",
57
+ "PROGRAMFILES",
58
+ "PROGRAMFILES(X86)",
59
+ "SSL_CERT_FILE",
60
+ "SYSTEMROOT",
61
+ "TEMP",
62
+ "TERM",
63
+ "TMP",
64
+ "TMPDIR",
65
+ "USER",
66
+ "USERNAME",
67
+ "USERPROFILE",
68
+ "WINDIR",
69
+ "XDG_CACHE_HOME",
70
+ "XDG_CONFIG_HOME",
71
+ "HTTP_PROXY",
72
+ "HTTPS_PROXY",
73
+ ]);
74
+
75
+ const WINDOWS_CHILD_ENV_PREFIXES = [
76
+ "AGY_",
77
+ "ANTIGRAVITY_",
78
+ "CLOUDSDK_",
79
+ "GEMINI_",
80
+ "GOOGLE_",
81
+ ];
82
+
83
+ export function buildGoogleCliChildEnv(
84
+ env: NodeJS.ProcessEnv = process.env,
85
+ platform: NodeJS.Platform = process.platform,
86
+ ): NodeJS.ProcessEnv {
87
+ if (platform !== "win32") return env;
88
+
89
+ const childEnv: NodeJS.ProcessEnv = {};
90
+ for (const [key, value] of Object.entries(env)) {
91
+ if (typeof value !== "string") continue;
92
+ const upperKey = key.toUpperCase();
93
+ if (
94
+ WINDOWS_CHILD_ENV_KEYS.has(upperKey) ||
95
+ WINDOWS_CHILD_ENV_PREFIXES.some((prefix) => upperKey.startsWith(prefix))
96
+ ) {
97
+ childEnv[key] = value;
98
+ }
99
+ }
100
+ return childEnv;
101
+ }
102
+
32
103
  function textBlocks(content: (TextContent | { type: string })[]): string {
33
104
  return content
34
105
  .map((block) => block.type === "text" ? (block as TextContent).text : `[${block.type} omitted]`)
@@ -120,15 +191,15 @@ function commandForProvider(provider: GoogleCliProviderId): string {
120
191
  return provider === "google-gemini-cli" ? "gemini" : "agy";
121
192
  }
122
193
 
123
- function argsForProvider(provider: GoogleCliProviderId, model: Model<Api>, prompt: string): string[] {
194
+ function argsForProvider(provider: GoogleCliProviderId, modelId: string, prompt?: string): string[] {
124
195
  if (provider === "google-gemini-cli") {
125
- const args = ["-p", prompt, "--output-format", "json"];
126
- if (model.id !== "default") args.unshift("-m", model.id);
196
+ const args = prompt === undefined ? ["--output-format", "json"] : ["-p", prompt, "--output-format", "json"];
197
+ if (modelId !== "default") args.unshift("-m", modelId);
127
198
  return args;
128
199
  }
129
200
 
130
- const args = ["-p", prompt];
131
- if (model.id !== "default") args.unshift("-m", model.id);
201
+ const args = prompt === undefined ? [] : ["-p", prompt];
202
+ if (modelId !== "default") args.unshift("-m", modelId);
132
203
  return args;
133
204
  }
134
205
 
@@ -136,20 +207,33 @@ export function buildGoogleCliSpawnInvocation(
136
207
  command: string,
137
208
  args: string[],
138
209
  platform: NodeJS.Platform = process.platform,
139
- ): { command: string; args: string[] } {
210
+ ): Omit<GoogleCliRunPlan, "stdin"> {
140
211
  if (platform === "win32") {
141
212
  return { command: "cmd", args: ["/c", command, ...args] };
142
213
  }
143
214
  return { command, args };
144
215
  }
145
216
 
146
- function runCli(command: string, args: string[], options?: SimpleStreamOptions): Promise<CliRunResult> {
217
+ export function buildGoogleCliRunPlan(
218
+ provider: GoogleCliProviderId,
219
+ modelId: string,
220
+ prompt: string,
221
+ platform: NodeJS.Platform = process.platform,
222
+ ): GoogleCliRunPlan {
223
+ const pipePrompt = platform === "win32";
224
+ const args = argsForProvider(provider, modelId, pipePrompt ? undefined : prompt);
225
+ return {
226
+ ...buildGoogleCliSpawnInvocation(commandForProvider(provider), args, platform),
227
+ ...(pipePrompt ? { stdin: prompt } : {}),
228
+ };
229
+ }
230
+
231
+ function runCli(plan: GoogleCliRunPlan, options?: SimpleStreamOptions): Promise<CliRunResult> {
147
232
  return new Promise((resolve, reject) => {
148
- const invocation = buildGoogleCliSpawnInvocation(command, args);
149
- const child = spawn(invocation.command, invocation.args, {
233
+ const child = spawn(plan.command, plan.args, {
150
234
  cwd: options?.cwd || process.cwd(),
151
- env: process.env,
152
- stdio: ["ignore", "pipe", "pipe"],
235
+ env: buildGoogleCliChildEnv(),
236
+ stdio: [plan.stdin === undefined ? "ignore" : "pipe", "pipe", "pipe"],
153
237
  });
154
238
 
155
239
  let stdout = "";
@@ -174,12 +258,17 @@ function runCli(command: string, args: string[], options?: SimpleStreamOptions):
174
258
  }
175
259
  options?.signal?.addEventListener("abort", onAbort);
176
260
 
177
- child.stdout.setEncoding("utf8");
178
- child.stderr.setEncoding("utf8");
179
- child.stdout.on("data", (chunk) => {
261
+ if (plan.stdin !== undefined) {
262
+ child.stdin?.on("error", () => {});
263
+ child.stdin?.end(plan.stdin);
264
+ }
265
+
266
+ child.stdout!.setEncoding("utf8");
267
+ child.stderr!.setEncoding("utf8");
268
+ child.stdout!.on("data", (chunk) => {
180
269
  stdout += chunk;
181
270
  });
182
- child.stderr.on("data", (chunk) => {
271
+ child.stderr!.on("data", (chunk) => {
183
272
  stderr += chunk;
184
273
  });
185
274
 
@@ -243,9 +332,7 @@ export function streamViaGoogleCli(
243
332
  queueMicrotask(async () => {
244
333
  try {
245
334
  const prompt = buildGoogleCliPrompt(context);
246
- const command = commandForProvider(provider);
247
- const args = argsForProvider(provider, model, prompt);
248
- const result = await runCli(command, args, options);
335
+ const result = await runCli(buildGoogleCliRunPlan(provider, model.id, prompt), options);
249
336
 
250
337
  if (result.code !== 0) {
251
338
  const detail = (result.stderr || result.stdout || `CLI exited with code ${result.code}`).trim();
@@ -76,6 +76,8 @@ import { join } from "node:path";
76
76
  import { evaluateAllCompleteSettlement } from "../milestone-settlement.js";
77
77
  import { hasHeldMilestoneLease, reclaimMissingMilestoneLease } from "./milestone-lease-reclaim.js";
78
78
 
79
+ type UokFlags = ReturnType<typeof resolveUokFlags>;
80
+
79
81
  function now(): number {
80
82
  return Date.now();
81
83
  }
@@ -517,15 +519,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
517
519
 
518
520
  // ── UokGateAdapter (folded) ──────────────────────────────────────────────
519
521
 
520
- private async emitUokGate(input: {
521
- gateId: string;
522
- gateType: "policy" | "execution";
523
- outcome: "pass" | "fail" | "manual-attention";
524
- failureClass: "none" | "policy" | "manual-attention";
525
- rationale: string;
526
- findings?: string;
527
- milestoneId?: string;
528
- }): Promise<void> {
522
+ private resolveUokGateContext(): { activeBasePath: string; uokFlags: UokFlags } {
529
523
  const activeBasePath = this.getLiveDispatchBasePath();
530
524
  const prefs = loadEffectiveGSDPreferencesWithRegistry(
531
525
  this.ctx.modelRegistry,
@@ -535,8 +529,22 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
535
529
  ? `${this.s.autoModeStartModel.provider}/${this.s.autoModeStartModel.id}`
536
530
  : undefined,
537
531
  )?.preferences;
538
- const uokFlags = resolveUokFlags(prefs);
539
- if (!uokFlags.gates) return;
532
+ return { activeBasePath, uokFlags: resolveUokFlags(prefs) };
533
+ }
534
+
535
+ private async emitUokGate(input: {
536
+ gateId: string;
537
+ gateType: "policy" | "execution";
538
+ outcome: "pass" | "fail" | "manual-attention";
539
+ failureClass: "none" | "policy" | "manual-attention";
540
+ rationale: string;
541
+ findings?: string;
542
+ milestoneId?: string;
543
+ activeBasePath: string;
544
+ uokFlags: UokFlags;
545
+ }): Promise<void> {
546
+ if (!input.uokFlags.gates) return;
547
+ const activeBasePath = input.activeBasePath;
540
548
  const milestoneId = input.milestoneId ?? this.s.currentMilestoneId ?? undefined;
541
549
  try {
542
550
  const { UokGateRunner } = await import("../uok/gate-runner.js");
@@ -943,10 +951,12 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
943
951
  const stopAdvanceTimer = debugTime("orchestrator-advance");
944
952
  try {
945
953
  this.ensureLockOwnership();
954
+ const uokGateContext = this.resolveUokGateContext();
946
955
 
947
956
  const staleMsg = this.checkResourcesStale();
948
957
  if (staleMsg) {
949
958
  await this.emitUokGate({
959
+ ...uokGateContext,
950
960
  gateId: "resource-version-guard",
951
961
  gateType: "policy",
952
962
  outcome: "fail",
@@ -960,6 +970,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
960
970
  return blocked;
961
971
  }
962
972
  await this.emitUokGate({
973
+ ...uokGateContext,
963
974
  gateId: "resource-version-guard",
964
975
  gateType: "policy",
965
976
  outcome: "pass",
@@ -970,6 +981,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
970
981
  const gate = await this.preAdvanceGate();
971
982
  if (gate.kind === "fail") {
972
983
  await this.emitUokGate({
984
+ ...uokGateContext,
973
985
  gateId: "pre-dispatch-health-gate",
974
986
  gateType: "execution",
975
987
  outcome: "manual-attention",
@@ -988,6 +1000,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
988
1000
  }
989
1001
  if (gate.kind === "threw") {
990
1002
  await this.emitUokGate({
1003
+ ...uokGateContext,
991
1004
  gateId: "pre-dispatch-health-gate",
992
1005
  gateType: "execution",
993
1006
  outcome: "manual-attention",
@@ -998,6 +1011,7 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
998
1011
  // intentional fall-through: matches runPreDispatch behaviour
999
1012
  } else {
1000
1013
  await this.emitUokGate({
1014
+ ...uokGateContext,
1001
1015
  gateId: "pre-dispatch-health-gate",
1002
1016
  gateType: "execution",
1003
1017
  outcome: "pass",
@@ -30,6 +30,7 @@ import {
30
30
  setSliceSketchFlag,
31
31
  transaction,
32
32
  getAssessment,
33
+ getSliceRunUatAssessment,
33
34
  } from "./gsd-db.js";
34
35
  import { isClosedStatus } from "./status-guards.js";
35
36
  import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
@@ -322,6 +323,19 @@ export async function readUatGateVerdict(
322
323
  }
323
324
  }
324
325
 
326
+ // ADR-017 DB fallback: when the ASSESSMENT markdown is missing or orphaned
327
+ // from its canonical path (e.g. after a milestone artifact-layout migration
328
+ // moves slice artifacts from `phases/…` to `milestones/…`), consult the
329
+ // authoritative assessments table by (mid, slice) identity instead of path.
330
+ // `gsd_uat_result_save` always writes this row, so it is the source of truth.
331
+ const runUatAssessment = getSliceRunUatAssessment(mid, sliceId);
332
+ if (runUatAssessment?.status) {
333
+ return {
334
+ verdict: runUatAssessment.status,
335
+ uatType: uatType ?? extractUatType(runUatAssessment.fullContent),
336
+ };
337
+ }
338
+
325
339
  return null;
326
340
  }
327
341
 
@@ -1142,16 +1156,13 @@ export const DISPATCH_RULES: DispatchRule[] = [
1142
1156
  const dbSlices = getMilestoneSliceSummaries(mid);
1143
1157
  if (dbSlices.length === 0) return null;
1144
1158
 
1145
- // Find slices that need research (no RESEARCH file, dependencies done)
1146
- const milestoneResearchFile =
1147
- resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
1148
- resolveMilestoneFile(basePath, mid, "RESEARCH");
1159
+ // Find slices that need research (no RESEARCH file, dependencies done).
1160
+ // Milestone research informs slice research; it does not satisfy the
1161
+ // per-slice RESEARCH artifact contract.
1149
1162
  const researchReadySlices: Array<{ id: string; title: string }> = [];
1150
1163
 
1151
1164
  for (const slice of dbSlices) {
1152
1165
  if (slice.done) continue;
1153
- // Skip S01 when milestone research exists
1154
- if (milestoneResearchFile && slice.id === "S01") continue;
1155
1166
  // Skip if already has research
1156
1167
  if (resolveExistingExpectedArtifact("research-slice", `${mid}/${slice.id}`, basePath)) continue;
1157
1168
  // Skip if dependencies aren't done (check for SUMMARY files)
@@ -1190,7 +1201,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
1190
1201
  },
1191
1202
  },
1192
1203
  {
1193
- name: "planning (no research, not S01) → research-slice",
1204
+ name: "planning (no research) → research-slice",
1194
1205
  match: async ({ state, mid, midTitle, basePath, prefs }) => {
1195
1206
  if (state.phase !== "planning") return null;
1196
1207
  // Phase skip: skip research when preference or profile says so
@@ -1205,16 +1216,6 @@ export const DISPATCH_RULES: DispatchRule[] = [
1205
1216
  resolveExistingExpectedArtifact("research-slice", `${mid}/${sid}`, basePath) ??
1206
1217
  resolveSliceFile(basePath, mid, sid, "RESEARCH");
1207
1218
  if (researchFile) return null; // has research, fall through
1208
- // Skip slice research for S01 when milestone research already exists —
1209
- // the milestone research already covers the same ground for the first slice.
1210
- const milestoneResearchFile =
1211
- resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
1212
- resolveMilestoneFile(
1213
- basePath,
1214
- mid,
1215
- "RESEARCH",
1216
- );
1217
- if (milestoneResearchFile && sid === "S01") return null; // fall through to plan-slice
1218
1219
  return {
1219
1220
  action: "dispatch",
1220
1221
  unitType: "research-slice",