diff --git a/packages/coding-agent/src/system-prompt.ts b/packages/coding-agent/src/system-prompt.ts index 58c9d86f7..d648da638 100644 --- a/packages/coding-agent/src/system-prompt.ts +++ b/packages/coding-agent/src/system-prompt.ts @@ -505,9 +505,15 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}): return result.value; } - const systemPromptCustomizationPromise = logger.time("loadSystemPromptFiles", loadSystemPromptFiles, { - cwd: resolvedCwd, - }); + // Caller-supplied `customPrompt` / `resolvedCustomPrompt` owns block 0; the + // secondary capability-path `SYSTEM.md` walk-up MUST NOT silently augment it, + // because that would defeat CLI precedence over project/user `SYSTEM.md`. + const callerControlsCustomPrompt = + (typeof providedResolvedCustomPrompt === "string" && providedResolvedCustomPrompt.length > 0) || + (typeof customPrompt === "string" && customPrompt.length > 0); + const systemPromptCustomizationPromise: Promise = callerControlsCustomPrompt + ? Promise.resolve(null) + : logger.time("loadSystemPromptFiles", loadSystemPromptFiles, { cwd: resolvedCwd }); const contextFilesPromise = providedContextFiles ? Promise.resolve(providedContextFiles) : logger.time("loadProjectContextFiles", loadProjectContextFiles, { cwd: resolvedCwd }); diff --git a/packages/coding-agent/test/system-prompt-dedup.test.ts b/packages/coding-agent/test/system-prompt-dedup.test.ts index 2c67dd9eb..69f74851c 100644 --- a/packages/coding-agent/test/system-prompt-dedup.test.ts +++ b/packages/coding-agent/test/system-prompt-dedup.test.ts @@ -106,6 +106,33 @@ describe("SYSTEM.md prompt assembly", () => { expect(promptText).not.toContain("File content that must not replace the prompt."); }); + it("suppresses discovered SYSTEM.md when the caller supplies a custom prompt", async () => { + const projectDir = path.join(tempDir, "project"); + fs.mkdirSync(path.join(projectDir, ".omp"), { recursive: true }); + fs.writeFileSync(path.join(projectDir, ".omp", "SYSTEM.md"), "Discovered project SYSTEM prompt"); + + const { systemPrompt } = await buildSystemPrompt({ + cwd: projectDir, + resolvedCustomPrompt: "CLI custom prompt", + contextFiles: [], + skills: [], + rules: [], + toolNames: ["read"], + tools: READ_TOOL, + workspaceTree: { + rootPath: projectDir, + rendered: "", + truncated: false, + totalLines: 0, + agentsMdFiles: [], + }, + }); + + const promptText = systemPrompt.join("\n\n"); + expect(promptText).toContain("CLI custom prompt"); + expect(promptText).not.toContain("Discovered project SYSTEM prompt"); + }); + it("prefers project SYSTEM.md over user SYSTEM.md", async () => { const projectDir = path.join(tempDir, "project"); fs.mkdirSync(path.join(projectDir, ".omp"), { recursive: true });