gsd-pi 2.67.0-dev.1cd1e0f → 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 +155 -70
- package/dist/resources/extensions/gsd/auto/phases.js +17 -0
- package/dist/resources/extensions/gsd/auto/session.js +10 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +12 -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/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/system-context.js +7 -2
- 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/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 +56 -31
- package/dist/resources/extensions/gsd/init-wizard.js +37 -0
- 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/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 +8 -8
- 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 +8 -8
- 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/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/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 +193 -93
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +173 -79
- package/src/resources/extensions/gsd/auto/phases.ts +25 -0
- package/src/resources/extensions/gsd/auto/session.ts +10 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +20 -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/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/system-context.ts +8 -2
- 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/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 +66 -36
- package/src/resources/extensions/gsd/init-wizard.ts +40 -0
- 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/core-overlay-fallback.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +380 -2
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +66 -0
- 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-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/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/dist/web/standalone/.next/static/{PHqEommYRR8CRn3i84CGM → WMDT_0C0XDkBKtsAI_AX4}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{PHqEommYRR8CRn3i84CGM → WMDT_0C0XDkBKtsAI_AX4}/_ssgManifest.js +0 -0
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { describe, test } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
3
6
|
import {
|
|
7
|
+
makeStreamExhaustedErrorMessage,
|
|
4
8
|
buildPromptFromContext,
|
|
5
|
-
buildFinalClaudeCodeContent,
|
|
6
9
|
buildSdkOptions,
|
|
10
|
+
extractToolResultsFromSdkUserMessage,
|
|
7
11
|
getClaudeLookupCommand,
|
|
8
|
-
makeStreamExhaustedErrorMessage,
|
|
9
12
|
parseClaudeLookupOutput,
|
|
10
|
-
sanitizeClaudeCodeStreamingEvent,
|
|
11
13
|
} from "../stream-adapter.ts";
|
|
12
|
-
import type {
|
|
14
|
+
import type { Context, Message } from "@gsd/pi-ai";
|
|
15
|
+
import type { SDKUserMessage } from "../sdk-types.ts";
|
|
13
16
|
|
|
14
17
|
// ---------------------------------------------------------------------------
|
|
15
18
|
// Existing tests — exhausted stream fallback (#2575)
|
|
@@ -105,6 +108,65 @@ describe("stream-adapter — full context prompt (#2859)", () => {
|
|
|
105
108
|
});
|
|
106
109
|
});
|
|
107
110
|
|
|
111
|
+
describe("stream-adapter — Claude Code external tool results", () => {
|
|
112
|
+
test("extractToolResultsFromSdkUserMessage maps tool_result content to tool payloads", () => {
|
|
113
|
+
const message: SDKUserMessage = {
|
|
114
|
+
type: "user",
|
|
115
|
+
session_id: "sess-1",
|
|
116
|
+
parent_tool_use_id: "tool-bash-1",
|
|
117
|
+
message: {
|
|
118
|
+
role: "user",
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: "tool_result",
|
|
122
|
+
tool_use_id: "tool-bash-1",
|
|
123
|
+
content: "line 1\nline 2",
|
|
124
|
+
is_error: false,
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const results = extractToolResultsFromSdkUserMessage(message);
|
|
131
|
+
assert.deepEqual(results, [
|
|
132
|
+
{
|
|
133
|
+
toolUseId: "tool-bash-1",
|
|
134
|
+
result: {
|
|
135
|
+
content: [{ type: "text", text: "line 1\nline 2" }],
|
|
136
|
+
details: {},
|
|
137
|
+
isError: false,
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("extractToolResultsFromSdkUserMessage falls back to tool_use_result", () => {
|
|
144
|
+
const message: SDKUserMessage = {
|
|
145
|
+
type: "user",
|
|
146
|
+
session_id: "sess-1",
|
|
147
|
+
parent_tool_use_id: "tool-read-1",
|
|
148
|
+
message: { role: "user", content: [] },
|
|
149
|
+
tool_use_result: {
|
|
150
|
+
tool_use_id: "tool-read-1",
|
|
151
|
+
content: "file contents",
|
|
152
|
+
is_error: true,
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const results = extractToolResultsFromSdkUserMessage(message);
|
|
157
|
+
assert.deepEqual(results, [
|
|
158
|
+
{
|
|
159
|
+
toolUseId: "tool-read-1",
|
|
160
|
+
result: {
|
|
161
|
+
content: [{ type: "text", text: "file contents" }],
|
|
162
|
+
details: {},
|
|
163
|
+
isError: true,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
]);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
108
170
|
describe("stream-adapter — session persistence (#2859)", () => {
|
|
109
171
|
test("buildSdkOptions enables persistSession by default", () => {
|
|
110
172
|
const options = buildSdkOptions("claude-sonnet-4-20250514", "test prompt");
|
|
@@ -129,91 +191,123 @@ describe("stream-adapter — session persistence (#2859)", () => {
|
|
|
129
191
|
"non-sonnet models should have empty betas",
|
|
130
192
|
);
|
|
131
193
|
});
|
|
132
|
-
});
|
|
133
194
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
""
|
|
144
|
-
|
|
195
|
+
test("buildSdkOptions includes workflow MCP server config when env is set", () => {
|
|
196
|
+
const prev = {
|
|
197
|
+
GSD_WORKFLOW_MCP_COMMAND: process.env.GSD_WORKFLOW_MCP_COMMAND,
|
|
198
|
+
GSD_WORKFLOW_MCP_NAME: process.env.GSD_WORKFLOW_MCP_NAME,
|
|
199
|
+
GSD_WORKFLOW_MCP_ARGS: process.env.GSD_WORKFLOW_MCP_ARGS,
|
|
200
|
+
GSD_WORKFLOW_MCP_ENV: process.env.GSD_WORKFLOW_MCP_ENV,
|
|
201
|
+
GSD_WORKFLOW_MCP_CWD: process.env.GSD_WORKFLOW_MCP_CWD,
|
|
202
|
+
};
|
|
203
|
+
try {
|
|
204
|
+
process.env.GSD_WORKFLOW_MCP_COMMAND = "node";
|
|
205
|
+
process.env.GSD_WORKFLOW_MCP_NAME = "gsd-workflow";
|
|
206
|
+
process.env.GSD_WORKFLOW_MCP_ARGS = JSON.stringify(["packages/mcp-server/dist/cli.js"]);
|
|
207
|
+
process.env.GSD_WORKFLOW_MCP_ENV = JSON.stringify({ GSD_CLI_PATH: "/tmp/gsd" });
|
|
208
|
+
process.env.GSD_WORKFLOW_MCP_CWD = "/tmp/project";
|
|
145
209
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
210
|
+
const options = buildSdkOptions("claude-sonnet-4-20250514", "test");
|
|
211
|
+
const mcpServers = options.mcpServers as Record<string, any>;
|
|
212
|
+
assert.ok(mcpServers?.["gsd-workflow"], "expected gsd-workflow server config");
|
|
213
|
+
const srv = mcpServers["gsd-workflow"];
|
|
214
|
+
assert.equal(srv.command, "node");
|
|
215
|
+
assert.deepEqual(srv.args, ["packages/mcp-server/dist/cli.js"]);
|
|
216
|
+
assert.equal(srv.cwd, "/tmp/project");
|
|
217
|
+
assert.equal(srv.env.GSD_CLI_PATH, "/tmp/gsd");
|
|
218
|
+
assert.equal(srv.env.GSD_PERSIST_WRITE_GATE_STATE, "1");
|
|
219
|
+
assert.equal(srv.env.GSD_WORKFLOW_PROJECT_ROOT, "/tmp/project");
|
|
220
|
+
} finally {
|
|
221
|
+
process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND;
|
|
222
|
+
process.env.GSD_WORKFLOW_MCP_NAME = prev.GSD_WORKFLOW_MCP_NAME;
|
|
223
|
+
process.env.GSD_WORKFLOW_MCP_ARGS = prev.GSD_WORKFLOW_MCP_ARGS;
|
|
224
|
+
process.env.GSD_WORKFLOW_MCP_ENV = prev.GSD_WORKFLOW_MCP_ENV;
|
|
225
|
+
process.env.GSD_WORKFLOW_MCP_CWD = prev.GSD_WORKFLOW_MCP_CWD;
|
|
226
|
+
}
|
|
150
227
|
});
|
|
151
228
|
|
|
152
|
-
test("
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
229
|
+
test("buildSdkOptions auto-discovers bundled MCP server even without env hints", () => {
|
|
230
|
+
const prev = {
|
|
231
|
+
GSD_WORKFLOW_MCP_COMMAND: process.env.GSD_WORKFLOW_MCP_COMMAND,
|
|
232
|
+
GSD_WORKFLOW_MCP_NAME: process.env.GSD_WORKFLOW_MCP_NAME,
|
|
233
|
+
GSD_WORKFLOW_MCP_ARGS: process.env.GSD_WORKFLOW_MCP_ARGS,
|
|
234
|
+
GSD_WORKFLOW_MCP_ENV: process.env.GSD_WORKFLOW_MCP_ENV,
|
|
235
|
+
GSD_WORKFLOW_MCP_CWD: process.env.GSD_WORKFLOW_MCP_CWD,
|
|
236
|
+
};
|
|
237
|
+
try {
|
|
238
|
+
delete process.env.GSD_WORKFLOW_MCP_COMMAND;
|
|
239
|
+
delete process.env.GSD_WORKFLOW_MCP_NAME;
|
|
240
|
+
delete process.env.GSD_WORKFLOW_MCP_ARGS;
|
|
241
|
+
delete process.env.GSD_WORKFLOW_MCP_ENV;
|
|
242
|
+
delete process.env.GSD_WORKFLOW_MCP_CWD;
|
|
160
243
|
|
|
161
|
-
|
|
244
|
+
const originalCwd = process.cwd();
|
|
245
|
+
const emptyDir = mkdtempSync(join(tmpdir(), "claude-mcp-none-"));
|
|
246
|
+
process.chdir(emptyDir);
|
|
247
|
+
const options = buildSdkOptions("claude-sonnet-4-20250514", "test");
|
|
248
|
+
process.chdir(originalCwd);
|
|
249
|
+
// The bundled CLI may or may not be discoverable depending on
|
|
250
|
+
// whether the build output exists relative to import.meta.url.
|
|
251
|
+
// Either outcome is valid — the key invariant is no crash.
|
|
252
|
+
const mcpServers = (options as any).mcpServers;
|
|
253
|
+
if (mcpServers) {
|
|
254
|
+
assert.ok(mcpServers["gsd-workflow"], "if present, must be gsd-workflow");
|
|
255
|
+
}
|
|
256
|
+
rmSync(emptyDir, { recursive: true, force: true });
|
|
257
|
+
} finally {
|
|
258
|
+
process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND;
|
|
259
|
+
process.env.GSD_WORKFLOW_MCP_NAME = prev.GSD_WORKFLOW_MCP_NAME;
|
|
260
|
+
process.env.GSD_WORKFLOW_MCP_ARGS = prev.GSD_WORKFLOW_MCP_ARGS;
|
|
261
|
+
process.env.GSD_WORKFLOW_MCP_ENV = prev.GSD_WORKFLOW_MCP_ENV;
|
|
262
|
+
process.env.GSD_WORKFLOW_MCP_CWD = prev.GSD_WORKFLOW_MCP_CWD;
|
|
263
|
+
}
|
|
162
264
|
});
|
|
163
|
-
});
|
|
164
265
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
usage: {
|
|
174
|
-
input: 0,
|
|
175
|
-
output: 0,
|
|
176
|
-
cacheRead: 0,
|
|
177
|
-
cacheWrite: 0,
|
|
178
|
-
totalTokens: 0,
|
|
179
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
180
|
-
},
|
|
181
|
-
stopReason: "stop",
|
|
182
|
-
timestamp: Date.now(),
|
|
266
|
+
test("buildSdkOptions auto-detects local workflow MCP dist CLI when present", () => {
|
|
267
|
+
const prev = {
|
|
268
|
+
GSD_WORKFLOW_MCP_COMMAND: process.env.GSD_WORKFLOW_MCP_COMMAND,
|
|
269
|
+
GSD_WORKFLOW_MCP_NAME: process.env.GSD_WORKFLOW_MCP_NAME,
|
|
270
|
+
GSD_WORKFLOW_MCP_ARGS: process.env.GSD_WORKFLOW_MCP_ARGS,
|
|
271
|
+
GSD_WORKFLOW_MCP_ENV: process.env.GSD_WORKFLOW_MCP_ENV,
|
|
272
|
+
GSD_WORKFLOW_MCP_CWD: process.env.GSD_WORKFLOW_MCP_CWD,
|
|
273
|
+
GSD_CLI_PATH: process.env.GSD_CLI_PATH,
|
|
183
274
|
};
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
{ type: "thinking", thinking: "Planning next step" },
|
|
194
|
-
{ type: "text", text: "Done." },
|
|
195
|
-
] as any),
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
assert.ok(event, "text events should still be forwarded");
|
|
199
|
-
assert.equal(event!.type, "text_delta");
|
|
200
|
-
assert.equal((event! as any).contentIndex, 1);
|
|
201
|
-
assert.deepEqual((event! as any).partial.content, [
|
|
202
|
-
{ type: "thinking", thinking: "Planning next step" },
|
|
203
|
-
{ type: "text", text: "Done." },
|
|
204
|
-
]);
|
|
205
|
-
});
|
|
275
|
+
const originalCwd = process.cwd();
|
|
276
|
+
const repoDir = mkdtempSync(join(tmpdir(), "claude-mcp-detect-"));
|
|
277
|
+
try {
|
|
278
|
+
delete process.env.GSD_WORKFLOW_MCP_COMMAND;
|
|
279
|
+
delete process.env.GSD_WORKFLOW_MCP_NAME;
|
|
280
|
+
delete process.env.GSD_WORKFLOW_MCP_ARGS;
|
|
281
|
+
delete process.env.GSD_WORKFLOW_MCP_ENV;
|
|
282
|
+
delete process.env.GSD_WORKFLOW_MCP_CWD;
|
|
283
|
+
process.env.GSD_CLI_PATH = "/tmp/gsd";
|
|
206
284
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
{ type: "toolCall", id: "tc_1", name: "Bash", arguments: {} },
|
|
213
|
-
] as any),
|
|
214
|
-
});
|
|
285
|
+
const distDir = join(repoDir, "packages", "mcp-server", "dist");
|
|
286
|
+
mkdirSync(distDir, { recursive: true });
|
|
287
|
+
writeFileSync(join(distDir, "cli.js"), "#!/usr/bin/env node\n");
|
|
288
|
+
process.chdir(repoDir);
|
|
289
|
+
const resolvedRepoDir = realpathSync(repoDir);
|
|
215
290
|
|
|
216
|
-
|
|
291
|
+
const options = buildSdkOptions("claude-sonnet-4-20250514", "test");
|
|
292
|
+
const mcpServers = options.mcpServers as Record<string, any>;
|
|
293
|
+
assert.ok(mcpServers?.["gsd-workflow"], "expected gsd-workflow server config");
|
|
294
|
+
const srv = mcpServers["gsd-workflow"];
|
|
295
|
+
assert.equal(srv.command, process.execPath);
|
|
296
|
+
assert.deepEqual(srv.args, [realpathSync(resolve(repoDir, "packages", "mcp-server", "dist", "cli.js"))]);
|
|
297
|
+
assert.equal(srv.cwd, resolvedRepoDir);
|
|
298
|
+
assert.equal(srv.env.GSD_CLI_PATH, "/tmp/gsd");
|
|
299
|
+
assert.equal(srv.env.GSD_PERSIST_WRITE_GATE_STATE, "1");
|
|
300
|
+
assert.equal(srv.env.GSD_WORKFLOW_PROJECT_ROOT, resolvedRepoDir);
|
|
301
|
+
} finally {
|
|
302
|
+
process.chdir(originalCwd);
|
|
303
|
+
rmSync(repoDir, { recursive: true, force: true });
|
|
304
|
+
process.env.GSD_WORKFLOW_MCP_COMMAND = prev.GSD_WORKFLOW_MCP_COMMAND;
|
|
305
|
+
process.env.GSD_WORKFLOW_MCP_NAME = prev.GSD_WORKFLOW_MCP_NAME;
|
|
306
|
+
process.env.GSD_WORKFLOW_MCP_ARGS = prev.GSD_WORKFLOW_MCP_ARGS;
|
|
307
|
+
process.env.GSD_WORKFLOW_MCP_ENV = prev.GSD_WORKFLOW_MCP_ENV;
|
|
308
|
+
process.env.GSD_WORKFLOW_MCP_CWD = prev.GSD_WORKFLOW_MCP_CWD;
|
|
309
|
+
process.env.GSD_CLI_PATH = prev.GSD_CLI_PATH;
|
|
310
|
+
}
|
|
217
311
|
});
|
|
218
312
|
});
|
|
219
313
|
|
|
@@ -41,6 +41,10 @@ import { isDbAvailable, getMilestoneSlices } from "../gsd-db.js";
|
|
|
41
41
|
import { resetEvidence } from "../safety/evidence-collector.js";
|
|
42
42
|
import { createCheckpoint, cleanupCheckpoint, rollbackToCheckpoint } from "../safety/git-checkpoint.js";
|
|
43
43
|
import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
|
|
44
|
+
import {
|
|
45
|
+
getWorkflowTransportSupportError,
|
|
46
|
+
getRequiredWorkflowToolsForAutoUnit,
|
|
47
|
+
} from "../workflow-mcp.js";
|
|
44
48
|
|
|
45
49
|
// ─── generateMilestoneReport ──────────────────────────────────────────────────
|
|
46
50
|
|
|
@@ -1216,6 +1220,27 @@ export async function runUnitPhase(
|
|
|
1216
1220
|
? `${(s.currentUnitModel as any).provider ?? ""}/${(s.currentUnitModel as any).id ?? ""}`
|
|
1217
1221
|
: null;
|
|
1218
1222
|
|
|
1223
|
+
const compatibilityError = getWorkflowTransportSupportError(
|
|
1224
|
+
s.currentUnitModel?.provider ?? ctx.model?.provider,
|
|
1225
|
+
getRequiredWorkflowToolsForAutoUnit(unitType),
|
|
1226
|
+
{
|
|
1227
|
+
projectRoot: s.basePath,
|
|
1228
|
+
surface: "auto-mode",
|
|
1229
|
+
unitType,
|
|
1230
|
+
authMode: s.currentUnitModel?.provider
|
|
1231
|
+
? ctx.modelRegistry.getProviderAuthMode(s.currentUnitModel.provider)
|
|
1232
|
+
: ctx.model?.provider
|
|
1233
|
+
? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider)
|
|
1234
|
+
: undefined,
|
|
1235
|
+
baseUrl: (s.currentUnitModel as any)?.baseUrl ?? ctx.model?.baseUrl,
|
|
1236
|
+
},
|
|
1237
|
+
);
|
|
1238
|
+
if (compatibilityError) {
|
|
1239
|
+
ctx.ui.notify(compatibilityError, "error");
|
|
1240
|
+
await deps.stopAuto(ctx, pi, compatibilityError);
|
|
1241
|
+
return { action: "break", reason: "workflow-capability" };
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1219
1244
|
// Progress widget + preconditions — deferred to after model selection so the
|
|
1220
1245
|
// widget's first render tick shows the correct model (#2899).
|
|
1221
1246
|
deps.updateProgressWidget(ctx, unitType, unitId, state);
|
|
@@ -84,6 +84,9 @@ export class AutoSession {
|
|
|
84
84
|
// ── Paths ────────────────────────────────────────────────────────────────
|
|
85
85
|
basePath = "";
|
|
86
86
|
originalBasePath = "";
|
|
87
|
+
previousProjectRootEnv: string | null = null;
|
|
88
|
+
hadProjectRootEnv = false;
|
|
89
|
+
projectRootEnvCaptured = false;
|
|
87
90
|
gitService: GitServiceImpl | null = null;
|
|
88
91
|
|
|
89
92
|
// ── Dispatch counters ────────────────────────────────────────────────────
|
|
@@ -116,6 +119,8 @@ export class AutoSession {
|
|
|
116
119
|
pendingVerificationRetry: PendingVerificationRetry | null = null;
|
|
117
120
|
readonly verificationRetryCount = new Map<string, number>();
|
|
118
121
|
pausedSessionFile: string | null = null;
|
|
122
|
+
pausedUnitType: string | null = null;
|
|
123
|
+
pausedUnitId: string | null = null;
|
|
119
124
|
resourceVersionOnStart: string | null = null;
|
|
120
125
|
lastStateRebuildAt = 0;
|
|
121
126
|
|
|
@@ -192,6 +197,9 @@ export class AutoSession {
|
|
|
192
197
|
// Paths
|
|
193
198
|
this.basePath = "";
|
|
194
199
|
this.originalBasePath = "";
|
|
200
|
+
this.previousProjectRootEnv = null;
|
|
201
|
+
this.hadProjectRootEnv = false;
|
|
202
|
+
this.projectRootEnvCaptured = false;
|
|
195
203
|
this.gitService = null;
|
|
196
204
|
|
|
197
205
|
// Dispatch
|
|
@@ -217,6 +225,8 @@ export class AutoSession {
|
|
|
217
225
|
this.pendingVerificationRetry = null;
|
|
218
226
|
this.verificationRetryCount.clear();
|
|
219
227
|
this.pausedSessionFile = null;
|
|
228
|
+
this.pausedUnitType = null;
|
|
229
|
+
this.pausedUnitId = null;
|
|
220
230
|
this.resourceVersionOnStart = null;
|
|
221
231
|
this.lastStateRebuildAt = 0;
|
|
222
232
|
|
|
@@ -29,6 +29,10 @@ import {
|
|
|
29
29
|
} from "./auto-prompts.js";
|
|
30
30
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
31
31
|
import { pauseAuto } from "./auto.js";
|
|
32
|
+
import {
|
|
33
|
+
getWorkflowTransportSupportError,
|
|
34
|
+
getRequiredWorkflowToolsForAutoUnit,
|
|
35
|
+
} from "./workflow-mcp.js";
|
|
32
36
|
|
|
33
37
|
export async function dispatchDirectPhase(
|
|
34
38
|
ctx: ExtensionCommandContext,
|
|
@@ -243,6 +247,22 @@ export async function dispatchDirectPhase(
|
|
|
243
247
|
return;
|
|
244
248
|
}
|
|
245
249
|
|
|
250
|
+
const compatibilityError = getWorkflowTransportSupportError(
|
|
251
|
+
ctx.model?.provider,
|
|
252
|
+
getRequiredWorkflowToolsForAutoUnit(unitType),
|
|
253
|
+
{
|
|
254
|
+
projectRoot: base,
|
|
255
|
+
surface: "direct phase dispatch",
|
|
256
|
+
unitType,
|
|
257
|
+
authMode: ctx.model?.provider ? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider) : undefined,
|
|
258
|
+
baseUrl: ctx.model?.baseUrl,
|
|
259
|
+
},
|
|
260
|
+
);
|
|
261
|
+
if (compatibilityError) {
|
|
262
|
+
ctx.ui.notify(compatibilityError, "error");
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
246
266
|
ctx.ui.notify(`Dispatching ${unitType} for ${unitId}...`, "info");
|
|
247
267
|
const result = await ctx.newSession();
|
|
248
268
|
if (result.cancelled) {
|
|
@@ -178,7 +178,7 @@ export function incrementUatCount(basePath: string, mid: string, sid: string): n
|
|
|
178
178
|
export function isVerificationNotApplicable(value: string): boolean {
|
|
179
179
|
const v = (value ?? "").toLowerCase().trim().replace(/[.\s]+$/, "");
|
|
180
180
|
if (!v || v === "none") return true;
|
|
181
|
-
return /^(?:none[\s._-]*
|
|
181
|
+
return /^(?:none(?:[\s._\u2014-]+[\s\S]*)?|n\/?a|not[\s._-]+(?:applicable|required|needed|provided)|no[\s._-]+operational[\s\S]*)$/i.test(v);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
// ─── Rules ────────────────────────────────────────────────────────────────
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
} from "@gsd/pi-coding-agent";
|
|
16
16
|
import { deriveState } from "./state.js";
|
|
17
17
|
import { loadFile, getManifestStatus } from "./files.js";
|
|
18
|
+
import type { InterruptedSessionAssessment } from "./interrupted-session.js";
|
|
18
19
|
import {
|
|
19
20
|
loadEffectiveGSDPreferences,
|
|
20
21
|
resolveSkillDiscoveryMode,
|
|
@@ -23,16 +24,9 @@ import {
|
|
|
23
24
|
import { ensureGsdSymlink, isInheritedRepo, validateProjectId } from "./repo-identity.js";
|
|
24
25
|
import { migrateToExternalState, recoverFailedMigration } from "./migrate-external.js";
|
|
25
26
|
import { collectSecretsFromManifest } from "../get-secrets-from-user.js";
|
|
26
|
-
import { gsdRoot, resolveMilestoneFile
|
|
27
|
+
import { gsdRoot, resolveMilestoneFile } from "./paths.js";
|
|
27
28
|
import { invalidateAllCaches } from "./cache.js";
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
writeLock,
|
|
31
|
-
clearLock,
|
|
32
|
-
readCrashLock,
|
|
33
|
-
formatCrashInfo,
|
|
34
|
-
isLockProcessAlive,
|
|
35
|
-
} from "./crash-recovery.js";
|
|
29
|
+
import { writeLock, clearLock } from "./crash-recovery.js";
|
|
36
30
|
import {
|
|
37
31
|
acquireSessionLock,
|
|
38
32
|
releaseSessionLock,
|
|
@@ -248,6 +242,7 @@ export async function bootstrapAutoSession(
|
|
|
248
242
|
verboseMode: boolean,
|
|
249
243
|
requestedStepMode: boolean,
|
|
250
244
|
deps: BootstrapDeps,
|
|
245
|
+
interrupted: InterruptedSessionAssessment,
|
|
251
246
|
): Promise<boolean> {
|
|
252
247
|
const {
|
|
253
248
|
shouldUseWorktreeIsolation,
|
|
@@ -340,57 +335,27 @@ export async function bootstrapAutoSession(
|
|
|
340
335
|
}
|
|
341
336
|
}
|
|
342
337
|
|
|
338
|
+
if (ctx.model?.provider === "claude-code") {
|
|
339
|
+
try {
|
|
340
|
+
const { ensureProjectWorkflowMcpConfig } = await import("./mcp-project-config.js");
|
|
341
|
+
const result = ensureProjectWorkflowMcpConfig(base);
|
|
342
|
+
if (result.status !== "unchanged") {
|
|
343
|
+
ctx.ui.notify(`Claude Code MCP prepared at ${result.configPath}`, "info");
|
|
344
|
+
}
|
|
345
|
+
} catch (err) {
|
|
346
|
+
ctx.ui.notify(
|
|
347
|
+
`Claude Code MCP prep failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
348
|
+
"warning",
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
343
353
|
// Initialize GitServiceImpl
|
|
344
354
|
s.gitService = new GitServiceImpl(
|
|
345
355
|
s.basePath,
|
|
346
356
|
loadEffectiveGSDPreferences()?.preferences?.git ?? {},
|
|
347
357
|
);
|
|
348
358
|
|
|
349
|
-
// Check for crash from previous session. Skip our own fresh bootstrap lock.
|
|
350
|
-
const crashLock = readCrashLock(base);
|
|
351
|
-
if (crashLock && crashLock.pid !== process.pid) {
|
|
352
|
-
if (isLockProcessAlive(crashLock)) {
|
|
353
|
-
ctx.ui.notify(
|
|
354
|
-
`Another auto-mode session (PID ${crashLock.pid}) appears to be running.\nStop it with \`kill ${crashLock.pid}\` before starting a new session.`,
|
|
355
|
-
"error",
|
|
356
|
-
);
|
|
357
|
-
return releaseLockAndReturn();
|
|
358
|
-
}
|
|
359
|
-
const recoveredMid = parseUnitId(crashLock.unitId).milestone;
|
|
360
|
-
const milestoneAlreadyComplete = recoveredMid
|
|
361
|
-
? !!resolveMilestoneFile(base, recoveredMid, "SUMMARY")
|
|
362
|
-
: false;
|
|
363
|
-
|
|
364
|
-
if (milestoneAlreadyComplete) {
|
|
365
|
-
ctx.ui.notify(
|
|
366
|
-
`Crash recovery: discarding stale context for ${crashLock.unitId} — milestone ${recoveredMid} is already complete.`,
|
|
367
|
-
"info",
|
|
368
|
-
);
|
|
369
|
-
} else {
|
|
370
|
-
const activityDir = join(gsdRoot(base), "activity");
|
|
371
|
-
const recovery = synthesizeCrashRecovery(
|
|
372
|
-
base,
|
|
373
|
-
crashLock.unitType,
|
|
374
|
-
crashLock.unitId,
|
|
375
|
-
crashLock.sessionFile,
|
|
376
|
-
activityDir,
|
|
377
|
-
);
|
|
378
|
-
if (recovery && recovery.trace.toolCallCount > 0) {
|
|
379
|
-
s.pendingCrashRecovery = recovery.prompt;
|
|
380
|
-
ctx.ui.notify(
|
|
381
|
-
`${formatCrashInfo(crashLock)}\nRecovered ${recovery.trace.toolCallCount} tool calls from crashed session. Resuming with full context.`,
|
|
382
|
-
"warning",
|
|
383
|
-
);
|
|
384
|
-
} else {
|
|
385
|
-
ctx.ui.notify(
|
|
386
|
-
`${formatCrashInfo(crashLock)}\nNo session data recovered. Resuming from disk state.`,
|
|
387
|
-
"warning",
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
clearLock(base);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
359
|
// ── Debug mode ──
|
|
395
360
|
if (!isDebugEnabled() && process.env.GSD_DEBUG === "1") {
|
|
396
361
|
enableDebug(base);
|
|
@@ -410,6 +375,10 @@ export async function bootstrapAutoSession(
|
|
|
410
375
|
ctx.ui.notify(`Debug logging enabled → ${getDebugLogPath()}`, "info");
|
|
411
376
|
}
|
|
412
377
|
|
|
378
|
+
if (interrupted.classification !== "recoverable") {
|
|
379
|
+
s.pendingCrashRecovery = null;
|
|
380
|
+
}
|
|
381
|
+
|
|
413
382
|
// Invalidate caches before initial state derivation
|
|
414
383
|
invalidateAllCaches();
|
|
415
384
|
|
|
@@ -909,4 +878,3 @@ export async function bootstrapAutoSession(
|
|
|
909
878
|
throw err;
|
|
910
879
|
}
|
|
911
880
|
}
|
|
912
|
-
|
|
@@ -1137,6 +1137,7 @@ function copyPlanningArtifacts(srcBase: string, wtPath: string): void {
|
|
|
1137
1137
|
const srcGsd = join(srcBase, ".gsd");
|
|
1138
1138
|
const dstGsd = join(wtPath, ".gsd");
|
|
1139
1139
|
if (!existsSync(srcGsd)) return;
|
|
1140
|
+
if (isSamePath(srcGsd, dstGsd)) return;
|
|
1140
1141
|
|
|
1141
1142
|
// Copy milestones/ directory (planning files, roadmaps, plans, research)
|
|
1142
1143
|
safeCopyRecursive(join(srcGsd, "milestones"), join(dstGsd, "milestones"), {
|
|
@@ -1420,8 +1421,31 @@ export function mergeMilestoneToMain(
|
|
|
1420
1421
|
const worktreeCwd = process.cwd();
|
|
1421
1422
|
const milestoneBranch = autoWorktreeBranch(milestoneId);
|
|
1422
1423
|
|
|
1423
|
-
// 1. Auto-commit dirty state
|
|
1424
|
-
|
|
1424
|
+
// 1. Auto-commit dirty state before leaving.
|
|
1425
|
+
// Guard: when we entered through an auto-worktree (originalBase is set),
|
|
1426
|
+
// only auto-commit when cwd is on the milestone branch. In parallel mode,
|
|
1427
|
+
// cwd may be on the integration branch after a prior merge's
|
|
1428
|
+
// MergeConflictError left cwd unrestored. Auto-committing on the
|
|
1429
|
+
// integration branch captures dirty files from OTHER milestones under a
|
|
1430
|
+
// misleading commit message, contaminating the main branch (#2929).
|
|
1431
|
+
//
|
|
1432
|
+
// When originalBase is null (branch mode, no worktree), autoCommitDirtyState
|
|
1433
|
+
// runs unconditionally — the caller is responsible for cwd placement.
|
|
1434
|
+
{
|
|
1435
|
+
let shouldAutoCommit = true;
|
|
1436
|
+
if (originalBase !== null) {
|
|
1437
|
+
try {
|
|
1438
|
+
const currentBranch = nativeGetCurrentBranch(worktreeCwd);
|
|
1439
|
+
shouldAutoCommit = currentBranch === milestoneBranch;
|
|
1440
|
+
} catch {
|
|
1441
|
+
// If we can't determine the branch, skip the auto-commit to be safe
|
|
1442
|
+
shouldAutoCommit = false;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
if (shouldAutoCommit) {
|
|
1446
|
+
autoCommitDirtyState(worktreeCwd);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1425
1449
|
|
|
1426
1450
|
// Reconcile worktree DB into main DB before leaving worktree context.
|
|
1427
1451
|
// Skip when both paths resolve to the same physical file (shared WAL /
|
|
@@ -1778,6 +1802,12 @@ export function mergeMilestoneToMain(
|
|
|
1778
1802
|
}
|
|
1779
1803
|
}
|
|
1780
1804
|
restoreShelter();
|
|
1805
|
+
// Restore cwd so the caller is not stranded on the integration branch.
|
|
1806
|
+
// Without this, the next mergeMilestoneToMain call in a parallel merge
|
|
1807
|
+
// sequence uses process.cwd() (now the project root) as worktreeCwd,
|
|
1808
|
+
// causing autoCommitDirtyState to commit unrelated milestone files to
|
|
1809
|
+
// the integration branch (#2929).
|
|
1810
|
+
process.chdir(previousCwd);
|
|
1781
1811
|
throw new MergeConflictError(
|
|
1782
1812
|
codeConflicts,
|
|
1783
1813
|
"squash",
|
|
@@ -1975,23 +2005,38 @@ export function mergeMilestoneToMain(
|
|
|
1975
2005
|
// changes (e.g. nativeHasChanges cache returned stale false, or auto-commit
|
|
1976
2006
|
// silently failed), force one final commit so code is not destroyed by
|
|
1977
2007
|
// `git worktree remove --force`.
|
|
2008
|
+
//
|
|
2009
|
+
// Guard: only run when worktreeCwd is on the milestone branch (#2929).
|
|
2010
|
+
// In parallel mode or branch-mode merges, worktreeCwd may be the project
|
|
2011
|
+
// root on the integration branch. Committing dirty state there would
|
|
2012
|
+
// capture unrelated files from other milestones.
|
|
1978
2013
|
if (existsSync(worktreeCwd)) {
|
|
2014
|
+
let preTeardownBranch: string | null = null;
|
|
1979
2015
|
try {
|
|
1980
|
-
|
|
1981
|
-
|
|
2016
|
+
preTeardownBranch = nativeGetCurrentBranch(worktreeCwd);
|
|
2017
|
+
} catch (err) {
|
|
2018
|
+
debugLog("mergeMilestoneToMain", { phase: "pre-teardown-branch-detect-failed", error: String(err) });
|
|
2019
|
+
}
|
|
2020
|
+
const isOnMilestoneBranch = preTeardownBranch === milestoneBranch;
|
|
2021
|
+
|
|
2022
|
+
if (isOnMilestoneBranch) {
|
|
2023
|
+
try {
|
|
2024
|
+
const dirtyCheck = nativeWorkingTreeStatus(worktreeCwd);
|
|
2025
|
+
if (dirtyCheck) {
|
|
2026
|
+
debugLog("mergeMilestoneToMain", {
|
|
2027
|
+
phase: "pre-teardown-dirty",
|
|
2028
|
+
worktreeCwd,
|
|
2029
|
+
status: dirtyCheck.slice(0, 200),
|
|
2030
|
+
});
|
|
2031
|
+
nativeAddAllWithExclusions(worktreeCwd, RUNTIME_EXCLUSION_PATHS);
|
|
2032
|
+
nativeCommit(worktreeCwd, "chore: pre-teardown auto-commit of uncommitted worktree changes");
|
|
2033
|
+
}
|
|
2034
|
+
} catch (e) {
|
|
1982
2035
|
debugLog("mergeMilestoneToMain", {
|
|
1983
|
-
phase: "pre-teardown-
|
|
1984
|
-
|
|
1985
|
-
status: dirtyCheck.slice(0, 200),
|
|
2036
|
+
phase: "pre-teardown-commit-error",
|
|
2037
|
+
error: String(e),
|
|
1986
2038
|
});
|
|
1987
|
-
nativeAddAllWithExclusions(worktreeCwd, RUNTIME_EXCLUSION_PATHS);
|
|
1988
|
-
nativeCommit(worktreeCwd, "chore: pre-teardown auto-commit of uncommitted worktree changes");
|
|
1989
2039
|
}
|
|
1990
|
-
} catch (e) {
|
|
1991
|
-
debugLog("mergeMilestoneToMain", {
|
|
1992
|
-
phase: "pre-teardown-commit-error",
|
|
1993
|
-
error: String(e),
|
|
1994
|
-
});
|
|
1995
2040
|
}
|
|
1996
2041
|
}
|
|
1997
2042
|
|
|
@@ -2020,4 +2065,3 @@ export function mergeMilestoneToMain(
|
|
|
2020
2065
|
|
|
2021
2066
|
return { commitMessage, pushed, prCreated, codeFilesChanged };
|
|
2022
2067
|
}
|
|
2023
|
-
|