From fecf32dc1ec0ddd41d6136e8acdf541ce8fc9fae Mon Sep 17 00:00:00 2001 From: HyperDev1 Date: Fri, 20 Mar 2026 01:50:08 +0300 Subject: [PATCH] fix: correct GSD-WORKFLOW.md fallback path and sync to agentDir (#1375) The fallback path for GSD-WORKFLOW.md still referenced the legacy .pi directory (~/.pi/GSD-WORKFLOW.md) instead of the correct .gsd/agent location. This broke workflow dispatch when GSD_WORKFLOW_PATH env var was not set. - Update fallback path from ~/.pi/ to ~/.gsd/agent/ in three call sites (dispatchWorkflow, dispatchDoctorHeal, handleTriage) - Sync GSD-WORKFLOW.md to agentDir during initResources() as a fallback for alternative entry points that may not set the env var Co-authored-by: Berat Can Co-authored-by: Claude Opus 4.6 (1M context) --- src/resource-loader.ts | 9 ++++++++- src/resources/extensions/gsd/commands-handlers.ts | 4 ++-- src/resources/extensions/gsd/guided-flow.ts | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/resource-loader.ts b/src/resource-loader.ts index 2e1a2c688..66f4ad617 100644 --- a/src/resource-loader.ts +++ b/src/resource-loader.ts @@ -240,7 +240,7 @@ function copyDirRecursive(src: string, dest: string): void { * - extensions/ → ~/.gsd/agent/extensions/ (overwrite when version changes) * - agents/ → ~/.gsd/agent/agents/ (overwrite when version changes) * - skills/ → ~/.gsd/agent/skills/ (overwrite when version changes) - * - GSD-WORKFLOW.md is read directly from bundled path via GSD_WORKFLOW_PATH env var + * - GSD-WORKFLOW.md → ~/.gsd/agent/GSD-WORKFLOW.md (fallback for env var miss) * * Skips the copy when the managed-resources.json version matches the current * GSD version, avoiding ~128ms of synchronous cpSync on every startup. @@ -270,6 +270,13 @@ export function initResources(agentDir: string): void { syncResourceDir(join(resourcesDir, 'agents'), join(agentDir, 'agents')) syncResourceDir(join(resourcesDir, 'skills'), join(agentDir, 'skills')) + // Sync GSD-WORKFLOW.md to agentDir as a fallback for when GSD_WORKFLOW_PATH + // env var is not set (e.g. fork/dev builds, alternative entry points). + const workflowSrc = join(resourcesDir, 'GSD-WORKFLOW.md') + if (existsSync(workflowSrc)) { + try { copyFileSync(workflowSrc, join(agentDir, 'GSD-WORKFLOW.md')) } catch { /* non-fatal */ } + } + // Ensure all newly copied files are owner-writable so the next run can // overwrite them (covers extensions, agents, and skills in one walk). makeTreeWritable(agentDir) diff --git a/src/resources/extensions/gsd/commands-handlers.ts b/src/resources/extensions/gsd/commands-handlers.ts index bfe18a3e4..46e3ab810 100644 --- a/src/resources/extensions/gsd/commands-handlers.ts +++ b/src/resources/extensions/gsd/commands-handlers.ts @@ -24,7 +24,7 @@ import { projectRoot } from "./commands.js"; import { loadPrompt } from "./prompt-loader.js"; export function dispatchDoctorHeal(pi: ExtensionAPI, scope: string | undefined, reportText: string, structuredIssues: string): void { - const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".pi", "GSD-WORKFLOW.md"); + const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".gsd", "agent", "GSD-WORKFLOW.md"); const workflow = readFileSync(workflowPath, "utf-8"); const prompt = loadPrompt("doctor-heal", { doctorSummary: reportText, @@ -187,7 +187,7 @@ export async function handleTriage(ctx: ExtensionCommandContext, pi: ExtensionAP roadmapContext: roadmapContext || "(no active roadmap)", }); - const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".pi", "GSD-WORKFLOW.md"); + const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".gsd", "agent", "GSD-WORKFLOW.md"); const workflow = readFileSync(workflowPath, "utf-8"); pi.sendMessage( diff --git a/src/resources/extensions/gsd/guided-flow.ts b/src/resources/extensions/gsd/guided-flow.ts index e22aa3a33..96faf73e4 100644 --- a/src/resources/extensions/gsd/guided-flow.ts +++ b/src/resources/extensions/gsd/guided-flow.ts @@ -191,7 +191,7 @@ type UIContext = ExtensionContext; * This is the only way the wizard triggers work — everything else is the LLM's job. */ function dispatchWorkflow(pi: ExtensionAPI, note: string, customType = "gsd-run"): void { - const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".pi", "GSD-WORKFLOW.md"); + const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".gsd", "agent", "GSD-WORKFLOW.md"); const workflow = readFileSync(workflowPath, "utf-8"); pi.sendMessage(