gsd-pi 2.67.0-dev.5399650 → 2.67.0-dev.6fc2289
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.
- package/README.md +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +152 -70
- package/dist/resources/extensions/gsd/auto/session.js +4 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +1 -1
- package/dist/resources/extensions/gsd/auto-start.js +16 -30
- package/dist/resources/extensions/gsd/auto-worktree.js +62 -15
- package/dist/resources/extensions/gsd/auto.js +94 -59
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +7 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +2 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -1
- package/dist/resources/extensions/gsd/commands-mcp-status.js +43 -7
- package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -4
- package/dist/resources/extensions/gsd/doctor-proactive.js +3 -3
- package/dist/resources/extensions/gsd/doctor.js +8 -4
- package/dist/resources/extensions/gsd/guided-flow.js +40 -31
- package/dist/resources/extensions/gsd/init-wizard.js +15 -12
- package/dist/resources/extensions/gsd/interrupted-session.js +146 -0
- package/dist/resources/extensions/gsd/mcp-project-config.js +83 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +64 -24
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-0c485498795110d6.js → page-f1e30ab6bb269149.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-b49b09f97429b5d0.js → webpack-6e4d7e9a4f57bed4.js} +1 -1
- package/package.json +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +10 -4
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.ts +13 -2
- package/packages/pi-agent-core/dist/agent-loop.js +14 -6
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +53 -0
- package/packages/pi-agent-core/src/agent-loop.ts +20 -6
- package/packages/pi-coding-agent/dist/core/contextual-tips.d.ts +43 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.js +208 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.test.js +227 -0
- package/packages/pi-coding-agent/dist/core/contextual-tips.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +28 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +17 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +19 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +14 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +15 -12
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/contextual-tips.test.ts +259 -0
- package/packages/pi-coding-agent/src/core/contextual-tips.ts +232 -0
- package/packages/pi-coding-agent/src/core/index.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +54 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +18 -12
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +21 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +19 -15
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +190 -93
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +89 -116
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +1 -1
- package/src/resources/extensions/gsd/auto-start.ts +23 -55
- package/src/resources/extensions/gsd/auto-worktree.ts +59 -15
- package/src/resources/extensions/gsd/auto.ts +104 -63
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -2
- package/src/resources/extensions/gsd/commands/catalog.ts +2 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -1
- package/src/resources/extensions/gsd/commands-mcp-status.ts +53 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +4 -4
- package/src/resources/extensions/gsd/doctor-proactive.ts +3 -3
- package/src/resources/extensions/gsd/doctor.ts +9 -5
- package/src/resources/extensions/gsd/guided-flow.ts +42 -36
- package/src/resources/extensions/gsd/init-wizard.ts +17 -11
- package/src/resources/extensions/gsd/interrupted-session.ts +224 -0
- package/src/resources/extensions/gsd/mcp-project-config.ts +128 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +668 -2
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +380 -2
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/integration/doctor-fixlevel.test.ts +52 -1
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +2 -9
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +0 -33
- package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +169 -0
- package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +136 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +178 -17
- package/src/resources/extensions/gsd/workflow-mcp.ts +76 -23
- package/dist/web/standalone/.next/static/chunks/6502.b804e48b7919f55e.js +0 -9
- package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.d.ts +0 -13
- package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.js +0 -27
- package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.js.map +0 -1
- package/packages/pi-coding-agent/src/modes/interactive/provider-auth-setup.ts +0 -40
- package/src/resources/extensions/gsd/tests/init-bootstrap-completeness.test.ts +0 -121
- /package/dist/web/standalone/.next/static/{6_QPFhgX0DQnDhhquheRc → yh2vT27L1E6PChb_C1N_F}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{6_QPFhgX0DQnDhhquheRc → yh2vT27L1E6PChb_C1N_F}/_ssgManifest.js +0 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { mkdtempSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
8
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
7
9
|
|
|
8
10
|
import {
|
|
9
11
|
buildWorkflowMcpServers,
|
|
@@ -44,13 +46,14 @@ test("detectWorkflowMcpLaunchConfig prefers explicit env override", () => {
|
|
|
44
46
|
command: "node",
|
|
45
47
|
args: ["dist/cli.js"],
|
|
46
48
|
cwd: "/tmp/project",
|
|
47
|
-
env:
|
|
48
|
-
FOO: "bar",
|
|
49
|
-
GSD_CLI_PATH: "/tmp/gsd",
|
|
50
|
-
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
51
|
-
GSD_WORKFLOW_PROJECT_ROOT: "/tmp/project",
|
|
52
|
-
},
|
|
49
|
+
env: launch?.env,
|
|
53
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)$/);
|
|
54
57
|
});
|
|
55
58
|
|
|
56
59
|
test("buildWorkflowMcpServers mirrors explicit launch config", () => {
|
|
@@ -63,12 +66,13 @@ test("buildWorkflowMcpServers mirrors explicit launch config", () => {
|
|
|
63
66
|
"gsd-workflow": {
|
|
64
67
|
command: "node",
|
|
65
68
|
args: ["dist/cli.js"],
|
|
66
|
-
env:
|
|
67
|
-
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
68
|
-
GSD_WORKFLOW_PROJECT_ROOT: "/tmp/project",
|
|
69
|
-
},
|
|
69
|
+
env: servers?.["gsd-workflow"]?.env,
|
|
70
70
|
},
|
|
71
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)$/);
|
|
72
76
|
});
|
|
73
77
|
|
|
74
78
|
test("detectWorkflowMcpLaunchConfig resolves the bundled server from GSD_PROJECT_ROOT", () => {
|
|
@@ -88,11 +92,41 @@ test("detectWorkflowMcpLaunchConfig resolves the bundled server from GSD_PROJECT
|
|
|
88
92
|
command: process.execPath,
|
|
89
93
|
args: [cliPath],
|
|
90
94
|
cwd: repoRoot,
|
|
91
|
-
env:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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,
|
|
95
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)$/);
|
|
96
130
|
});
|
|
97
131
|
|
|
98
132
|
test("detectWorkflowMcpLaunchConfig resolves the bundled server relative to the installed GSD package", () => {
|
|
@@ -104,10 +138,137 @@ test("detectWorkflowMcpLaunchConfig resolves the bundled server relative to the
|
|
|
104
138
|
assert.equal(launch?.cwd, "/tmp/project");
|
|
105
139
|
assert.equal(launch?.env?.GSD_CLI_PATH, "/tmp/gsd-loader.js");
|
|
106
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)$/);
|
|
107
156
|
assert.equal(typeof launch?.args?.[0], "string");
|
|
108
157
|
assert.match(launch?.args?.[0] ?? "", /packages[\/\\]mcp-server[\/\\]dist[\/\\]cli\.js$/);
|
|
109
158
|
});
|
|
110
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
|
+
}
|
|
270
|
+
});
|
|
271
|
+
|
|
111
272
|
test("usesWorkflowMcpTransport matches local externalCli providers", () => {
|
|
112
273
|
assert.equal(usesWorkflowMcpTransport("externalCli", "local://claude-code"), true);
|
|
113
274
|
assert.equal(usesWorkflowMcpTransport("externalCli", "https://api.example.com"), false);
|
|
@@ -131,7 +292,7 @@ test("transport compatibility passes when required tools fit current MCP surface
|
|
|
131
292
|
assert.equal(error, null);
|
|
132
293
|
});
|
|
133
294
|
|
|
134
|
-
test("transport compatibility
|
|
295
|
+
test("transport compatibility discovers the bundled MCP server without env overrides", () => {
|
|
135
296
|
const error = getWorkflowTransportSupportError(
|
|
136
297
|
"claude-code",
|
|
137
298
|
["gsd_task_complete"],
|
|
@@ -145,7 +306,7 @@ test("transport compatibility fails cleanly when MCP server is unavailable", ()
|
|
|
145
306
|
},
|
|
146
307
|
);
|
|
147
308
|
|
|
148
|
-
assert.
|
|
309
|
+
assert.equal(error, null);
|
|
149
310
|
});
|
|
150
311
|
|
|
151
312
|
test("transport compatibility now allows auto execute-task over workflow MCP surface", () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
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
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
|
|
6
6
|
export interface WorkflowMcpLaunchConfig {
|
|
@@ -67,8 +67,32 @@ function lookupCommand(command: string, platform: NodeJS.Platform = process.plat
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
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
|
+
|
|
70
85
|
function getBundledWorkflowMcpCliPath(env: NodeJS.ProcessEnv): string | null {
|
|
71
|
-
|
|
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
|
+
}
|
|
72
96
|
|
|
73
97
|
const candidates = [
|
|
74
98
|
resolve(fileURLToPath(new URL("../../../../packages/mcp-server/dist/cli.js", import.meta.url))),
|
|
@@ -82,6 +106,52 @@ function getBundledWorkflowMcpCliPath(env: NodeJS.ProcessEnv): string | null {
|
|
|
82
106
|
return null;
|
|
83
107
|
}
|
|
84
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
|
+
|
|
85
155
|
export function detectWorkflowMcpLaunchConfig(
|
|
86
156
|
projectRoot = process.cwd(),
|
|
87
157
|
env: NodeJS.ProcessEnv = process.env,
|
|
@@ -101,12 +171,7 @@ export function detectWorkflowMcpLaunchConfig(
|
|
|
101
171
|
const resolvedWorkflowProjectRoot = resolve(workflowProjectRoot);
|
|
102
172
|
|
|
103
173
|
if (explicitCommand) {
|
|
104
|
-
const launchEnv =
|
|
105
|
-
...(explicitEnv ?? {}),
|
|
106
|
-
...(gsdCliPath ? { GSD_CLI_PATH: gsdCliPath } : {}),
|
|
107
|
-
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
108
|
-
GSD_WORKFLOW_PROJECT_ROOT: resolve(workflowProjectRoot),
|
|
109
|
-
};
|
|
174
|
+
const launchEnv = buildWorkflowLaunchEnv(resolve(workflowProjectRoot), gsdCliPath, explicitEnv);
|
|
110
175
|
return {
|
|
111
176
|
name,
|
|
112
177
|
command: explicitCommand,
|
|
@@ -123,11 +188,7 @@ export function detectWorkflowMcpLaunchConfig(
|
|
|
123
188
|
command: process.execPath,
|
|
124
189
|
args: [distCli],
|
|
125
190
|
cwd: resolvedWorkflowProjectRoot,
|
|
126
|
-
env:
|
|
127
|
-
...(gsdCliPath ? { GSD_CLI_PATH: gsdCliPath } : {}),
|
|
128
|
-
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
129
|
-
GSD_WORKFLOW_PROJECT_ROOT: resolvedWorkflowProjectRoot,
|
|
130
|
-
},
|
|
191
|
+
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
|
|
131
192
|
};
|
|
132
193
|
}
|
|
133
194
|
|
|
@@ -138,11 +199,7 @@ export function detectWorkflowMcpLaunchConfig(
|
|
|
138
199
|
command: process.execPath,
|
|
139
200
|
args: [bundledCli],
|
|
140
201
|
cwd: resolvedWorkflowProjectRoot,
|
|
141
|
-
env:
|
|
142
|
-
...(gsdCliPath ? { GSD_CLI_PATH: gsdCliPath } : {}),
|
|
143
|
-
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
144
|
-
GSD_WORKFLOW_PROJECT_ROOT: resolvedWorkflowProjectRoot,
|
|
145
|
-
},
|
|
202
|
+
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
|
|
146
203
|
};
|
|
147
204
|
}
|
|
148
205
|
|
|
@@ -151,11 +208,7 @@ export function detectWorkflowMcpLaunchConfig(
|
|
|
151
208
|
return {
|
|
152
209
|
name,
|
|
153
210
|
command: binPath,
|
|
154
|
-
env:
|
|
155
|
-
...(gsdCliPath ? { GSD_CLI_PATH: gsdCliPath } : {}),
|
|
156
|
-
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
157
|
-
GSD_WORKFLOW_PROJECT_ROOT: resolvedWorkflowProjectRoot,
|
|
158
|
-
},
|
|
211
|
+
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
|
|
159
212
|
};
|
|
160
213
|
}
|
|
161
214
|
|