gsd-pi 2.67.0-dev.2142d3e → 2.67.0-dev.2367d7e

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 (233) hide show
  1. package/README.md +1 -1
  2. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +152 -70
  3. package/dist/resources/extensions/gsd/auto/session.js +10 -0
  4. package/dist/resources/extensions/gsd/auto-dispatch.js +1 -1
  5. package/dist/resources/extensions/gsd/auto-start.js +16 -30
  6. package/dist/resources/extensions/gsd/auto-worktree.js +62 -15
  7. package/dist/resources/extensions/gsd/auto.js +121 -59
  8. package/dist/resources/extensions/gsd/bootstrap/system-context.js +7 -2
  9. package/dist/resources/extensions/gsd/commands/catalog.js +2 -1
  10. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -1
  11. package/dist/resources/extensions/gsd/commands-mcp-status.js +43 -7
  12. package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -4
  13. package/dist/resources/extensions/gsd/doctor-proactive.js +3 -3
  14. package/dist/resources/extensions/gsd/doctor.js +8 -4
  15. package/dist/resources/extensions/gsd/gsd-db.js +11 -0
  16. package/dist/resources/extensions/gsd/guided-flow.js +40 -31
  17. package/dist/resources/extensions/gsd/init-wizard.js +15 -12
  18. package/dist/resources/extensions/gsd/interrupted-session.js +146 -0
  19. package/dist/resources/extensions/gsd/mcp-project-config.js +83 -0
  20. package/dist/resources/extensions/gsd/state.js +7 -2
  21. package/dist/resources/extensions/gsd/workflow-mcp.js +90 -19
  22. package/dist/web/standalone/.next/BUILD_ID +1 -1
  23. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  24. package/dist/web/standalone/.next/build-manifest.json +3 -3
  25. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  26. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  27. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  29. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  37. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/index.html +1 -1
  46. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  47. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  48. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  49. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  53. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  54. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  55. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  57. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  58. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  59. package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +9 -0
  60. package/dist/web/standalone/.next/static/chunks/app/{page-0c485498795110d6.js → page-f1e30ab6bb269149.js} +1 -1
  61. package/dist/web/standalone/.next/static/chunks/{webpack-b49b09f97429b5d0.js → webpack-6e4d7e9a4f57bed4.js} +1 -1
  62. package/package.json +4 -2
  63. package/packages/mcp-server/dist/cli.d.ts +9 -0
  64. package/packages/mcp-server/dist/cli.d.ts.map +1 -0
  65. package/packages/mcp-server/dist/cli.js +58 -0
  66. package/packages/mcp-server/dist/cli.js.map +1 -0
  67. package/packages/mcp-server/dist/index.d.ts +20 -0
  68. package/packages/mcp-server/dist/index.d.ts.map +1 -0
  69. package/packages/mcp-server/dist/index.js +14 -0
  70. package/packages/mcp-server/dist/index.js.map +1 -0
  71. package/packages/mcp-server/dist/readers/captures.d.ts +25 -0
  72. package/packages/mcp-server/dist/readers/captures.d.ts.map +1 -0
  73. package/packages/mcp-server/dist/readers/captures.js +67 -0
  74. package/packages/mcp-server/dist/readers/captures.js.map +1 -0
  75. package/packages/mcp-server/dist/readers/doctor-lite.d.ts +20 -0
  76. package/packages/mcp-server/dist/readers/doctor-lite.d.ts.map +1 -0
  77. package/packages/mcp-server/dist/readers/doctor-lite.js +173 -0
  78. package/packages/mcp-server/dist/readers/doctor-lite.js.map +1 -0
  79. package/packages/mcp-server/dist/readers/index.d.ts +14 -0
  80. package/packages/mcp-server/dist/readers/index.d.ts.map +1 -0
  81. package/packages/mcp-server/dist/readers/index.js +10 -0
  82. package/packages/mcp-server/dist/readers/index.js.map +1 -0
  83. package/packages/mcp-server/dist/readers/knowledge.d.ts +18 -0
  84. package/packages/mcp-server/dist/readers/knowledge.d.ts.map +1 -0
  85. package/packages/mcp-server/dist/readers/knowledge.js +82 -0
  86. package/packages/mcp-server/dist/readers/knowledge.js.map +1 -0
  87. package/packages/mcp-server/dist/readers/metrics.d.ts +32 -0
  88. package/packages/mcp-server/dist/readers/metrics.d.ts.map +1 -0
  89. package/packages/mcp-server/dist/readers/metrics.js +74 -0
  90. package/packages/mcp-server/dist/readers/metrics.js.map +1 -0
  91. package/packages/mcp-server/dist/readers/paths.d.ts +42 -0
  92. package/packages/mcp-server/dist/readers/paths.d.ts.map +1 -0
  93. package/packages/mcp-server/dist/readers/paths.js +199 -0
  94. package/packages/mcp-server/dist/readers/paths.js.map +1 -0
  95. package/packages/mcp-server/dist/readers/roadmap.d.ts +26 -0
  96. package/packages/mcp-server/dist/readers/roadmap.d.ts.map +1 -0
  97. package/packages/mcp-server/dist/readers/roadmap.js +194 -0
  98. package/packages/mcp-server/dist/readers/roadmap.js.map +1 -0
  99. package/packages/mcp-server/dist/readers/state.d.ts +43 -0
  100. package/packages/mcp-server/dist/readers/state.d.ts.map +1 -0
  101. package/packages/mcp-server/dist/readers/state.js +184 -0
  102. package/packages/mcp-server/dist/readers/state.js.map +1 -0
  103. package/packages/mcp-server/dist/server.d.ts +28 -0
  104. package/packages/mcp-server/dist/server.d.ts.map +1 -0
  105. package/packages/mcp-server/dist/server.js +319 -0
  106. package/packages/mcp-server/dist/server.js.map +1 -0
  107. package/packages/mcp-server/dist/session-manager.d.ts +54 -0
  108. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -0
  109. package/packages/mcp-server/dist/session-manager.js +284 -0
  110. package/packages/mcp-server/dist/session-manager.js.map +1 -0
  111. package/packages/mcp-server/dist/types.d.ts +61 -0
  112. package/packages/mcp-server/dist/types.d.ts.map +1 -0
  113. package/packages/mcp-server/dist/types.js +11 -0
  114. package/packages/mcp-server/dist/types.js.map +1 -0
  115. package/packages/mcp-server/dist/workflow-tools.d.ts +9 -0
  116. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -0
  117. package/packages/mcp-server/dist/workflow-tools.js +532 -0
  118. package/packages/mcp-server/dist/workflow-tools.js.map +1 -0
  119. package/packages/mcp-server/src/workflow-tools.ts +13 -2
  120. package/packages/mcp-server/tsconfig.json +1 -1
  121. package/packages/pi-agent-core/dist/agent-loop.js +14 -6
  122. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  123. package/packages/pi-agent-core/src/agent-loop.test.ts +53 -0
  124. package/packages/pi-agent-core/src/agent-loop.ts +20 -6
  125. package/packages/pi-coding-agent/dist/core/contextual-tips.d.ts +43 -0
  126. package/packages/pi-coding-agent/dist/core/contextual-tips.d.ts.map +1 -0
  127. package/packages/pi-coding-agent/dist/core/contextual-tips.js +208 -0
  128. package/packages/pi-coding-agent/dist/core/contextual-tips.js.map +1 -0
  129. package/packages/pi-coding-agent/dist/core/contextual-tips.test.d.ts +2 -0
  130. package/packages/pi-coding-agent/dist/core/contextual-tips.test.d.ts.map +1 -0
  131. package/packages/pi-coding-agent/dist/core/contextual-tips.test.js +227 -0
  132. package/packages/pi-coding-agent/dist/core/contextual-tips.test.js.map +1 -0
  133. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
  134. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  135. package/packages/pi-coding-agent/dist/core/index.js +1 -0
  136. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  137. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.d.ts +2 -0
  138. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.d.ts.map +1 -0
  139. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +28 -0
  140. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -0
  141. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
  142. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  143. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +17 -12
  144. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  145. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  146. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +19 -0
  147. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  148. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts +4 -0
  149. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  150. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +14 -0
  151. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  152. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  153. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  154. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +15 -12
  155. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  156. package/packages/pi-coding-agent/src/core/contextual-tips.test.ts +259 -0
  157. package/packages/pi-coding-agent/src/core/contextual-tips.ts +232 -0
  158. package/packages/pi-coding-agent/src/core/index.ts +2 -0
  159. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +54 -0
  160. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +18 -12
  161. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +21 -0
  162. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +19 -0
  163. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +19 -15
  164. package/packages/rpc-client/dist/index.d.ts +10 -0
  165. package/packages/rpc-client/dist/index.d.ts.map +1 -0
  166. package/packages/rpc-client/dist/index.js +9 -0
  167. package/packages/rpc-client/dist/index.js.map +1 -0
  168. package/packages/rpc-client/dist/jsonl.d.ts +17 -0
  169. package/packages/rpc-client/dist/jsonl.d.ts.map +1 -0
  170. package/packages/rpc-client/dist/jsonl.js +54 -0
  171. package/packages/rpc-client/dist/jsonl.js.map +1 -0
  172. package/packages/rpc-client/dist/rpc-client.d.ts +259 -0
  173. package/packages/rpc-client/dist/rpc-client.d.ts.map +1 -0
  174. package/packages/rpc-client/dist/rpc-client.js +541 -0
  175. package/packages/rpc-client/dist/rpc-client.js.map +1 -0
  176. package/packages/rpc-client/dist/rpc-client.test.d.ts +2 -0
  177. package/packages/rpc-client/dist/rpc-client.test.d.ts.map +1 -0
  178. package/packages/rpc-client/dist/rpc-client.test.js +477 -0
  179. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -0
  180. package/packages/rpc-client/dist/rpc-types.d.ts +566 -0
  181. package/packages/rpc-client/dist/rpc-types.d.ts.map +1 -0
  182. package/packages/rpc-client/dist/rpc-types.js +12 -0
  183. package/packages/rpc-client/dist/rpc-types.js.map +1 -0
  184. package/scripts/ensure-workspace-builds.cjs +2 -0
  185. package/scripts/link-workspace-packages.cjs +21 -14
  186. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +190 -93
  187. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +89 -116
  188. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  189. package/src/resources/extensions/gsd/auto-dispatch.ts +1 -1
  190. package/src/resources/extensions/gsd/auto-start.ts +23 -55
  191. package/src/resources/extensions/gsd/auto-worktree.ts +59 -15
  192. package/src/resources/extensions/gsd/auto.ts +133 -64
  193. package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -2
  194. package/src/resources/extensions/gsd/commands/catalog.ts +2 -1
  195. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
  196. package/src/resources/extensions/gsd/commands-mcp-status.ts +53 -7
  197. package/src/resources/extensions/gsd/doctor-git-checks.ts +4 -4
  198. package/src/resources/extensions/gsd/doctor-proactive.ts +3 -3
  199. package/src/resources/extensions/gsd/doctor.ts +9 -5
  200. package/src/resources/extensions/gsd/gsd-db.ts +12 -0
  201. package/src/resources/extensions/gsd/guided-flow.ts +42 -36
  202. package/src/resources/extensions/gsd/init-wizard.ts +17 -11
  203. package/src/resources/extensions/gsd/interrupted-session.ts +224 -0
  204. package/src/resources/extensions/gsd/mcp-project-config.ts +128 -0
  205. package/src/resources/extensions/gsd/state.ts +7 -1
  206. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +29 -0
  207. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +668 -2
  208. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +14 -4
  209. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +21 -0
  210. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +380 -2
  211. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +30 -0
  212. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +12 -0
  213. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +2 -2
  214. package/src/resources/extensions/gsd/tests/integration/doctor-fixlevel.test.ts +52 -1
  215. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +2 -9
  216. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +0 -33
  217. package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +169 -0
  218. package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +146 -0
  219. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +136 -0
  220. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +85 -0
  221. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +15 -0
  222. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +11 -0
  223. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +212 -13
  224. package/src/resources/extensions/gsd/workflow-mcp.ts +106 -19
  225. package/dist/web/standalone/.next/static/chunks/6502.b804e48b7919f55e.js +0 -9
  226. package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.d.ts +0 -13
  227. package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.d.ts.map +0 -1
  228. package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.js +0 -27
  229. package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.js.map +0 -1
  230. package/packages/pi-coding-agent/src/modes/interactive/provider-auth-setup.ts +0 -40
  231. package/src/resources/extensions/gsd/tests/init-bootstrap-completeness.test.ts +0 -121
  232. /package/dist/web/standalone/.next/static/{xR6qurkuYSvyjBjRyJLxG → WMDT_0C0XDkBKtsAI_AX4}/_buildManifest.js +0 -0
  233. /package/dist/web/standalone/.next/static/{xR6qurkuYSvyjBjRyJLxG → WMDT_0C0XDkBKtsAI_AX4}/_ssgManifest.js +0 -0
