gsd-pi 2.67.0-dev.a5b1d8f → 2.67.0-dev.fe39184
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 +41 -31
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +121 -8
- package/dist/resources/extensions/gsd/auto/phases.js +17 -0
- package/dist/resources/extensions/gsd/auto/session.js +6 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +12 -0
- package/dist/resources/extensions/gsd/auto-start.js +12 -0
- package/dist/resources/extensions/gsd/auto.js +27 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +11 -435
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -4
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +7 -64
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +2 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +39 -25
- package/dist/resources/extensions/gsd/commands/index.js +8 -1
- package/dist/resources/extensions/gsd/commands-mcp-status.js +43 -7
- package/dist/resources/extensions/gsd/guided-flow.js +16 -0
- package/dist/resources/extensions/gsd/init-wizard.js +37 -0
- package/dist/resources/extensions/gsd/mcp-project-config.js +83 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +508 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +18 -3
- package/dist/resources/extensions/gsd/workflow-mcp.js +261 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
- 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 +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.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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- 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-paths-manifest.json +15 -15
- 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/6502.5dcdcf1e1432e20d.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-b49b09f97429b5d0.js → webpack-42a66876b763aa26.js} +1 -1
- package/package.json +4 -2
- package/packages/mcp-server/README.md +38 -0
- package/packages/mcp-server/dist/cli.d.ts +9 -0
- package/packages/mcp-server/dist/cli.d.ts.map +1 -0
- package/packages/mcp-server/dist/cli.js +58 -0
- package/packages/mcp-server/dist/cli.js.map +1 -0
- package/packages/mcp-server/dist/index.d.ts +20 -0
- package/packages/mcp-server/dist/index.d.ts.map +1 -0
- package/packages/mcp-server/dist/index.js +14 -0
- package/packages/mcp-server/dist/index.js.map +1 -0
- package/packages/mcp-server/dist/readers/captures.d.ts +25 -0
- package/packages/mcp-server/dist/readers/captures.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/captures.js +67 -0
- package/packages/mcp-server/dist/readers/captures.js.map +1 -0
- package/packages/mcp-server/dist/readers/doctor-lite.d.ts +20 -0
- package/packages/mcp-server/dist/readers/doctor-lite.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/doctor-lite.js +173 -0
- package/packages/mcp-server/dist/readers/doctor-lite.js.map +1 -0
- package/packages/mcp-server/dist/readers/index.d.ts +14 -0
- package/packages/mcp-server/dist/readers/index.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/index.js +10 -0
- package/packages/mcp-server/dist/readers/index.js.map +1 -0
- package/packages/mcp-server/dist/readers/knowledge.d.ts +18 -0
- package/packages/mcp-server/dist/readers/knowledge.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/knowledge.js +82 -0
- package/packages/mcp-server/dist/readers/knowledge.js.map +1 -0
- package/packages/mcp-server/dist/readers/metrics.d.ts +32 -0
- package/packages/mcp-server/dist/readers/metrics.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/metrics.js +74 -0
- package/packages/mcp-server/dist/readers/metrics.js.map +1 -0
- package/packages/mcp-server/dist/readers/paths.d.ts +42 -0
- package/packages/mcp-server/dist/readers/paths.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/paths.js +199 -0
- package/packages/mcp-server/dist/readers/paths.js.map +1 -0
- package/packages/mcp-server/dist/readers/roadmap.d.ts +26 -0
- package/packages/mcp-server/dist/readers/roadmap.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/roadmap.js +194 -0
- package/packages/mcp-server/dist/readers/roadmap.js.map +1 -0
- package/packages/mcp-server/dist/readers/state.d.ts +43 -0
- package/packages/mcp-server/dist/readers/state.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/state.js +184 -0
- package/packages/mcp-server/dist/readers/state.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +28 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -0
- package/packages/mcp-server/dist/server.js +319 -0
- package/packages/mcp-server/dist/server.js.map +1 -0
- package/packages/mcp-server/dist/session-manager.d.ts +54 -0
- package/packages/mcp-server/dist/session-manager.d.ts.map +1 -0
- package/packages/mcp-server/dist/session-manager.js +284 -0
- package/packages/mcp-server/dist/session-manager.js.map +1 -0
- package/packages/mcp-server/dist/types.d.ts +61 -0
- package/packages/mcp-server/dist/types.d.ts.map +1 -0
- package/packages/mcp-server/dist/types.js +11 -0
- package/packages/mcp-server/dist/types.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts +9 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.js +532 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -0
- package/packages/mcp-server/src/server.ts +6 -2
- package/packages/mcp-server/src/workflow-tools.test.ts +976 -0
- package/packages/mcp-server/src/workflow-tools.ts +997 -0
- package/packages/mcp-server/tsconfig.json +1 -1
- 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/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/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/rpc-client/dist/index.d.ts +10 -0
- package/packages/rpc-client/dist/index.d.ts.map +1 -0
- package/packages/rpc-client/dist/index.js +9 -0
- package/packages/rpc-client/dist/index.js.map +1 -0
- package/packages/rpc-client/dist/jsonl.d.ts +17 -0
- package/packages/rpc-client/dist/jsonl.d.ts.map +1 -0
- package/packages/rpc-client/dist/jsonl.js +54 -0
- package/packages/rpc-client/dist/jsonl.js.map +1 -0
- package/packages/rpc-client/dist/rpc-client.d.ts +259 -0
- package/packages/rpc-client/dist/rpc-client.d.ts.map +1 -0
- package/packages/rpc-client/dist/rpc-client.js +541 -0
- package/packages/rpc-client/dist/rpc-client.js.map +1 -0
- package/packages/rpc-client/dist/rpc-client.test.d.ts +2 -0
- package/packages/rpc-client/dist/rpc-client.test.d.ts.map +1 -0
- package/packages/rpc-client/dist/rpc-client.test.js +477 -0
- package/packages/rpc-client/dist/rpc-client.test.js.map +1 -0
- package/packages/rpc-client/dist/rpc-types.d.ts +566 -0
- package/packages/rpc-client/dist/rpc-types.d.ts.map +1 -0
- package/packages/rpc-client/dist/rpc-types.js +12 -0
- package/packages/rpc-client/dist/rpc-types.js.map +1 -0
- package/scripts/ensure-workspace-builds.cjs +2 -0
- package/scripts/link-workspace-packages.cjs +21 -14
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +157 -8
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +182 -0
- package/src/resources/extensions/gsd/auto/phases.ts +25 -0
- package/src/resources/extensions/gsd/auto/session.ts +6 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +20 -0
- package/src/resources/extensions/gsd/auto-start.ts +15 -1
- package/src/resources/extensions/gsd/auto.ts +29 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +22 -435
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -5
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +7 -72
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +122 -6
- package/src/resources/extensions/gsd/commands/catalog.ts +2 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +53 -26
- package/src/resources/extensions/gsd/commands/index.ts +7 -1
- package/src/resources/extensions/gsd/commands-mcp-status.ts +53 -7
- package/src/resources/extensions/gsd/guided-flow.ts +24 -0
- package/src/resources/extensions/gsd/init-wizard.ts +40 -0
- package/src/resources/extensions/gsd/mcp-project-config.ts +128 -0
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/core-overlay-fallback.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +66 -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/workflow-logger.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +500 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +625 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +629 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +19 -3
- package/src/resources/extensions/gsd/workflow-mcp.ts +320 -0
- package/dist/web/standalone/.next/static/chunks/6502.b804e48b7919f55e.js +0 -9
- /package/dist/web/standalone/.next/static/{NllX5BEOLdTXS9ypf1i3i → gbSATDX4Jt2ufxzUr5nYm}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{NllX5BEOLdTXS9ypf1i3i → gbSATDX4Jt2ufxzUr5nYm}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
8
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
buildWorkflowMcpServers,
|
|
12
|
+
detectWorkflowMcpLaunchConfig,
|
|
13
|
+
getWorkflowTransportSupportError,
|
|
14
|
+
getRequiredWorkflowToolsForAutoUnit,
|
|
15
|
+
getRequiredWorkflowToolsForGuidedUnit,
|
|
16
|
+
usesWorkflowMcpTransport,
|
|
17
|
+
} from "../workflow-mcp.ts";
|
|
18
|
+
|
|
19
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const gsdDir = join(__dirname, "..");
|
|
21
|
+
|
|
22
|
+
function readSrc(file: string): string {
|
|
23
|
+
return readFileSync(join(gsdDir, file), "utf-8");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
test("guided execute-task requires canonical task completion tool", () => {
|
|
27
|
+
assert.deepEqual(getRequiredWorkflowToolsForGuidedUnit("execute-task"), ["gsd_task_complete"]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("auto execute-task requires legacy completion alias until prompt contract is aligned", () => {
|
|
31
|
+
assert.deepEqual(getRequiredWorkflowToolsForAutoUnit("execute-task"), ["gsd_complete_task"]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("detectWorkflowMcpLaunchConfig prefers explicit env override", () => {
|
|
35
|
+
const launch = detectWorkflowMcpLaunchConfig("/tmp/project", {
|
|
36
|
+
GSD_WORKFLOW_MCP_NAME: "workflow-tools",
|
|
37
|
+
GSD_WORKFLOW_MCP_COMMAND: "node",
|
|
38
|
+
GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["dist/cli.js"]),
|
|
39
|
+
GSD_WORKFLOW_MCP_ENV: JSON.stringify({ FOO: "bar" }),
|
|
40
|
+
GSD_WORKFLOW_MCP_CWD: "/tmp/project",
|
|
41
|
+
GSD_CLI_PATH: "/tmp/gsd",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
assert.deepEqual(launch, {
|
|
45
|
+
name: "workflow-tools",
|
|
46
|
+
command: "node",
|
|
47
|
+
args: ["dist/cli.js"],
|
|
48
|
+
cwd: "/tmp/project",
|
|
49
|
+
env: launch?.env,
|
|
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)$/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("buildWorkflowMcpServers mirrors explicit launch config", () => {
|
|
60
|
+
const servers = buildWorkflowMcpServers("/tmp/project", {
|
|
61
|
+
GSD_WORKFLOW_MCP_COMMAND: "node",
|
|
62
|
+
GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["dist/cli.js"]),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
assert.deepEqual(servers, {
|
|
66
|
+
"gsd-workflow": {
|
|
67
|
+
command: "node",
|
|
68
|
+
args: ["dist/cli.js"],
|
|
69
|
+
env: servers?.["gsd-workflow"]?.env,
|
|
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
|
+
}
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("usesWorkflowMcpTransport matches local externalCli providers", () => {
|
|
273
|
+
assert.equal(usesWorkflowMcpTransport("externalCli", "local://claude-code"), true);
|
|
274
|
+
assert.equal(usesWorkflowMcpTransport("externalCli", "https://api.example.com"), false);
|
|
275
|
+
assert.equal(usesWorkflowMcpTransport("oauth", "local://custom"), false);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test("transport compatibility passes when required tools fit current MCP surface", () => {
|
|
279
|
+
const error = getWorkflowTransportSupportError(
|
|
280
|
+
"claude-code",
|
|
281
|
+
["gsd_task_complete"],
|
|
282
|
+
{
|
|
283
|
+
projectRoot: "/tmp/project",
|
|
284
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
285
|
+
surface: "guided flow",
|
|
286
|
+
unitType: "execute-task",
|
|
287
|
+
authMode: "externalCli",
|
|
288
|
+
baseUrl: "local://claude-code",
|
|
289
|
+
},
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
assert.equal(error, null);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test("transport compatibility discovers the bundled MCP server without env overrides", () => {
|
|
296
|
+
const error = getWorkflowTransportSupportError(
|
|
297
|
+
"claude-code",
|
|
298
|
+
["gsd_task_complete"],
|
|
299
|
+
{
|
|
300
|
+
projectRoot: "/tmp/project",
|
|
301
|
+
env: {},
|
|
302
|
+
surface: "auto-mode",
|
|
303
|
+
unitType: "execute-task",
|
|
304
|
+
authMode: "externalCli",
|
|
305
|
+
baseUrl: "local://claude-code",
|
|
306
|
+
},
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
assert.equal(error, null);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
test("transport compatibility now allows auto execute-task over workflow MCP surface", () => {
|
|
313
|
+
const error = getWorkflowTransportSupportError(
|
|
314
|
+
"claude-code",
|
|
315
|
+
["gsd_complete_task"],
|
|
316
|
+
{
|
|
317
|
+
projectRoot: "/tmp/project",
|
|
318
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
319
|
+
surface: "auto-mode",
|
|
320
|
+
unitType: "execute-task",
|
|
321
|
+
authMode: "externalCli",
|
|
322
|
+
baseUrl: "local://claude-code",
|
|
323
|
+
},
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
assert.equal(error, null);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
test("transport compatibility ignores API-backed providers", () => {
|
|
330
|
+
const error = getWorkflowTransportSupportError(
|
|
331
|
+
"openai-codex",
|
|
332
|
+
["gsd_plan_slice"],
|
|
333
|
+
{
|
|
334
|
+
projectRoot: "/tmp/project",
|
|
335
|
+
env: {},
|
|
336
|
+
surface: "auto-mode",
|
|
337
|
+
unitType: "plan-slice",
|
|
338
|
+
authMode: "oauth",
|
|
339
|
+
baseUrl: "https://api.openai.com",
|
|
340
|
+
},
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
assert.equal(error, null);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
test("transport compatibility now allows plan-slice over workflow MCP surface", () => {
|
|
347
|
+
const error = getWorkflowTransportSupportError(
|
|
348
|
+
"claude-code",
|
|
349
|
+
["gsd_plan_slice"],
|
|
350
|
+
{
|
|
351
|
+
projectRoot: "/tmp/project",
|
|
352
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
353
|
+
surface: "auto-mode",
|
|
354
|
+
unitType: "plan-slice",
|
|
355
|
+
authMode: "externalCli",
|
|
356
|
+
baseUrl: "local://claude-code",
|
|
357
|
+
},
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
assert.equal(error, null);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
test("transport compatibility now allows complete-slice over workflow MCP surface", () => {
|
|
364
|
+
const error = getWorkflowTransportSupportError(
|
|
365
|
+
"claude-code",
|
|
366
|
+
["gsd_complete_slice"],
|
|
367
|
+
{
|
|
368
|
+
projectRoot: "/tmp/project",
|
|
369
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
370
|
+
surface: "auto-mode",
|
|
371
|
+
unitType: "complete-slice",
|
|
372
|
+
authMode: "externalCli",
|
|
373
|
+
baseUrl: "local://claude-code",
|
|
374
|
+
},
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
assert.equal(error, null);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
test("transport compatibility now allows reassess-roadmap over workflow MCP surface", () => {
|
|
381
|
+
const error = getWorkflowTransportSupportError(
|
|
382
|
+
"claude-code",
|
|
383
|
+
["gsd_milestone_status", "gsd_reassess_roadmap"],
|
|
384
|
+
{
|
|
385
|
+
projectRoot: "/tmp/project",
|
|
386
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
387
|
+
surface: "auto-mode",
|
|
388
|
+
unitType: "reassess-roadmap",
|
|
389
|
+
authMode: "externalCli",
|
|
390
|
+
baseUrl: "local://claude-code",
|
|
391
|
+
},
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
assert.equal(error, null);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test("transport compatibility now allows gate-evaluate over workflow MCP surface", () => {
|
|
398
|
+
const error = getWorkflowTransportSupportError(
|
|
399
|
+
"claude-code",
|
|
400
|
+
["gsd_save_gate_result"],
|
|
401
|
+
{
|
|
402
|
+
projectRoot: "/tmp/project",
|
|
403
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
404
|
+
surface: "auto-mode",
|
|
405
|
+
unitType: "gate-evaluate",
|
|
406
|
+
authMode: "externalCli",
|
|
407
|
+
baseUrl: "local://claude-code",
|
|
408
|
+
},
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
assert.equal(error, null);
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
test("transport compatibility now allows validate-milestone over workflow MCP surface", () => {
|
|
415
|
+
const error = getWorkflowTransportSupportError(
|
|
416
|
+
"claude-code",
|
|
417
|
+
["gsd_milestone_status", "gsd_validate_milestone"],
|
|
418
|
+
{
|
|
419
|
+
projectRoot: "/tmp/project",
|
|
420
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
421
|
+
surface: "auto-mode",
|
|
422
|
+
unitType: "validate-milestone",
|
|
423
|
+
authMode: "externalCli",
|
|
424
|
+
baseUrl: "local://claude-code",
|
|
425
|
+
},
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
assert.equal(error, null);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
test("transport compatibility now allows complete-milestone over workflow MCP surface", () => {
|
|
432
|
+
const error = getWorkflowTransportSupportError(
|
|
433
|
+
"claude-code",
|
|
434
|
+
["gsd_milestone_status", "gsd_complete_milestone"],
|
|
435
|
+
{
|
|
436
|
+
projectRoot: "/tmp/project",
|
|
437
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
438
|
+
surface: "auto-mode",
|
|
439
|
+
unitType: "complete-milestone",
|
|
440
|
+
authMode: "externalCli",
|
|
441
|
+
baseUrl: "local://claude-code",
|
|
442
|
+
},
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
assert.equal(error, null);
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
test("transport compatibility now allows replan-slice over workflow MCP surface", () => {
|
|
449
|
+
const error = getWorkflowTransportSupportError(
|
|
450
|
+
"claude-code",
|
|
451
|
+
["gsd_replan_slice"],
|
|
452
|
+
{
|
|
453
|
+
projectRoot: "/tmp/project",
|
|
454
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
455
|
+
surface: "auto-mode",
|
|
456
|
+
unitType: "replan-slice",
|
|
457
|
+
authMode: "externalCli",
|
|
458
|
+
baseUrl: "local://claude-code",
|
|
459
|
+
},
|
|
460
|
+
);
|
|
461
|
+
|
|
462
|
+
assert.equal(error, null);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
test("transport compatibility still blocks units whose MCP tools are not exposed", () => {
|
|
466
|
+
const error = getWorkflowTransportSupportError(
|
|
467
|
+
"claude-code",
|
|
468
|
+
["gsd_skip_slice"],
|
|
469
|
+
{
|
|
470
|
+
projectRoot: "/tmp/project",
|
|
471
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
472
|
+
surface: "auto-mode",
|
|
473
|
+
unitType: "skip-slice",
|
|
474
|
+
authMode: "externalCli",
|
|
475
|
+
baseUrl: "local://claude-code",
|
|
476
|
+
},
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
assert.match(error ?? "", /requires gsd_skip_slice/);
|
|
480
|
+
assert.match(error ?? "", /currently exposes only/);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
test("guided-flow source enforces workflow compatibility preflight", () => {
|
|
484
|
+
const src = readSrc("guided-flow.ts");
|
|
485
|
+
assert.match(src, /getRequiredWorkflowToolsForGuidedUnit/);
|
|
486
|
+
assert.match(src, /getWorkflowTransportSupportError/);
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
test("auto direct dispatch source enforces workflow compatibility preflight", () => {
|
|
490
|
+
const src = readSrc("auto-direct-dispatch.ts");
|
|
491
|
+
assert.match(src, /getRequiredWorkflowToolsForAutoUnit/);
|
|
492
|
+
assert.match(src, /getWorkflowTransportSupportError/);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
test("auto phases source enforces workflow compatibility preflight", () => {
|
|
496
|
+
const src = readSrc(join("auto", "phases.ts"));
|
|
497
|
+
assert.match(src, /getRequiredWorkflowToolsForAutoUnit/);
|
|
498
|
+
assert.match(src, /getWorkflowTransportSupportError/);
|
|
499
|
+
assert.match(src, /workflow-capability/);
|
|
500
|
+
});
|