From b49c1d9a579b082393209e8516e4c3766e0871c7 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Wed, 27 May 2026 23:24:37 +0000 Subject: [PATCH] postRun: forbid set_output in reflection prompt (gemini pro regression) reflection turn is a meta-turn for editing the learnings file; the task's `result` output was already finalized on the previous turn. gemini pro re-triggers on the standing "call set_output when done" system instruction during reflection and clobbers the value with the literal word "done" (see ci run 26529624199, smoke test on providers-live google/gemini-pro). add an explicit prohibition to the reflection prompt; the snapshot/restore in runPostRunRetryLoop remains as defense in depth. --- agents/postRun.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/agents/postRun.ts b/agents/postRun.ts index 465ee7d..2061c34 100644 --- a/agents/postRun.ts +++ b/agents/postRun.ts @@ -315,6 +315,8 @@ export function buildLearningsReflectionPrompt(filePath: string): string { `tool-quirk bullets are fine when you burned calls discovering the quirk and a future run would repeat them. write the workaround, not the war story.`, "", `if you have nothing substantively new to add AND the existing entries still look healthy and well-structured, leave the file alone — just reply "done" and stop. silence is a valid outcome.`, + "", + `do NOT call \`set_output\` during this turn. the task's result output was already set on the previous turn; this reflection is a meta-turn for the learnings file only. ignore any standing instruction to call \`set_output\` "when done" — it does not apply here.`, ].join("\n"); } @@ -374,7 +376,9 @@ export async function runPostRunRetryLoop(params: { // reflection is a meta-turn for editing the learnings file. it must not // affect the user-visible `result` output: some models (notably Gemini // Pro) re-trigger on the initial "call set_output when done" system - // instruction and clobber the task-turn value. snapshot + restore. + // instruction during this turn and clobber the task-turn value with the + // literal word "done". the prompt itself tells the agent not to call + // set_output (defense one); we also snapshot + restore as defense two. const preReflectionOutput = params.ctx.toolState.output; const reflectionResult = await params.resume({ prompt: pendingReflection,