gsd-pi 2.67.0-dev.1cd1e0f → 2.67.0-dev.2142d3e
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/dist/resources/extensions/claude-code-cli/stream-adapter.js +3 -0
- package/dist/resources/extensions/gsd/auto/phases.js +17 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +12 -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/handlers/core.js +38 -24
- package/dist/resources/extensions/gsd/commands/index.js +8 -1
- package/dist/resources/extensions/gsd/guided-flow.js +16 -0
- package/dist/resources/extensions/gsd/init-wizard.js +34 -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 +190 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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 +10 -10
- package/dist/web/standalone/.next/server/middleware-build-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/package.json +1 -1
- package/packages/mcp-server/README.md +38 -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 +986 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +3 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +121 -0
- package/src/resources/extensions/gsd/auto/phases.ts +25 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +20 -0
- 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/handlers/core.ts +52 -25
- package/src/resources/extensions/gsd/commands/index.ts +7 -1
- package/src/resources/extensions/gsd/guided-flow.ts +24 -0
- package/src/resources/extensions/gsd/init-wizard.ts +34 -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/init-bootstrap-completeness.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +301 -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 +233 -0
- /package/dist/web/standalone/.next/static/{PHqEommYRR8CRn3i84CGM → xR6qurkuYSvyjBjRyJLxG}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{PHqEommYRR8CRn3i84CGM → xR6qurkuYSvyjBjRyJLxG}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSD Init Wizard — Bootstrap completeness regression tests
|
|
3
|
+
*
|
|
4
|
+
* Regression test for #3880 — fresh install never creates gsd.db.
|
|
5
|
+
*
|
|
6
|
+
* The init wizard must create all artifacts needed for full-capability
|
|
7
|
+
* mode: gsd.db (via ensureDbOpen), runtime/ directory, and STATE.md
|
|
8
|
+
* (via deriveState + buildStateMarkdown). Without these, GSD enters
|
|
9
|
+
* degraded markdown-only mode on every fresh install.
|
|
10
|
+
*
|
|
11
|
+
* These are structural tests that verify the init-wizard.ts source
|
|
12
|
+
* contains the required calls in the correct order.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { describe, test } from "node:test";
|
|
16
|
+
import assert from "node:assert/strict";
|
|
17
|
+
import { readFileSync } from "node:fs";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
import { dirname, join } from "node:path";
|
|
20
|
+
|
|
21
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
22
|
+
const __dirname = dirname(__filename);
|
|
23
|
+
|
|
24
|
+
const wizardSrc = readFileSync(
|
|
25
|
+
join(__dirname, "..", "init-wizard.ts"),
|
|
26
|
+
"utf-8",
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
describe("init-wizard bootstrap completeness (#3880)", () => {
|
|
30
|
+
// ── Gap 1: gsd.db must be created during init ─────────────────────────
|
|
31
|
+
|
|
32
|
+
test("bootstrapGsdDirectory is followed by ensureDbOpen", () => {
|
|
33
|
+
const bootstrapIdx = wizardSrc.indexOf("bootstrapGsdDirectory(basePath");
|
|
34
|
+
const ensureDbIdx = wizardSrc.indexOf("ensureDbOpen(basePath)");
|
|
35
|
+
assert.ok(bootstrapIdx > -1, "bootstrapGsdDirectory call should exist");
|
|
36
|
+
assert.ok(ensureDbIdx > -1, "ensureDbOpen(basePath) call should exist");
|
|
37
|
+
assert.ok(
|
|
38
|
+
ensureDbIdx > bootstrapIdx,
|
|
39
|
+
"ensureDbOpen must appear after bootstrapGsdDirectory so .gsd/ exists first",
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("ensureDbOpen is imported from dynamic-tools", () => {
|
|
44
|
+
assert.match(
|
|
45
|
+
wizardSrc,
|
|
46
|
+
/import.*dynamic-tools/,
|
|
47
|
+
"init-wizard should import from dynamic-tools for ensureDbOpen",
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// ── Gap 2: runtime/ directory must be created during init ──────────────
|
|
52
|
+
|
|
53
|
+
test("bootstrapGsdDirectory creates runtime/ directory", () => {
|
|
54
|
+
// Find the bootstrapGsdDirectory function body
|
|
55
|
+
const fnStart = wizardSrc.indexOf("function bootstrapGsdDirectory(");
|
|
56
|
+
assert.ok(fnStart > -1, "bootstrapGsdDirectory function should exist");
|
|
57
|
+
|
|
58
|
+
// Find the next function definition to bound the search
|
|
59
|
+
const fnBody = wizardSrc.slice(fnStart, wizardSrc.indexOf("\nfunction ", fnStart + 1));
|
|
60
|
+
|
|
61
|
+
assert.match(
|
|
62
|
+
fnBody,
|
|
63
|
+
/mkdirSync\(.*"runtime"/,
|
|
64
|
+
'bootstrapGsdDirectory should create "runtime" directory',
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// ── Gap 3: STATE.md must be written during init ────────────────────────
|
|
69
|
+
|
|
70
|
+
test("showProjectInit generates STATE.md after bootstrap", () => {
|
|
71
|
+
const bootstrapIdx = wizardSrc.indexOf("bootstrapGsdDirectory(basePath");
|
|
72
|
+
const deriveIdx = wizardSrc.indexOf("deriveState(basePath)");
|
|
73
|
+
const stateIdx = wizardSrc.indexOf("buildStateMarkdown(state)");
|
|
74
|
+
const saveIdx = wizardSrc.indexOf('resolveGsdRootFile(basePath, "STATE")');
|
|
75
|
+
|
|
76
|
+
assert.ok(deriveIdx > -1, "deriveState call should exist in init-wizard");
|
|
77
|
+
assert.ok(stateIdx > -1, "buildStateMarkdown call should exist in init-wizard");
|
|
78
|
+
assert.ok(saveIdx > -1, "resolveGsdRootFile STATE call should exist in init-wizard");
|
|
79
|
+
assert.ok(
|
|
80
|
+
deriveIdx > bootstrapIdx,
|
|
81
|
+
"deriveState must appear after bootstrapGsdDirectory",
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// ── Ordering: DB must be open before deriveState ───────────────────────
|
|
86
|
+
|
|
87
|
+
test("ensureDbOpen appears before deriveState", () => {
|
|
88
|
+
const ensureDbIdx = wizardSrc.indexOf("ensureDbOpen(basePath)");
|
|
89
|
+
const deriveIdx = wizardSrc.indexOf("deriveState(basePath)");
|
|
90
|
+
assert.ok(ensureDbIdx > -1, "ensureDbOpen should exist");
|
|
91
|
+
assert.ok(deriveIdx > -1, "deriveState should exist");
|
|
92
|
+
assert.ok(
|
|
93
|
+
ensureDbIdx < deriveIdx,
|
|
94
|
+
"ensureDbOpen must appear before deriveState so DB is ready for state derivation",
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ── Failure visibility: user must be warned on partial bootstrap ───────
|
|
99
|
+
|
|
100
|
+
test("ensureDbOpen failure surfaces a warning to the user", () => {
|
|
101
|
+
assert.match(
|
|
102
|
+
wizardSrc,
|
|
103
|
+
/if\s*\(\s*!dbReady\s*\)/,
|
|
104
|
+
"init-wizard should check dbReady and warn the user on failure",
|
|
105
|
+
);
|
|
106
|
+
// The warning must reference degraded mode so the user knows what happened
|
|
107
|
+
assert.match(
|
|
108
|
+
wizardSrc,
|
|
109
|
+
/degraded mode/,
|
|
110
|
+
"DB failure warning should mention degraded mode",
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("STATE.md failure surfaces a warning to the user", () => {
|
|
115
|
+
assert.match(
|
|
116
|
+
wizardSrc,
|
|
117
|
+
/if\s*\(\s*!stateReady\s*\)/,
|
|
118
|
+
"init-wizard should check stateReady and warn the user on failure",
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
summarizeLogs,
|
|
19
19
|
formatForNotification,
|
|
20
20
|
setLogBasePath,
|
|
21
|
+
setStderrLoggingEnabled,
|
|
21
22
|
_resetLogs,
|
|
22
23
|
} from "../workflow-logger.ts";
|
|
23
24
|
|
|
@@ -375,5 +376,20 @@ describe("workflow-logger", () => {
|
|
|
375
376
|
logError("tool", "failed", { cmd: "complete_task" });
|
|
376
377
|
assert.ok(written[0].includes('"cmd":"complete_task"'));
|
|
377
378
|
});
|
|
379
|
+
|
|
380
|
+
test("suppresses stderr when disabled", (t) => {
|
|
381
|
+
const written: string[] = [];
|
|
382
|
+
const orig = process.stderr.write.bind(process.stderr);
|
|
383
|
+
const previous = setStderrLoggingEnabled(false);
|
|
384
|
+
// @ts-ignore — patching for test
|
|
385
|
+
process.stderr.write = (chunk: string) => { written.push(chunk); return true; };
|
|
386
|
+
t.after(() => {
|
|
387
|
+
process.stderr.write = orig;
|
|
388
|
+
setStderrLoggingEnabled(previous);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
logWarning("engine", "hidden warning");
|
|
392
|
+
assert.deepEqual(written, []);
|
|
393
|
+
});
|
|
378
394
|
});
|
|
379
395
|
});
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
buildWorkflowMcpServers,
|
|
9
|
+
detectWorkflowMcpLaunchConfig,
|
|
10
|
+
getWorkflowTransportSupportError,
|
|
11
|
+
getRequiredWorkflowToolsForAutoUnit,
|
|
12
|
+
getRequiredWorkflowToolsForGuidedUnit,
|
|
13
|
+
usesWorkflowMcpTransport,
|
|
14
|
+
} from "../workflow-mcp.ts";
|
|
15
|
+
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const gsdDir = join(__dirname, "..");
|
|
18
|
+
|
|
19
|
+
function readSrc(file: string): string {
|
|
20
|
+
return readFileSync(join(gsdDir, file), "utf-8");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
test("guided execute-task requires canonical task completion tool", () => {
|
|
24
|
+
assert.deepEqual(getRequiredWorkflowToolsForGuidedUnit("execute-task"), ["gsd_task_complete"]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("auto execute-task requires legacy completion alias until prompt contract is aligned", () => {
|
|
28
|
+
assert.deepEqual(getRequiredWorkflowToolsForAutoUnit("execute-task"), ["gsd_complete_task"]);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("detectWorkflowMcpLaunchConfig prefers explicit env override", () => {
|
|
32
|
+
const launch = detectWorkflowMcpLaunchConfig("/tmp/project", {
|
|
33
|
+
GSD_WORKFLOW_MCP_NAME: "workflow-tools",
|
|
34
|
+
GSD_WORKFLOW_MCP_COMMAND: "node",
|
|
35
|
+
GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["dist/cli.js"]),
|
|
36
|
+
GSD_WORKFLOW_MCP_ENV: JSON.stringify({ FOO: "bar" }),
|
|
37
|
+
GSD_WORKFLOW_MCP_CWD: "/tmp/project",
|
|
38
|
+
GSD_CLI_PATH: "/tmp/gsd",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
assert.deepEqual(launch, {
|
|
42
|
+
name: "workflow-tools",
|
|
43
|
+
command: "node",
|
|
44
|
+
args: ["dist/cli.js"],
|
|
45
|
+
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
|
+
},
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("buildWorkflowMcpServers mirrors explicit launch config", () => {
|
|
56
|
+
const servers = buildWorkflowMcpServers("/tmp/project", {
|
|
57
|
+
GSD_WORKFLOW_MCP_COMMAND: "node",
|
|
58
|
+
GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["dist/cli.js"]),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
assert.deepEqual(servers, {
|
|
62
|
+
"gsd-workflow": {
|
|
63
|
+
command: "node",
|
|
64
|
+
args: ["dist/cli.js"],
|
|
65
|
+
env: {
|
|
66
|
+
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
67
|
+
GSD_WORKFLOW_PROJECT_ROOT: "/tmp/project",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("usesWorkflowMcpTransport matches local externalCli providers", () => {
|
|
74
|
+
assert.equal(usesWorkflowMcpTransport("externalCli", "local://claude-code"), true);
|
|
75
|
+
assert.equal(usesWorkflowMcpTransport("externalCli", "https://api.example.com"), false);
|
|
76
|
+
assert.equal(usesWorkflowMcpTransport("oauth", "local://custom"), false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("transport compatibility passes when required tools fit current MCP surface", () => {
|
|
80
|
+
const error = getWorkflowTransportSupportError(
|
|
81
|
+
"claude-code",
|
|
82
|
+
["gsd_task_complete"],
|
|
83
|
+
{
|
|
84
|
+
projectRoot: "/tmp/project",
|
|
85
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
86
|
+
surface: "guided flow",
|
|
87
|
+
unitType: "execute-task",
|
|
88
|
+
authMode: "externalCli",
|
|
89
|
+
baseUrl: "local://claude-code",
|
|
90
|
+
},
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
assert.equal(error, null);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("transport compatibility fails cleanly when MCP server is unavailable", () => {
|
|
97
|
+
const error = getWorkflowTransportSupportError(
|
|
98
|
+
"claude-code",
|
|
99
|
+
["gsd_task_complete"],
|
|
100
|
+
{
|
|
101
|
+
projectRoot: "/tmp/project",
|
|
102
|
+
env: {},
|
|
103
|
+
surface: "auto-mode",
|
|
104
|
+
unitType: "execute-task",
|
|
105
|
+
authMode: "externalCli",
|
|
106
|
+
baseUrl: "local://claude-code",
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
assert.match(error ?? "", /workflow MCP server is not configured or discoverable/);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("transport compatibility now allows auto execute-task over workflow MCP surface", () => {
|
|
114
|
+
const error = getWorkflowTransportSupportError(
|
|
115
|
+
"claude-code",
|
|
116
|
+
["gsd_complete_task"],
|
|
117
|
+
{
|
|
118
|
+
projectRoot: "/tmp/project",
|
|
119
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
120
|
+
surface: "auto-mode",
|
|
121
|
+
unitType: "execute-task",
|
|
122
|
+
authMode: "externalCli",
|
|
123
|
+
baseUrl: "local://claude-code",
|
|
124
|
+
},
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
assert.equal(error, null);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("transport compatibility ignores API-backed providers", () => {
|
|
131
|
+
const error = getWorkflowTransportSupportError(
|
|
132
|
+
"openai-codex",
|
|
133
|
+
["gsd_plan_slice"],
|
|
134
|
+
{
|
|
135
|
+
projectRoot: "/tmp/project",
|
|
136
|
+
env: {},
|
|
137
|
+
surface: "auto-mode",
|
|
138
|
+
unitType: "plan-slice",
|
|
139
|
+
authMode: "oauth",
|
|
140
|
+
baseUrl: "https://api.openai.com",
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
assert.equal(error, null);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("transport compatibility now allows plan-slice over workflow MCP surface", () => {
|
|
148
|
+
const error = getWorkflowTransportSupportError(
|
|
149
|
+
"claude-code",
|
|
150
|
+
["gsd_plan_slice"],
|
|
151
|
+
{
|
|
152
|
+
projectRoot: "/tmp/project",
|
|
153
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
154
|
+
surface: "auto-mode",
|
|
155
|
+
unitType: "plan-slice",
|
|
156
|
+
authMode: "externalCli",
|
|
157
|
+
baseUrl: "local://claude-code",
|
|
158
|
+
},
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
assert.equal(error, null);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("transport compatibility now allows complete-slice over workflow MCP surface", () => {
|
|
165
|
+
const error = getWorkflowTransportSupportError(
|
|
166
|
+
"claude-code",
|
|
167
|
+
["gsd_complete_slice"],
|
|
168
|
+
{
|
|
169
|
+
projectRoot: "/tmp/project",
|
|
170
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
171
|
+
surface: "auto-mode",
|
|
172
|
+
unitType: "complete-slice",
|
|
173
|
+
authMode: "externalCli",
|
|
174
|
+
baseUrl: "local://claude-code",
|
|
175
|
+
},
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
assert.equal(error, null);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("transport compatibility now allows reassess-roadmap over workflow MCP surface", () => {
|
|
182
|
+
const error = getWorkflowTransportSupportError(
|
|
183
|
+
"claude-code",
|
|
184
|
+
["gsd_milestone_status", "gsd_reassess_roadmap"],
|
|
185
|
+
{
|
|
186
|
+
projectRoot: "/tmp/project",
|
|
187
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
188
|
+
surface: "auto-mode",
|
|
189
|
+
unitType: "reassess-roadmap",
|
|
190
|
+
authMode: "externalCli",
|
|
191
|
+
baseUrl: "local://claude-code",
|
|
192
|
+
},
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
assert.equal(error, null);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("transport compatibility now allows gate-evaluate over workflow MCP surface", () => {
|
|
199
|
+
const error = getWorkflowTransportSupportError(
|
|
200
|
+
"claude-code",
|
|
201
|
+
["gsd_save_gate_result"],
|
|
202
|
+
{
|
|
203
|
+
projectRoot: "/tmp/project",
|
|
204
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
205
|
+
surface: "auto-mode",
|
|
206
|
+
unitType: "gate-evaluate",
|
|
207
|
+
authMode: "externalCli",
|
|
208
|
+
baseUrl: "local://claude-code",
|
|
209
|
+
},
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
assert.equal(error, null);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test("transport compatibility now allows validate-milestone over workflow MCP surface", () => {
|
|
216
|
+
const error = getWorkflowTransportSupportError(
|
|
217
|
+
"claude-code",
|
|
218
|
+
["gsd_milestone_status", "gsd_validate_milestone"],
|
|
219
|
+
{
|
|
220
|
+
projectRoot: "/tmp/project",
|
|
221
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
222
|
+
surface: "auto-mode",
|
|
223
|
+
unitType: "validate-milestone",
|
|
224
|
+
authMode: "externalCli",
|
|
225
|
+
baseUrl: "local://claude-code",
|
|
226
|
+
},
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
assert.equal(error, null);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test("transport compatibility now allows complete-milestone over workflow MCP surface", () => {
|
|
233
|
+
const error = getWorkflowTransportSupportError(
|
|
234
|
+
"claude-code",
|
|
235
|
+
["gsd_milestone_status", "gsd_complete_milestone"],
|
|
236
|
+
{
|
|
237
|
+
projectRoot: "/tmp/project",
|
|
238
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
239
|
+
surface: "auto-mode",
|
|
240
|
+
unitType: "complete-milestone",
|
|
241
|
+
authMode: "externalCli",
|
|
242
|
+
baseUrl: "local://claude-code",
|
|
243
|
+
},
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
assert.equal(error, null);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test("transport compatibility now allows replan-slice over workflow MCP surface", () => {
|
|
250
|
+
const error = getWorkflowTransportSupportError(
|
|
251
|
+
"claude-code",
|
|
252
|
+
["gsd_replan_slice"],
|
|
253
|
+
{
|
|
254
|
+
projectRoot: "/tmp/project",
|
|
255
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
256
|
+
surface: "auto-mode",
|
|
257
|
+
unitType: "replan-slice",
|
|
258
|
+
authMode: "externalCli",
|
|
259
|
+
baseUrl: "local://claude-code",
|
|
260
|
+
},
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
assert.equal(error, null);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
test("transport compatibility still blocks units whose MCP tools are not exposed", () => {
|
|
267
|
+
const error = getWorkflowTransportSupportError(
|
|
268
|
+
"claude-code",
|
|
269
|
+
["gsd_skip_slice"],
|
|
270
|
+
{
|
|
271
|
+
projectRoot: "/tmp/project",
|
|
272
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
273
|
+
surface: "auto-mode",
|
|
274
|
+
unitType: "skip-slice",
|
|
275
|
+
authMode: "externalCli",
|
|
276
|
+
baseUrl: "local://claude-code",
|
|
277
|
+
},
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
assert.match(error ?? "", /requires gsd_skip_slice/);
|
|
281
|
+
assert.match(error ?? "", /currently exposes only/);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("guided-flow source enforces workflow compatibility preflight", () => {
|
|
285
|
+
const src = readSrc("guided-flow.ts");
|
|
286
|
+
assert.match(src, /getRequiredWorkflowToolsForGuidedUnit/);
|
|
287
|
+
assert.match(src, /getWorkflowTransportSupportError/);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test("auto direct dispatch source enforces workflow compatibility preflight", () => {
|
|
291
|
+
const src = readSrc("auto-direct-dispatch.ts");
|
|
292
|
+
assert.match(src, /getRequiredWorkflowToolsForAutoUnit/);
|
|
293
|
+
assert.match(src, /getWorkflowTransportSupportError/);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
test("auto phases source enforces workflow compatibility preflight", () => {
|
|
297
|
+
const src = readSrc(join("auto", "phases.ts"));
|
|
298
|
+
assert.match(src, /getRequiredWorkflowToolsForAutoUnit/);
|
|
299
|
+
assert.match(src, /getWorkflowTransportSupportError/);
|
|
300
|
+
assert.match(src, /workflow-capability/);
|
|
301
|
+
});
|