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
|
@@ -14,7 +14,8 @@ import { buildSkillActivationBlock } from "./auto-prompts.js";
|
|
|
14
14
|
import { deriveState } from "./state.js";
|
|
15
15
|
import { invalidateAllCaches } from "./cache.js";
|
|
16
16
|
import { startAuto } from "./auto.js";
|
|
17
|
-
import {
|
|
17
|
+
import { clearLock } from "./crash-recovery.js";
|
|
18
|
+
import { assessInterruptedSession, formatInterruptedSessionRunningMessage, formatInterruptedSessionSummary, } from "./interrupted-session.js";
|
|
18
19
|
import { listUnitRuntimeRecords, clearUnitRuntimeRecord } from "./unit-runtime.js";
|
|
19
20
|
import { resolveExpectedArtifactPath } from "./auto.js";
|
|
20
21
|
import { gsdRoot, milestonesDir, resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveGsdRootFile, relGsdRootFile, relMilestoneFile, relSliceFile, } from "./paths.js";
|
|
@@ -167,14 +168,9 @@ export function checkAutoStartAfterDiscuss() {
|
|
|
167
168
|
}
|
|
168
169
|
// Gate 4: Discussion manifest process verification (multi-milestone only)
|
|
169
170
|
// The LLM writes DISCUSSION-MANIFEST.json after each Phase 3 gate decision.
|
|
170
|
-
//
|
|
171
|
-
//
|
|
171
|
+
// When it exists, validate it before auto-starting. Project history alone is
|
|
172
|
+
// not a reliable signal for the current discussion mode.
|
|
172
173
|
const manifestPath = join(gsdRoot(basePath), "DISCUSSION-MANIFEST.json");
|
|
173
|
-
const requiresManifest = projectIds.length > 1 || findMilestoneIds(basePath).length > 1;
|
|
174
|
-
if (requiresManifest && !existsSync(manifestPath)) {
|
|
175
|
-
ctx.ui.notify("Multi-milestone discussion manifest is missing. Auto-start will remain paused until the manifest is written.", "warning");
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
174
|
if (existsSync(manifestPath)) {
|
|
179
175
|
try {
|
|
180
176
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
@@ -1102,33 +1098,46 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1102
1098
|
untrackRuntimeFiles(basePath);
|
|
1103
1099
|
// ── Self-heal stale runtime records from crashed auto-mode sessions ──
|
|
1104
1100
|
selfHealRuntimeRecords(basePath, ctx);
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1101
|
+
const interrupted = await assessInterruptedSession(basePath);
|
|
1102
|
+
if (interrupted.classification === "running") {
|
|
1103
|
+
ctx.ui.notify(formatInterruptedSessionRunningMessage(interrupted), "error");
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
if (interrupted.classification === "stale") {
|
|
1110
1107
|
clearLock(basePath);
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
// real auto-mode work begins.
|
|
1115
|
-
const isBootstrapCrash = crashLock.unitType === "starting"
|
|
1116
|
-
&& crashLock.unitId === "bootstrap";
|
|
1117
|
-
if (!isBootstrapCrash) {
|
|
1118
|
-
const resume = await showNextAction(ctx, {
|
|
1119
|
-
title: "GSD — Interrupted Session Detected",
|
|
1120
|
-
summary: [formatCrashInfo(crashLock)],
|
|
1121
|
-
actions: [
|
|
1122
|
-
{ id: "resume", label: "Resume with /gsd auto", description: "Pick up where it left off", recommended: true },
|
|
1123
|
-
{ id: "continue", label: "Continue manually", description: "Open the wizard as normal" },
|
|
1124
|
-
],
|
|
1125
|
-
});
|
|
1126
|
-
if (resume === "resume") {
|
|
1127
|
-
await startAuto(ctx, pi, basePath, false);
|
|
1128
|
-
return;
|
|
1108
|
+
if (interrupted.pausedSession) {
|
|
1109
|
+
try {
|
|
1110
|
+
unlinkSync(join(gsdRoot(basePath), "runtime", "paused-session.json"));
|
|
1129
1111
|
}
|
|
1112
|
+
catch (e) {
|
|
1113
|
+
logWarning("guided", `stale pause file cleanup failed: ${e.message}`, { file: "guided-flow.ts" });
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
else if (interrupted.classification === "recoverable") {
|
|
1118
|
+
if (interrupted.lock)
|
|
1119
|
+
clearLock(basePath);
|
|
1120
|
+
const resumeLabel = interrupted.pausedSession?.stepMode
|
|
1121
|
+
? "Resume with /gsd next"
|
|
1122
|
+
: "Resume with /gsd auto";
|
|
1123
|
+
const resume = await showNextAction(ctx, {
|
|
1124
|
+
title: "GSD — Interrupted Session Detected",
|
|
1125
|
+
summary: formatInterruptedSessionSummary(interrupted),
|
|
1126
|
+
actions: [
|
|
1127
|
+
{ id: "resume", label: resumeLabel, description: "Pick up where it left off", recommended: true },
|
|
1128
|
+
{ id: "continue", label: "Continue manually", description: "Open the wizard as normal" },
|
|
1129
|
+
],
|
|
1130
|
+
});
|
|
1131
|
+
if (resume === "resume") {
|
|
1132
|
+
await startAuto(ctx, pi, basePath, false, {
|
|
1133
|
+
interrupted,
|
|
1134
|
+
step: interrupted.pausedSession?.stepMode ?? false,
|
|
1135
|
+
});
|
|
1136
|
+
return;
|
|
1130
1137
|
}
|
|
1131
1138
|
}
|
|
1139
|
+
// Always derive from the project root — the assessment may have derived
|
|
1140
|
+
// state from a worktree path that was cleaned up in the stale branch above.
|
|
1132
1141
|
const state = await deriveState(basePath);
|
|
1133
1142
|
// Rebuild STATE.md from derived state before any dispatch (#3475).
|
|
1134
1143
|
try {
|
|
@@ -190,16 +190,12 @@ export async function showProjectInit(ctx, pi, basePath, detection) {
|
|
|
190
190
|
// Initialize SQLite database so GSD starts in full-capability mode (#3880).
|
|
191
191
|
// Without this, isDbAvailable() returns false and GSD enters degraded
|
|
192
192
|
// markdown-only mode until a tool handler happens to call ensureDbOpen().
|
|
193
|
-
let dbReady = false;
|
|
194
193
|
try {
|
|
195
194
|
const { ensureDbOpen } = await import("./bootstrap/dynamic-tools.js");
|
|
196
|
-
|
|
195
|
+
await ensureDbOpen(basePath);
|
|
197
196
|
}
|
|
198
197
|
catch {
|
|
199
|
-
//
|
|
200
|
-
}
|
|
201
|
-
if (!dbReady) {
|
|
202
|
-
ctx.ui.notify("Warning: database initialization failed — GSD will run in degraded mode until the next /gsd invocation.", "warning");
|
|
198
|
+
// Non-fatal — DB creation failure should not block project init
|
|
203
199
|
}
|
|
204
200
|
// Ensure .gitignore
|
|
205
201
|
ensureGitignore(basePath);
|
|
@@ -218,7 +214,6 @@ export async function showProjectInit(ctx, pi, basePath, detection) {
|
|
|
218
214
|
// Write initial STATE.md so it exists before the first /gsd invocation.
|
|
219
215
|
// The explicit /gsd init path (ops.ts) returns without entering showSmartEntry(),
|
|
220
216
|
// which would otherwise generate STATE.md at guided-flow.ts:1358.
|
|
221
|
-
let stateReady = false;
|
|
222
217
|
try {
|
|
223
218
|
const { deriveState } = await import("./state.js");
|
|
224
219
|
const { buildStateMarkdown } = await import("./doctor.js");
|
|
@@ -226,13 +221,21 @@ export async function showProjectInit(ctx, pi, basePath, detection) {
|
|
|
226
221
|
const { resolveGsdRootFile } = await import("./paths.js");
|
|
227
222
|
const state = await deriveState(basePath);
|
|
228
223
|
await saveFile(resolveGsdRootFile(basePath, "STATE"), buildStateMarkdown(state));
|
|
229
|
-
stateReady = true;
|
|
230
224
|
}
|
|
231
225
|
catch {
|
|
232
|
-
//
|
|
233
|
-
}
|
|
234
|
-
if (
|
|
235
|
-
|
|
226
|
+
// Non-fatal — STATE.md will be regenerated on next /gsd invocation
|
|
227
|
+
}
|
|
228
|
+
if (ctx.model?.provider === "claude-code") {
|
|
229
|
+
try {
|
|
230
|
+
const { ensureProjectWorkflowMcpConfig } = await import("./mcp-project-config.js");
|
|
231
|
+
const result = ensureProjectWorkflowMcpConfig(basePath);
|
|
232
|
+
if (result.status !== "unchanged") {
|
|
233
|
+
ctx.ui.notify(`Claude Code MCP prepared at ${result.configPath}`, "info");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
ctx.ui.notify(`Claude Code MCP prep failed: ${err instanceof Error ? err.message : String(err)}`, "warning");
|
|
238
|
+
}
|
|
236
239
|
}
|
|
237
240
|
ctx.ui.notify("GSD initialized. Starting your first milestone...", "info");
|
|
238
241
|
return { completed: true, bootstrapped: true };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { verifyExpectedArtifact } from "./auto-recovery.js";
|
|
4
|
+
import { formatCrashInfo, isLockProcessAlive, readCrashLock, } from "./crash-recovery.js";
|
|
5
|
+
import { gsdRoot } from "./paths.js";
|
|
6
|
+
import { synthesizeCrashRecovery, } from "./session-forensics.js";
|
|
7
|
+
import { deriveState } from "./state.js";
|
|
8
|
+
export function readPausedSessionMetadata(basePath) {
|
|
9
|
+
const pausedPath = join(gsdRoot(basePath), "runtime", "paused-session.json");
|
|
10
|
+
if (!existsSync(pausedPath))
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(readFileSync(pausedPath, "utf-8"));
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function isBootstrapCrashLock(lock) {
|
|
20
|
+
return !!(lock &&
|
|
21
|
+
lock.unitType === "starting" &&
|
|
22
|
+
lock.unitId === "bootstrap");
|
|
23
|
+
}
|
|
24
|
+
export function hasResumableDerivedState(state) {
|
|
25
|
+
return !!(state?.activeMilestone && state.phase !== "complete");
|
|
26
|
+
}
|
|
27
|
+
export async function assessInterruptedSession(basePath) {
|
|
28
|
+
const pausedSession = readPausedSessionMetadata(basePath);
|
|
29
|
+
const worktreeExists = pausedSession?.worktreePath
|
|
30
|
+
? existsSync(pausedSession.worktreePath)
|
|
31
|
+
: false;
|
|
32
|
+
const assessmentBasePath = worktreeExists ? pausedSession.worktreePath : basePath;
|
|
33
|
+
const rawLock = readCrashLock(basePath);
|
|
34
|
+
const lock = rawLock && rawLock.pid !== process.pid ? rawLock : null;
|
|
35
|
+
if (!lock && !pausedSession) {
|
|
36
|
+
return {
|
|
37
|
+
classification: "none",
|
|
38
|
+
lock: null,
|
|
39
|
+
pausedSession: null,
|
|
40
|
+
state: null,
|
|
41
|
+
recovery: null,
|
|
42
|
+
recoveryPrompt: null,
|
|
43
|
+
recoveryToolCallCount: 0,
|
|
44
|
+
artifactSatisfied: false,
|
|
45
|
+
hasResumableDiskState: false,
|
|
46
|
+
isBootstrapCrash: false,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (lock && isLockProcessAlive(lock)) {
|
|
50
|
+
return {
|
|
51
|
+
classification: "running",
|
|
52
|
+
lock,
|
|
53
|
+
pausedSession,
|
|
54
|
+
state: null,
|
|
55
|
+
recovery: null,
|
|
56
|
+
recoveryPrompt: null,
|
|
57
|
+
recoveryToolCallCount: 0,
|
|
58
|
+
artifactSatisfied: false,
|
|
59
|
+
hasResumableDiskState: false,
|
|
60
|
+
isBootstrapCrash: false,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const isBootstrapCrash = isBootstrapCrashLock(lock);
|
|
64
|
+
const state = await deriveState(assessmentBasePath);
|
|
65
|
+
const hasResumableDiskState = hasResumableDerivedState(state);
|
|
66
|
+
const artifactSatisfied = !!(lock &&
|
|
67
|
+
!isBootstrapCrash &&
|
|
68
|
+
verifyExpectedArtifact(lock.unitType, lock.unitId, assessmentBasePath));
|
|
69
|
+
let recovery = null;
|
|
70
|
+
if (lock && !isBootstrapCrash && !artifactSatisfied) {
|
|
71
|
+
recovery = synthesizeCrashRecovery(assessmentBasePath, lock.unitType, lock.unitId, lock.sessionFile, join(gsdRoot(assessmentBasePath), "activity"));
|
|
72
|
+
}
|
|
73
|
+
const recoveryToolCallCount = recovery?.trace.toolCallCount ?? 0;
|
|
74
|
+
const recoveryPrompt = recoveryToolCallCount > 0 ? recovery.prompt : null;
|
|
75
|
+
if (isBootstrapCrash) {
|
|
76
|
+
return {
|
|
77
|
+
classification: pausedSession ? "recoverable" : "stale",
|
|
78
|
+
lock,
|
|
79
|
+
pausedSession,
|
|
80
|
+
state,
|
|
81
|
+
recovery,
|
|
82
|
+
recoveryPrompt,
|
|
83
|
+
recoveryToolCallCount,
|
|
84
|
+
artifactSatisfied,
|
|
85
|
+
hasResumableDiskState,
|
|
86
|
+
isBootstrapCrash: true,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (!hasResumableDiskState && pausedSession && !lock && recoveryToolCallCount === 0) {
|
|
90
|
+
return {
|
|
91
|
+
classification: "stale",
|
|
92
|
+
lock,
|
|
93
|
+
pausedSession,
|
|
94
|
+
state,
|
|
95
|
+
recovery,
|
|
96
|
+
recoveryPrompt,
|
|
97
|
+
recoveryToolCallCount,
|
|
98
|
+
artifactSatisfied,
|
|
99
|
+
hasResumableDiskState,
|
|
100
|
+
isBootstrapCrash: false,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (lock && artifactSatisfied && !hasResumableDiskState && recoveryToolCallCount === 0) {
|
|
104
|
+
return {
|
|
105
|
+
classification: "stale",
|
|
106
|
+
lock,
|
|
107
|
+
pausedSession,
|
|
108
|
+
state,
|
|
109
|
+
recovery,
|
|
110
|
+
recoveryPrompt,
|
|
111
|
+
recoveryToolCallCount,
|
|
112
|
+
artifactSatisfied,
|
|
113
|
+
hasResumableDiskState,
|
|
114
|
+
isBootstrapCrash: false,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const hasStrongRecoverySignal = hasResumableDiskState || recoveryToolCallCount > 0;
|
|
118
|
+
return {
|
|
119
|
+
classification: hasStrongRecoverySignal ? "recoverable" : "stale",
|
|
120
|
+
lock,
|
|
121
|
+
pausedSession,
|
|
122
|
+
state,
|
|
123
|
+
recovery,
|
|
124
|
+
recoveryPrompt,
|
|
125
|
+
recoveryToolCallCount,
|
|
126
|
+
artifactSatisfied,
|
|
127
|
+
hasResumableDiskState,
|
|
128
|
+
isBootstrapCrash: false,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export function formatInterruptedSessionSummary(assessment) {
|
|
132
|
+
if (assessment.lock)
|
|
133
|
+
return [formatCrashInfo(assessment.lock)];
|
|
134
|
+
if (assessment.pausedSession?.milestoneId) {
|
|
135
|
+
return [
|
|
136
|
+
`Paused auto-mode session detected for ${assessment.pausedSession.milestoneId}.`,
|
|
137
|
+
];
|
|
138
|
+
}
|
|
139
|
+
return ["Paused auto-mode session detected."];
|
|
140
|
+
}
|
|
141
|
+
export function formatInterruptedSessionRunningMessage(assessment) {
|
|
142
|
+
const pid = assessment.lock?.pid;
|
|
143
|
+
return pid
|
|
144
|
+
? `Another auto-mode session (PID ${pid}) appears to be running.\nStop it with \`kill ${pid}\` before starting a new session.`
|
|
145
|
+
: "Another auto-mode session appears to be running.";
|
|
146
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { assertSafeDirectory } from "./validate-directory.js";
|
|
5
|
+
import { detectWorkflowMcpLaunchConfig } from "./workflow-mcp.js";
|
|
6
|
+
export const GSD_WORKFLOW_MCP_SERVER_NAME = "gsd-workflow";
|
|
7
|
+
export function resolveBundledGsdCliPath(env = process.env) {
|
|
8
|
+
const explicit = env.GSD_CLI_PATH?.trim() || env.GSD_BIN_PATH?.trim();
|
|
9
|
+
if (explicit)
|
|
10
|
+
return explicit;
|
|
11
|
+
const candidates = [
|
|
12
|
+
resolve(fileURLToPath(new URL("../../../../scripts/dev-cli.js", import.meta.url))),
|
|
13
|
+
resolve(fileURLToPath(new URL("../../../../dist/loader.js", import.meta.url))),
|
|
14
|
+
resolve(fileURLToPath(new URL("../../../loader.js", import.meta.url))),
|
|
15
|
+
];
|
|
16
|
+
for (const candidate of candidates) {
|
|
17
|
+
if (existsSync(candidate))
|
|
18
|
+
return candidate;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
export function buildProjectWorkflowMcpServerConfig(projectRoot, env = process.env) {
|
|
23
|
+
const resolvedProjectRoot = resolve(projectRoot);
|
|
24
|
+
const gsdCliPath = resolveBundledGsdCliPath(env);
|
|
25
|
+
const launch = detectWorkflowMcpLaunchConfig(resolvedProjectRoot, {
|
|
26
|
+
...env,
|
|
27
|
+
...(gsdCliPath ? { GSD_CLI_PATH: gsdCliPath, GSD_BIN_PATH: gsdCliPath } : {}),
|
|
28
|
+
});
|
|
29
|
+
if (!launch) {
|
|
30
|
+
throw new Error("Unable to resolve the GSD workflow MCP server. Build this checkout or install gsd-mcp-server on PATH.");
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
command: launch.command,
|
|
34
|
+
...(launch.args && launch.args.length > 0 ? { args: launch.args } : {}),
|
|
35
|
+
...(launch.cwd ? { cwd: launch.cwd } : {}),
|
|
36
|
+
...(launch.env ? { env: launch.env } : {}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function readExistingConfig(configPath) {
|
|
40
|
+
if (!existsSync(configPath))
|
|
41
|
+
return {};
|
|
42
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
43
|
+
try {
|
|
44
|
+
const parsed = JSON.parse(raw);
|
|
45
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
throw new Error(`Failed to parse ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export function ensureProjectWorkflowMcpConfig(projectRoot, env = process.env) {
|
|
52
|
+
const resolvedProjectRoot = resolve(projectRoot);
|
|
53
|
+
assertSafeDirectory(resolvedProjectRoot);
|
|
54
|
+
const configPath = resolve(resolvedProjectRoot, ".mcp.json");
|
|
55
|
+
const existing = readExistingConfig(configPath);
|
|
56
|
+
const desiredServer = buildProjectWorkflowMcpServerConfig(resolvedProjectRoot, env);
|
|
57
|
+
const previousServers = existing.mcpServers ?? {};
|
|
58
|
+
const nextServers = {
|
|
59
|
+
...previousServers,
|
|
60
|
+
[GSD_WORKFLOW_MCP_SERVER_NAME]: desiredServer,
|
|
61
|
+
};
|
|
62
|
+
const alreadyPresent = existsSync(configPath);
|
|
63
|
+
const unchanged = JSON.stringify(previousServers[GSD_WORKFLOW_MCP_SERVER_NAME] ?? null)
|
|
64
|
+
=== JSON.stringify(desiredServer)
|
|
65
|
+
&& existing.mcpServers !== undefined;
|
|
66
|
+
if (unchanged) {
|
|
67
|
+
return {
|
|
68
|
+
configPath,
|
|
69
|
+
serverName: GSD_WORKFLOW_MCP_SERVER_NAME,
|
|
70
|
+
status: "unchanged",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const nextConfig = {
|
|
74
|
+
...existing,
|
|
75
|
+
mcpServers: nextServers,
|
|
76
|
+
};
|
|
77
|
+
writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf-8");
|
|
78
|
+
return {
|
|
79
|
+
configPath,
|
|
80
|
+
serverName: GSD_WORKFLOW_MCP_SERVER_NAME,
|
|
81
|
+
status: alreadyPresent ? "updated" : "created",
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -13,7 +13,7 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
|
13
13
|
import { debugCount, debugTime } from './debug-logger.js';
|
|
14
14
|
import { logWarning, logError } from './workflow-logger.js';
|
|
15
15
|
import { extractVerdict } from './verdict-parser.js';
|
|
16
|
-
import { isDbAvailable, getAllMilestones, getMilestone, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, insertMilestone, insertSlice, insertTask, updateTaskStatus, getPendingSliceGateCount, } from './gsd-db.js';
|
|
16
|
+
import { isDbAvailable, wasDbOpenAttempted, getAllMilestones, getMilestone, getMilestoneSlices, getSliceTasks, getReplanHistory, getSlice, insertMilestone, insertSlice, insertTask, updateTaskStatus, getPendingSliceGateCount, } from './gsd-db.js';
|
|
17
17
|
/**
|
|
18
18
|
* A "ghost" milestone directory contains only META.json (and no substantive
|
|
19
19
|
* files like CONTEXT, CONTEXT-DRAFT, ROADMAP, or SUMMARY). These appear when
|
|
@@ -200,7 +200,12 @@ export async function deriveState(basePath) {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
else {
|
|
203
|
-
|
|
203
|
+
// Only warn when DB initialization was attempted and failed — not when
|
|
204
|
+
// the DB simply hasn't been opened yet (e.g. during before_agent_start
|
|
205
|
+
// context injection which runs before any tool invocation opens the DB).
|
|
206
|
+
if (wasDbOpenAttempted()) {
|
|
207
|
+
logWarning("state", "DB unavailable — using filesystem state derivation (degraded mode)");
|
|
208
|
+
}
|
|
204
209
|
result = await _deriveStateImpl(basePath);
|
|
205
210
|
_telemetry.markdownDeriveCount++;
|
|
206
211
|
}
|
|
@@ -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
|
const MCP_WORKFLOW_TOOL_SURFACE = new Set([
|
|
5
6
|
"gsd_complete_milestone",
|
|
6
7
|
"gsd_complete_task",
|
|
@@ -47,23 +48,91 @@ function lookupCommand(command, platform = process.platform) {
|
|
|
47
48
|
return null;
|
|
48
49
|
}
|
|
49
50
|
}
|
|
51
|
+
function findWorkflowCliFromAncestorPath(startPath) {
|
|
52
|
+
let current = resolve(startPath);
|
|
53
|
+
while (true) {
|
|
54
|
+
const candidate = resolve(current, "packages", "mcp-server", "dist", "cli.js");
|
|
55
|
+
if (existsSync(candidate))
|
|
56
|
+
return candidate;
|
|
57
|
+
const parent = dirname(current);
|
|
58
|
+
if (parent === current)
|
|
59
|
+
break;
|
|
60
|
+
current = parent;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
function getBundledWorkflowMcpCliPath(env) {
|
|
65
|
+
const envAnchors = [
|
|
66
|
+
env.GSD_BIN_PATH?.trim(),
|
|
67
|
+
env.GSD_CLI_PATH?.trim(),
|
|
68
|
+
env.GSD_WORKFLOW_PATH?.trim(),
|
|
69
|
+
].filter((value) => typeof value === "string" && value.length > 0);
|
|
70
|
+
for (const anchor of envAnchors) {
|
|
71
|
+
const candidate = findWorkflowCliFromAncestorPath(anchor);
|
|
72
|
+
if (candidate)
|
|
73
|
+
return candidate;
|
|
74
|
+
}
|
|
75
|
+
const candidates = [
|
|
76
|
+
resolve(fileURLToPath(new URL("../../../../packages/mcp-server/dist/cli.js", import.meta.url))),
|
|
77
|
+
resolve(fileURLToPath(new URL("../../../../../packages/mcp-server/dist/cli.js", import.meta.url))),
|
|
78
|
+
];
|
|
79
|
+
for (const bundledCli of candidates) {
|
|
80
|
+
if (existsSync(bundledCli))
|
|
81
|
+
return bundledCli;
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
function getBundledWorkflowExecutorModulePath() {
|
|
86
|
+
const candidates = [
|
|
87
|
+
resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/tools/workflow-tool-executors.js", import.meta.url))),
|
|
88
|
+
resolve(fileURLToPath(new URL("./tools/workflow-tool-executors.js", import.meta.url))),
|
|
89
|
+
resolve(fileURLToPath(new URL("./tools/workflow-tool-executors.ts", import.meta.url))),
|
|
90
|
+
];
|
|
91
|
+
for (const candidate of candidates) {
|
|
92
|
+
if (existsSync(candidate))
|
|
93
|
+
return candidate;
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
function getBundledWorkflowWriteGateModulePath() {
|
|
98
|
+
const candidates = [
|
|
99
|
+
resolve(fileURLToPath(new URL("../../../../dist/resources/extensions/gsd/bootstrap/write-gate.js", import.meta.url))),
|
|
100
|
+
resolve(fileURLToPath(new URL("./bootstrap/write-gate.js", import.meta.url))),
|
|
101
|
+
resolve(fileURLToPath(new URL("./bootstrap/write-gate.ts", import.meta.url))),
|
|
102
|
+
];
|
|
103
|
+
for (const candidate of candidates) {
|
|
104
|
+
if (existsSync(candidate))
|
|
105
|
+
return candidate;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
function buildWorkflowLaunchEnv(projectRoot, gsdCliPath, explicitEnv) {
|
|
110
|
+
const executorModulePath = getBundledWorkflowExecutorModulePath();
|
|
111
|
+
const writeGateModulePath = getBundledWorkflowWriteGateModulePath();
|
|
112
|
+
return {
|
|
113
|
+
...(explicitEnv ?? {}),
|
|
114
|
+
...(gsdCliPath ? { GSD_CLI_PATH: gsdCliPath } : {}),
|
|
115
|
+
...(executorModulePath ? { GSD_WORKFLOW_EXECUTORS_MODULE: executorModulePath } : {}),
|
|
116
|
+
...(writeGateModulePath ? { GSD_WORKFLOW_WRITE_GATE_MODULE: writeGateModulePath } : {}),
|
|
117
|
+
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
118
|
+
GSD_WORKFLOW_PROJECT_ROOT: projectRoot,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
50
121
|
export function detectWorkflowMcpLaunchConfig(projectRoot = process.cwd(), env = process.env) {
|
|
51
122
|
const name = env.GSD_WORKFLOW_MCP_NAME?.trim() || "gsd-workflow";
|
|
52
123
|
const explicitCommand = env.GSD_WORKFLOW_MCP_COMMAND?.trim();
|
|
53
124
|
const explicitArgs = parseJsonEnv(env, "GSD_WORKFLOW_MCP_ARGS");
|
|
54
125
|
const explicitEnv = parseJsonEnv(env, "GSD_WORKFLOW_MCP_ENV");
|
|
55
126
|
const explicitCwd = env.GSD_WORKFLOW_MCP_CWD?.trim();
|
|
127
|
+
const gsdCliPath = env.GSD_CLI_PATH?.trim() || env.GSD_BIN_PATH?.trim();
|
|
56
128
|
const workflowProjectRoot = explicitEnv?.GSD_WORKFLOW_PROJECT_ROOT?.trim() ||
|
|
57
129
|
env.GSD_WORKFLOW_PROJECT_ROOT?.trim() ||
|
|
130
|
+
env.GSD_PROJECT_ROOT?.trim() ||
|
|
58
131
|
explicitCwd ||
|
|
59
132
|
projectRoot;
|
|
133
|
+
const resolvedWorkflowProjectRoot = resolve(workflowProjectRoot);
|
|
60
134
|
if (explicitCommand) {
|
|
61
|
-
const launchEnv =
|
|
62
|
-
...(explicitEnv ?? {}),
|
|
63
|
-
...(env.GSD_CLI_PATH ? { GSD_CLI_PATH: env.GSD_CLI_PATH } : {}),
|
|
64
|
-
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
65
|
-
GSD_WORKFLOW_PROJECT_ROOT: resolve(workflowProjectRoot),
|
|
66
|
-
};
|
|
135
|
+
const launchEnv = buildWorkflowLaunchEnv(resolve(workflowProjectRoot), gsdCliPath, explicitEnv);
|
|
67
136
|
return {
|
|
68
137
|
name,
|
|
69
138
|
command: explicitCommand,
|
|
@@ -72,18 +141,24 @@ export function detectWorkflowMcpLaunchConfig(projectRoot = process.cwd(), env =
|
|
|
72
141
|
env: Object.keys(launchEnv).length > 0 ? launchEnv : undefined,
|
|
73
142
|
};
|
|
74
143
|
}
|
|
75
|
-
const distCli = resolve(
|
|
144
|
+
const distCli = resolve(resolvedWorkflowProjectRoot, "packages", "mcp-server", "dist", "cli.js");
|
|
76
145
|
if (existsSync(distCli)) {
|
|
77
146
|
return {
|
|
78
147
|
name,
|
|
79
148
|
command: process.execPath,
|
|
80
149
|
args: [distCli],
|
|
81
|
-
cwd:
|
|
82
|
-
env:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
150
|
+
cwd: resolvedWorkflowProjectRoot,
|
|
151
|
+
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
const bundledCli = getBundledWorkflowMcpCliPath(env);
|
|
155
|
+
if (bundledCli) {
|
|
156
|
+
return {
|
|
157
|
+
name,
|
|
158
|
+
command: process.execPath,
|
|
159
|
+
args: [bundledCli],
|
|
160
|
+
cwd: resolvedWorkflowProjectRoot,
|
|
161
|
+
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
|
|
87
162
|
};
|
|
88
163
|
}
|
|
89
164
|
const binPath = lookupCommand("gsd-mcp-server");
|
|
@@ -91,11 +166,7 @@ export function detectWorkflowMcpLaunchConfig(projectRoot = process.cwd(), env =
|
|
|
91
166
|
return {
|
|
92
167
|
name,
|
|
93
168
|
command: binPath,
|
|
94
|
-
env:
|
|
95
|
-
...(env.GSD_CLI_PATH ? { GSD_CLI_PATH: env.GSD_CLI_PATH } : {}),
|
|
96
|
-
GSD_PERSIST_WRITE_GATE_STATE: "1",
|
|
97
|
-
GSD_WORKFLOW_PROJECT_ROOT: resolve(projectRoot),
|
|
98
|
-
},
|
|
169
|
+
env: buildWorkflowLaunchEnv(resolvedWorkflowProjectRoot, gsdCliPath),
|
|
99
170
|
};
|
|
100
171
|
}
|
|
101
172
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
WMDT_0C0XDkBKtsAI_AX4
|
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"/_not-found/page": "/_not-found",
|
|
3
3
|
"/_global-error/page": "/_global-error",
|
|
4
|
-
"/api/boot/route": "/api/boot",
|
|
5
4
|
"/api/bridge-terminal/resize/route": "/api/bridge-terminal/resize",
|
|
6
5
|
"/api/bridge-terminal/input/route": "/api/bridge-terminal/input",
|
|
6
|
+
"/api/boot/route": "/api/boot",
|
|
7
7
|
"/api/bridge-terminal/stream/route": "/api/bridge-terminal/stream",
|
|
8
|
-
"/api/browse-directories/route": "/api/browse-directories",
|
|
9
|
-
"/api/captures/route": "/api/captures",
|
|
10
|
-
"/api/cleanup/route": "/api/cleanup",
|
|
11
8
|
"/api/dev-mode/route": "/api/dev-mode",
|
|
9
|
+
"/api/cleanup/route": "/api/cleanup",
|
|
12
10
|
"/api/doctor/route": "/api/doctor",
|
|
11
|
+
"/api/captures/route": "/api/captures",
|
|
13
12
|
"/api/export-data/route": "/api/export-data",
|
|
14
|
-
"/api/
|
|
13
|
+
"/api/browse-directories/route": "/api/browse-directories",
|
|
15
14
|
"/api/forensics/route": "/api/forensics",
|
|
16
|
-
"/api/git/route": "/api/git",
|
|
17
15
|
"/api/history/route": "/api/history",
|
|
16
|
+
"/api/git/route": "/api/git",
|
|
18
17
|
"/api/hooks/route": "/api/hooks",
|
|
19
18
|
"/api/inspect/route": "/api/inspect",
|
|
20
19
|
"/api/knowledge/route": "/api/knowledge",
|
|
21
|
-
"/api/
|
|
20
|
+
"/api/experimental/route": "/api/experimental",
|
|
22
21
|
"/api/live-state/route": "/api/live-state",
|
|
23
22
|
"/api/notifications/route": "/api/notifications",
|
|
24
|
-
"/api/onboarding/route": "/api/onboarding",
|
|
25
23
|
"/api/preferences/route": "/api/preferences",
|
|
26
24
|
"/api/recovery/route": "/api/recovery",
|
|
25
|
+
"/api/onboarding/route": "/api/onboarding",
|
|
27
26
|
"/api/projects/route": "/api/projects",
|
|
28
27
|
"/api/session/browser/route": "/api/session/browser",
|
|
29
|
-
"/api/session/command/route": "/api/session/command",
|
|
30
28
|
"/api/session/events/route": "/api/session/events",
|
|
31
|
-
"/api/session/
|
|
32
|
-
"/api/remote-questions/route": "/api/remote-questions",
|
|
29
|
+
"/api/session/command/route": "/api/session/command",
|
|
33
30
|
"/api/settings-data/route": "/api/settings-data",
|
|
34
31
|
"/api/shutdown/route": "/api/shutdown",
|
|
32
|
+
"/api/session/manage/route": "/api/session/manage",
|
|
35
33
|
"/api/skill-health/route": "/api/skill-health",
|
|
34
|
+
"/api/files/route": "/api/files",
|
|
36
35
|
"/api/steer/route": "/api/steer",
|
|
37
|
-
"/api/switch-root/route": "/api/switch-root",
|
|
38
36
|
"/api/terminal/input/route": "/api/terminal/input",
|
|
39
37
|
"/api/terminal/resize/route": "/api/terminal/resize",
|
|
38
|
+
"/api/switch-root/route": "/api/switch-root",
|
|
40
39
|
"/api/terminal/sessions/route": "/api/terminal/sessions",
|
|
41
40
|
"/api/terminal/stream/route": "/api/terminal/stream",
|
|
42
|
-
"/api/terminal/upload/route": "/api/terminal/upload",
|
|
43
41
|
"/api/undo/route": "/api/undo",
|
|
44
|
-
"/api/update/route": "/api/update",
|
|
45
42
|
"/api/visualizer/route": "/api/visualizer",
|
|
43
|
+
"/api/terminal/upload/route": "/api/terminal/upload",
|
|
44
|
+
"/api/remote-questions/route": "/api/remote-questions",
|
|
45
|
+
"/api/update/route": "/api/update",
|
|
46
46
|
"/page": "/"
|
|
47
47
|
}
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
],
|
|
5
5
|
"devFiles": [],
|
|
6
6
|
"lowPriorityFiles": [
|
|
7
|
-
"static/
|
|
8
|
-
"static/
|
|
7
|
+
"static/WMDT_0C0XDkBKtsAI_AX4/_buildManifest.js",
|
|
8
|
+
"static/WMDT_0C0XDkBKtsAI_AX4/_ssgManifest.js"
|
|
9
9
|
],
|
|
10
10
|
"rootMainFiles": [
|
|
11
|
-
"static/chunks/webpack-
|
|
11
|
+
"static/chunks/webpack-6e4d7e9a4f57bed4.js",
|
|
12
12
|
"static/chunks/4bd1b696-e356ca5ba0218e27.js",
|
|
13
13
|
"static/chunks/3794-42fdce068d44fa4f.js",
|
|
14
14
|
"static/chunks/main-app-fdab67f7802d7832.js"
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"dynamicRoutes": {},
|
|
79
79
|
"notFoundRoutes": [],
|
|
80
80
|
"preview": {
|
|
81
|
-
"previewModeId": "
|
|
82
|
-
"previewModeSigningKey": "
|
|
83
|
-
"previewModeEncryptionKey": "
|
|
81
|
+
"previewModeId": "34187a5617b6cb6f15e59ced43db8d2b",
|
|
82
|
+
"previewModeSigningKey": "a1e45a0ba7e5084958c94d9eb4055b405d298537344b19b9d1739fef8f10df51",
|
|
83
|
+
"previewModeEncryptionKey": "21ffd377f053491c7bd1c2156def3bad40f4fe9e03a34ab34d5ddf4fd361b1fc"
|
|
84
84
|
}
|
|
85
85
|
}
|