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.
- 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 +10 -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 +121 -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/gsd-db.js +11 -0
- 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/state.js +7 -2
- package/dist/resources/extensions/gsd/workflow-mcp.js +90 -19
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
- 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 +14 -14
- 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 +4 -2
- 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/workflow-tools.ts +13 -2
- 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/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/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 +190 -93
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +89 -116
- package/src/resources/extensions/gsd/auto/session.ts +10 -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 +133 -64
- 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/gsd-db.ts +12 -0
- 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/state.ts +7 -1
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +29 -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/gsd-db.test.ts +12 -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 +212 -13
- package/src/resources/extensions/gsd/workflow-mcp.ts +106 -19
- 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/{xR6qurkuYSvyjBjRyJLxG → WMDT_0C0XDkBKtsAI_AX4}/_buildManifest.js +0 -0
- /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
|
|
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.
|
|
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(
|
|
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:
|
|
107
|
-
env:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
|