@@ -1,8 +1,11 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { readFileSync } from "node:fs";
3
+ import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { dirname, join } from "node:path";
5
+ import { tmpdir } from "node:os";
5
6
  import { fileURLToPath } from "node:url";
7
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
8
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
6
9
 
7
10
  import {
8
11
  buildWorkflowMcpServers,
@@ -43,13 +46,14 @@ test("detectWorkflowMcpLaunchConfig prefers explicit env override", () => {
43
46
  command: "node",
44
47
  args: ["dist/cli.js"],
45
48
  cwd: "/tmp/project",
46
- env: {
47
- FOO: "bar",
48
- GSD_CLI_PATH: "/tmp/gsd",
49
- GSD_PERSIST_WRITE_GATE_STATE: "1",
50
- GSD_WORKFLOW_PROJECT_ROOT: "/tmp/project",
51
- },
49
+ env: launch?.env,
52
50
  });
51
+ assert.equal(launch?.env?.FOO, "bar");
52
+ assert.equal(launch?.env?.GSD_CLI_PATH, "/tmp/gsd");
53
+ assert.equal(launch?.env?.GSD_PERSIST_WRITE_GATE_STATE, "1");
54
+ assert.equal(launch?.env?.GSD_WORKFLOW_PROJECT_ROOT, "/tmp/project");
55
+ assert.match(launch?.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "", /workflow-tool-executors\.(js|ts)$/);
56
+ assert.match(launch?.env?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "", /write-gate\.(js|ts)$/);
53
57
  });
