diff --git a/src/selfhost/ai.ts b/src/selfhost/ai.ts index cf5b9f1f92..203c1b5e90 100644 --- a/src/selfhost/ai.ts +++ b/src/selfhost/ai.ts @@ -75,7 +75,7 @@ function toCliPrompt(options: AiRunOptions, systemAppend: string | undefined): s .join("\n\n"); } -function prependCodexSystemAppend(prompt: string, systemAppend: string | undefined): string { +function prependCliSystemAppend(prompt: string, systemAppend: string | undefined): string { return systemAppend ? `ADDITIONAL SYSTEM INSTRUCTIONS:\n${systemAppend}\n\n${prompt}` : prompt; @@ -736,10 +736,9 @@ export function createClaudeCodeAi(parentEnv: Record OTEL_METRIC_EXPORT_INTERVAL: parentEnv.OTEL_METRIC_EXPORT_INTERVAL, }); const systemAppend = normalizedSystemAppend(options); - const prompt = toCliPrompt(options, systemAppend); + const prompt = prependCliSystemAppend(toCliPrompt(options, systemAppend), systemAppend); const spawn = spawnImpl ?? (await defaultSpawn()); const args = ["--print", "--output-format", "json", "--model", claudeModel, "--permission-mode", "plan", "--effort", effort, "--disallowedTools", "Bash,Edit,Write,WebFetch,WebSearch"]; - if (systemAppend) args.push("--append-system-prompt", systemAppend); attempted = true; const { stdout, code, stderr, timedOut } = await spawn( "claude", @@ -808,7 +807,7 @@ export function createCodexAi( await authCheckImpl(parentEnv); const env = codexCliEnv(parentEnv); const systemAppend = normalizedSystemAppend(options); - const prompt = prependCodexSystemAppend(toCliPrompt(options, systemAppend), systemAppend); + const prompt = prependCliSystemAppend(toCliPrompt(options, systemAppend), systemAppend); const spawn = spawnImpl ?? (await defaultSpawn()); const args = ["exec", "--json", "--skip-git-repo-check", "--sandbox", "read-only"]; if (codexModel) args.push("--model", codexModel); diff --git a/test/unit/selfhost-ai.test.ts b/test/unit/selfhost-ai.test.ts index c1486d261e..ddda1b71a3 100644 --- a/test/unit/selfhost-ai.test.ts +++ b/test/unit/selfhost-ai.test.ts @@ -979,7 +979,7 @@ describe("subscription CLI helpers + fail-safe", () => { expect(seen[seen.indexOf("--effort") + 1]).toBe("medium"); }); - it("Claude Code passes systemAppend through --append-system-prompt and strips the duplicate stdin copy (#1471)", async () => { + it("Claude Code keeps systemAppend out of argv and supplies it through stdin once (#1471)", async () => { const systemAppend = "REPOSITORY REVIEW INSTRUCTIONS: Follow async-error conventions."; let seen: string[] = []; let capturedInput = ""; @@ -995,10 +995,11 @@ describe("subscription CLI helpers + fail-safe", () => { ], systemAppend, }); - expect(seen[seen.indexOf("--append-system-prompt") + 1]).toBe(systemAppend); + expect(seen).not.toContain("--append-system-prompt"); + expect(seen).not.toContain(systemAppend); expect(capturedInput).toContain("Base system."); expect(capturedInput).toContain("Review this diff."); - expect(capturedInput).not.toContain(systemAppend); + expect(countOccurrences(capturedInput, systemAppend)).toBe(1); await createClaudeCodeAi({ CLAUDE_CODE_OAUTH_TOKEN: "t" }, cap).run("", { prompt: "Review this diff.",