fix(prompting): preserved CLI prompt precedence over SYSTEM.md
Skip the secondary loadSystemPromptFiles capability walk when the caller already controls block 0 via customPrompt/resolvedCustomPrompt, so project/user SYSTEM.md cannot silently augment a CLI --system-prompt override. Fixes #3014
This commit is contained in:
@@ -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<string | null> = callerControlsCustomPrompt
|
||||
? Promise.resolve(null)
|
||||
: logger.time("loadSystemPromptFiles", loadSystemPromptFiles, { cwd: resolvedCwd });
|
||||
const contextFilesPromise = providedContextFiles
|
||||
? Promise.resolve(providedContextFiles)
|
||||
: logger.time("loadProjectContextFiles", loadProjectContextFiles, { cwd: resolvedCwd });
|
||||
|
||||
@@ -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 });
|
||||
|
||||
Reference in New Issue
Block a user