54
58
 
55
59
  test("buildWorkflowMcpServers mirrors explicit launch config", () => {
@@ -62,12 +66,207 @@ test("buildWorkflowMcpServers mirrors explicit launch config", () => {
62
66
  "gsd-workflow": {
63
67
  command: "node",
64
68
  args: ["dist/cli.js"],
65
- env: {
66
- GSD_PERSIST_WRITE_GATE_STATE: "1",
67
- GSD_WORKFLOW_PROJECT_ROOT: "/tmp/project",
68
- },
69
+ env: servers?.["gsd-workflow"]?.env,
69
70
  },
70
71
  });
72
+ assert.equal((servers?.["gsd-workflow"]?.env as Record<string, string> | undefined)?.GSD_PERSIST_WRITE_GATE_STATE, "1");
73
+ assert.equal((servers?.["gsd-workflow"]?.env as Record<string, string> | undefined)?.GSD_WORKFLOW_PROJECT_ROOT, "/tmp/project");
74
+ assert.match((servers?.["gsd-workflow"]?.env as Record<string, string> | undefined)?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "", /workflow-tool-executors\.(js|ts)$/);
75
+ assert.match((servers?.["gsd-workflow"]?.env as Record<string, string> | undefined)?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "", /write-gate\.(js|ts)$/);
76
+ });
77
+
78
+ test("detectWorkflowMcpLaunchConfig resolves the bundled server from GSD_PROJECT_ROOT", () => {
79
+ const repoRoot = mkdtempSync(join(tmpdir(), "gsd-workflow-root-"));
80
+ const worktreeRoot = mkdtempSync(join(tmpdir(), "gsd-workflow-worktree-"));
81
+ const cliPath = join(repoRoot, "packages", "mcp-server", "dist", "cli.js");
82
+
83
+ mkdirSync(join(repoRoot, "packages", "mcp-server", "dist"), { recursive: true });
84
+ writeFileSync(cliPath, "#!/usr/bin/env node\n", "utf-8");
85
+
86
+ const launch = detectWorkflowMcpLaunchConfig(worktreeRoot, {
87
+ GSD_PROJECT_ROOT: repoRoot,
88
+ });
89
+
90
+ assert.deepEqual(launch, {
91
+ name: "gsd-workflow",
92
+ command: process.execPath,
93
+ args: [cliPath],
94
+ cwd: repoRoot,
95
+ env: launch?.env,
96
+ });
97
+ assert.equal(launch?.env?.GSD_PERSIST_WRITE_GATE_STATE, "1");
98
+ assert.equal(launch?.env?.GSD_WORKFLOW_PROJECT_ROOT, repoRoot);
99
+ assert.match(launch?.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "", /workflow-tool-executors\.(js|ts)$/);
100
+ assert.match(launch?.env?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "", /write-gate\.(js|ts)$/);
101
+ });
102
+
103
+ test("detectWorkflowMcpLaunchConfig resolves the bundled server from GSD_BIN_PATH ancestry", () => {
104
+ const repoRoot = mkdtempSync(join(tmpdir(), "gsd-workflow-root-"));
105
+ const worktreeRoot = mkdtempSync(join(tmpdir(), "gsd-workflow-worktree-"));
106
+ const cliPath = join(repoRoot, "packages", "mcp-server", "dist", "cli.js");
107
+ const devCliPath = join(repoRoot, "scripts", "dev-cli.js");
108
+
109
+ mkdirSync(join(repoRoot, "packages", "mcp-server", "dist"), { recursive: true });
110
+ mkdirSync(join(repoRoot, "scripts"), { recursive: true });
111
+ writeFileSync(cliPath, "#!/usr/bin/env node\n", "utf-8");
112
+ writeFileSync(devCliPath, "#!/usr/bin/env node\n", "utf-8");
113
+
114
+ const launch = detectWorkflowMcpLaunchConfig(worktreeRoot, {
115
+ GSD_BIN_PATH: devCliPath,
116
+ });
117
+
118
+ assert.deepEqual(launch, {
119
+ name: "gsd-workflow",
120
+ command: process.execPath,
121
+ args: [cliPath],
122
+ cwd: worktreeRoot,
123
+ env: launch?.env,
124
+ });
125
+ assert.equal(launch?.env?.GSD_CLI_PATH, devCliPath);
126
+ assert.equal(launch?.env?.GSD_PERSIST_WRITE_GATE_STATE, "1");
127
+ assert.equal(launch?.env?.GSD_WORKFLOW_PROJECT_ROOT, worktreeRoot);
128
+ assert.match(launch?.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "", /workflow-tool-executors\.(js|ts)$/);
129
+ assert.match(launch?.env?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "", /write-gate\.(js|ts)$/);
130
+ });
131
+
132
+ test("detectWorkflowMcpLaunchConfig resolves the bundled server relative to the installed GSD package", () => {
133
+ const launch = detectWorkflowMcpLaunchConfig("/tmp/project", {
134
+ GSD_BIN_PATH: "/tmp/gsd-loader.js",
135
+ });
136
+
137
+ assert.equal(launch?.command, process.execPath);
138
+ assert.equal(launch?.cwd, "/tmp/project");
139
+ assert.equal(launch?.env?.GSD_CLI_PATH, "/tmp/gsd-loader.js");
140
+ assert.equal(launch?.env?.GSD_WORKFLOW_PROJECT_ROOT, "/tmp/project");
141
+ assert.match(launch?.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "", /workflow-tool-executors\.(js|ts)$/);
142
+ assert.match(launch?.env?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "", /write-gate\.(js|ts)$/);
143
+ assert.equal(typeof launch?.args?.[0], "string");
144
+ assert.match(launch?.args?.[0] ?? "", /packages[\/\\]mcp-server[\/\\]dist[\/\\]cli\.js$/);
145
+ });
146
+
147
+ test("detectWorkflowMcpLaunchConfig resolves the bundled server relative to the package without env hints", () => {
148
+ const launch = detectWorkflowMcpLaunchConfig("/tmp/project", {});
149
+
150
+ assert.equal(launch?.command, process.execPath);
151
+ assert.equal(launch?.cwd, "/tmp/project");
152
+ assert.equal(launch?.env?.GSD_CLI_PATH, undefined);
153
+ assert.equal(launch?.env?.GSD_WORKFLOW_PROJECT_ROOT, "/tmp/project");
154
+ assert.match(launch?.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "", /workflow-tool-executors\.(js|ts)$/);
155
+ assert.match(launch?.env?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "", /write-gate\.(js|ts)$/);
156
+ assert.equal(typeof launch?.args?.[0], "string");
157
+ assert.match(launch?.args?.[0] ?? "", /packages[\/\\]mcp-server[\/\\]dist[\/\\]cli\.js$/);
158
+ });
159
+
160
+ test("workflow MCP launch config reaches mutation tools over stdio", async () => {
161
+ const projectRoot = mkdtempSync(join(tmpdir(), "gsd-workflow-transport-"));
162
+ mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
163
+
164
+ const launch = detectWorkflowMcpLaunchConfig(projectRoot, {});
165
+ assert.ok(launch, "expected a workflow MCP launch config");
166
+ assert.match(
167
+ launch.env?.GSD_WORKFLOW_EXECUTORS_MODULE ?? "",
168
+ /dist[\/\\]resources[\/\\]extensions[\/\\]gsd[\/\\]tools[\/\\]workflow-tool-executors\.js$/,
169
+ );
170
+ assert.match(
171
+ launch.env?.GSD_WORKFLOW_WRITE_GATE_MODULE ?? "",
172
+ /dist[\/\\]resources[\/\\]extensions[\/\\]gsd[\/\\]bootstrap[\/\\]write-gate\.js$/,
173
+ );
174
+
175
+ const client = new Client({ name: "workflow-mcp-transport-test", version: "1.0.0" });
176
+ const transport = new StdioClientTransport({
177
+ command: launch.command,
178
+ args: launch.args,
179
+ env: { ...process.env, ...launch.env } as Record<string, string>,
180
+ cwd: launch.cwd,
181
+ stderr: "pipe",
182
+ });
183
+
184
+ try {
185
+ await client.connect(transport, { timeout: 30_000 });
186
+
187
+ const tools = await client.listTools(undefined, { timeout: 30_000 });
188
+ assert.ok(
189
+ (tools.tools ?? []).some((tool) => tool.name === "gsd_plan_slice"),
190
+ "expected workflow MCP surface to expose gsd_plan_slice",
191
+ );
192
+
193
+ const milestoneResult = await client.callTool(
194
+ {
195
+ name: "gsd_plan_milestone",
196
+ arguments: {
197
+ projectDir: projectRoot,
198
+ milestoneId: "M001",
199
+ title: "Transport planning",
200
+ vision: "Verify stdio workflow MCP uses the executor bridge.",
201
+ slices: [
202
+ {
203
+ sliceId: "S01",
204
+ title: "Bridge path",
205
+ risk: "low",
206
+ depends: [],
207
+ demo: "Milestone planning succeeds over stdio MCP.",
208
+ goal: "Prove the executor bridge works in the spawned server.",
209
+ successCriteria: "gsd_plan_slice can write plan artifacts.",
210
+ proofLevel: "integration",
211
+ integrationClosure: "Stdio MCP client reaches the workflow executor bridge.",
212
+ observabilityImpact: "Regression test covers the spawned-server path.",
213
+ },
214
+ ],
215
+ },
216
+ },
217
+ undefined,
218
+ { timeout: 30_000 },
219
+ );
220
+ assert.equal(milestoneResult.isError, undefined);
221
+ assert.match(
222
+ ((milestoneResult.content as Array<{ text?: string }>)?.[0])?.text ?? "",
223
+ /Planned milestone M001/,
224
+ );
225
+
226
+ const sliceResult = await client.callTool(
227
+ {
228
+ name: "gsd_plan_slice",
229
+ arguments: {
230
+ projectDir: projectRoot,
231
+ milestoneId: "M001",
232
+ sliceId: "S01",
233
+ goal: "Persist slice planning over the spawned MCP transport.",
234
+ tasks: [
235
+ {
236
+ taskId: "T01",
237
+ title: "Connect the bridge",
238
+ description: "Ensure the workflow executor bridge resolves in the child process.",
239
+ estimate: "10m",
240
+ files: ["src/resources/extensions/gsd/workflow-mcp.ts"],
241
+ verify: "node --test",
242
+ inputs: ["M001-ROADMAP.md"],
243
+ expectedOutput: ["S01-PLAN.md", "T01-PLAN.md"],
244
+ },
245
+ ],
246
+ },
247
+ },
248
+ undefined,
249
+ { timeout: 30_000 },
250
+ );
251
+ assert.equal(sliceResult.isError, undefined);
252
+ assert.match(
253
+ ((sliceResult.content as Array<{ text?: string }>)?.[0])?.text ?? "",
254
+ /Planned slice S01/,
255
+ );
256
+ assert.ok(
257
+ existsSync(join(projectRoot, ".gsd", "milestones", "M001", "slices", "S01", "S01-PLAN.md")),
258
+ "expected slice plan artifact to be written through stdio MCP",
259
+ );
260
+ assert.ok(
261
+ existsSync(
262
+ join(projectRoot, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-PLAN.md"),
263
+ ),
264
+ "expected task plan artifact to be written through stdio MCP",
265
+ );
266
+ } finally {
267
+ await client.close().catch(() => {});
268
+ rmSync(projectRoot, { recursive: true, force: true });
269
+ }
71
270
  });
72
271
 
73
272
  test("usesWorkflowMcpTransport matches local externalCli providers", () => {
@@ -93,7 +292,7 @@ test("transport compatibility passes when required tools fit current MCP surface
93
292
  assert.equal(error, null);
94
293
  });
95
294
 
96
- test("transport compatibility fails cleanly when MCP server is unavailable", () => {
295
+ test("transport compatibility discovers the bundled MCP server without env overrides", () => {
97
296
  const error = getWorkflowTransportSupportError(
98
297
  "claude-code",
99
298
  ["gsd_task_complete"],
@@ -107,7 +306,7 @@ test("transport compatibility fails cleanly when MCP server is unavailable", ()
107
306
  },
108
307
  );
109
308
 
110
- assert.match(error ?? "", /workflow MCP server is not configured or discoverable/);
309
+ assert.equal(error, null);
111
310
  });
112
311
 
113
312
  test("transport compatibility now allows auto execute-task over workflow MCP surface", () => {
@@ -1,6 +1,7 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
- import { resolve } from "node:path";
3
+ import { dirname, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
4
5
 
5
6
  export interface WorkflowMcpLaunchConfig {
6
7
  name: string;
@@ -66,6 +67,91 @@ function lookupCommand(command: string, platform: NodeJS.Platform = process.plat
66
67
  }
67
68
  }
68
69
 
70
+ function findWorkflowCliFromAncestorPath(startPath: string): string | null {
71
+ let current = resolve(startPath);
72
+
73
+ while (true) {
74
+ const candidate = resolve(current, "packages", "mcp-server", "dist", "cli.js");
75
+ if (existsSync(candidate)) return candidate;
76
+
77
+ const parent = dirname(current);
78
+ if (parent === current) break;
79
+ current = parent;
80
+ }
81
+
82
+ return null;
83
+ }
84
+
85
+ function getBundledWorkflowMcpCliPath(env: NodeJS.ProcessEnv): string | null {
86
+ const envAnchors = [
87
+ env.GSD_BIN_PATH?.trim(),
88
+ env.GSD_CLI_PATH?.trim(),
89
+ env.GSD_WORKFLOW_PATH?.trim(),
90
+ ].filter((value): value is string => typeof value === "string" && value.length > 0);
91
+
92
+ for (const anchor of envAnchors) {
93
+ const candidate = findWorkflowCliFromAncestorPath(anchor);
94
+ if (candidate) return candidate;
95
+ }
96
+
97
+ const candidates = [
98
+ resolve(fileURLToPath(new URL("../../../../packages/mcp-server/dist/cli.js", import.meta.url))),
99
+ resolve(fileURLToPath(new URL("../../../../../packages/mcp-server/dist/cli.js", import.meta.url))),
100
+ ];
101
+
102
+ for (const bundledCli of candidates) {
103
+ if (existsSync(bundledCli)) return bundledCli;
104
+ }
105
+
106
+ return null;
107
+ }
108
+
109
+ function getBundledWorkflowExecutorModulePath(): string | null {
110
+ const candidates = [
111
+ resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/tools/workflow-tool-executors.js", import.meta.url))),
112
+ resolve(fileURLToPath(new URL("./tools/workflow-tool-executors.js", import.meta.url))),
113
+ resolve(fileURLToPath(new URL("./tools/workflow-tool-executors.ts", import.meta.url))),
114
+ ];
115
+
116
+ for (const candidate of candidates) {
117
+ if (existsSync(candidate)) return candidate;
118
+ }
119
+
120
+ return null;
121
+ }
122
+
123
+ function getBundledWorkflowWriteGateModulePath(): string | null {
124
+ const candidates = [
125
+ resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/bootstrap/write-gate.js", import.meta.url))),
126
+ resolve(fileURLToPath(new URL("./bootstrap/write-gate.js", import.meta.url))),
127
+ resolve(fileURLToPath(new URL("./bootstrap/write-gate.ts", import.meta.url))),
128
+ ];
129
+
130
+ for (const candidate of candidates) {
131
+ if (existsSync(candidate)) return candidate;
132
+ }
133
+
134
+ return null;
135
+ }
136
+
137
+ function buildWorkflowLaunchEnv(
138
+ projectRoot: string,
139
+ gsdCliPath: string | undefined,
140
+ explicitEnv?: Record<string, string>,
141
+ ): Record<string, string> {
142
+ const executorModulePath = getBundledWorkflowExecutorModulePath();
143
+ const writeGateModulePath = getBundledWorkflowWriteGateModulePath();
144
+
145
+ return {
146
+ ...(explicitEnv ?? {}),
147
+ ...(gsdCliPath ? { GSD_CLI_PATH: gsdCliPath } : {}),
148
+ ...(executorModulePath ? { GSD_WORKFLOW_EXECUTORS_MODULE: executorModulePath } : {}),
149
+ ...(writeGateModulePath ? { GSD_WORKFLOW_WRITE_GATE_MODULE: writeGateModulePath } : {}),
150
+ GSD_PERSIST_WRITE_GATE_STATE: "1",
151
+ GSD_WORKFLOW_PROJECT_ROOT: projectRoot,
152
+ };
153
+ }
154
+
69
155
  export function detectWorkflowMcpLaunchConfig(
70
156
  projectRoot = process.cwd(),
71
157
  env: NodeJS.ProcessEnv = process.env,
@@ -75,19 +161,17 @@ export function detectWorkflowMcpLaunchConfig(
75
161
  const explicitArgs = parseJsonEnv<unknown>(env, "GSD_WORKFLOW_MCP_ARGS");
76
162
  const explicitEnv = parseJsonEnv<Record<string, string>>(env, "GSD_WORKFLOW_MCP_ENV");
77
163
  const explicitCwd = env.GSD_WORKFLOW_MCP_CWD?.trim();
164
+ const gsdCliPath = env.GSD_CLI_PATH?.trim() || env.GSD_BIN_PATH?.trim();
78
165
  const workflowProjectRoot =
79
166
  explicitEnv?.GSD_WORKFLOW_PROJECT_ROOT?.trim() ||
80
167
  env.GSD_WORKFLOW_PROJECT_ROOT?.trim() ||
168
+ env.GSD_PROJECT_ROOT?.trim() ||
81
169
  explicitCwd ||
82
170
  projectRoot;
171
+ const resolvedWorkflowProjectRoot = resolve(workflowProjectRoot);
83
172
 
84
173
  if (explicitCommand) {
85
- const launchEnv = {
86
- ...(explicitEnv ?? {}),
87
- ...(env.GSD_CLI_PATH ? { GSD_CLI_PATH: env.GSD_CLI_PATH } : {}),
88
- GSD_PERSIST_WRITE_GATE_STATE: "1",
89
- GSD_WORKFLOW_PROJECT_ROOT: resolve(workflowProjectRoot),
90
- };
174
+ const launchEnv = buildWorkflowLaunchEnv(resolve(workflowProjectRoot), gsdCliPath, explicitEnv);
91
175
  return {
92
176
  name,
93
177
  command: explicitCommand,
@@ -97,18 +181,25 @@ export function detectWorkflowMcpLaunchConfig(
97
181
  };
98
182
  }
99
183
 
100
- const distCli = resolve(projectRoot, "packages", "mcp-server", "dist", "cli.js");
184
+ const distCli = resolve(resolvedWorkflowProjectRoot, "packages", "mcp-server", "dist", "cli.js");
101
185
  if (existsSync(distCli)) {
102
186
  return {
103
187
  name,
104
188
  command: process.execPath,
105
189
  args: [distCli],
106
- cwd: projectRoot,
107
- env: {
108
- ...(env.GSD_CLI_PATH ? { GSD_CLI_PATH: env.GSD_CLI_PATH } : {}),
109
- GSD_PERSIST_WRITE_GATE_STATE: "1",
110
- GSD_WORKFLOW_PROJECT_ROOT: resolve(projectRoot),
111
- },
190
+ cwd: resolvedWorkflowProjectRoot,
191
+ env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
192
+ };
193
+ }
194
+
195
+ const bundledCli = getBundledWorkflowMcpCliPath(env);
196
+ if (bundledCli) {
197
+ return {
198
+ name,
199
+ command: process.execPath,
200
+ args: [bundledCli],
201
+ cwd: resolvedWorkflowProjectRoot,
202
+ env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
112
203
  };
113
204
  }
114
205
 
@@ -117,11 +208,7 @@ export function detectWorkflowMcpLaunchConfig(
117
208
  return {
118
209
  name,
119
210
  command: binPath,
120
- env: {
121
- ...(env.GSD_CLI_PATH ? { GSD_CLI_PATH: env.GSD_CLI_PATH } : {}),
122
- GSD_PERSIST_WRITE_GATE_STATE: "1",
123
- GSD_WORKFLOW_PROJECT_ROOT: resolve(projectRoot),
124
- },
211
+ env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
125
212
  };
126
213
  }
127
214