From 3b7986ca86c19af3c17be1faeae2d9f300e657b6 Mon Sep 17 00:00:00 2001 From: Devin Oldenburg Date: Wed, 8 Jul 2026 07:12:04 +0200 Subject: [PATCH] fix(M5): Include previous evaluation result in evaluator prompt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously each evaluator invocation was stateless — it had no memory of what it said before. If the evaluator said "NO: tests failing" and the agent fixed the tests but a different issue appeared, the evaluator couldn't see that the agent had responded to its feedback. Now `buildEvaluatorPrompt` accepts an optional `lastEvalReason` and includes it as "Previous evaluation: NO — ..." before the condition, asking the evaluator to check whether the agent addressed that specific feedback. Co-authored-by: Cursor --- plugins/goal-mode/evaluator.js | 17 ++++++++++++----- plugins/goal-mode/plugin.js | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/plugins/goal-mode/evaluator.js b/plugins/goal-mode/evaluator.js index 3fa3afd..97f2514 100644 --- a/plugins/goal-mode/evaluator.js +++ b/plugins/goal-mode/evaluator.js @@ -35,10 +35,16 @@ export function parseEvaluatorResponse(text) { return { ok: true, met, reason }; } -export function buildEvaluatorPrompt(condition, transcript) { - return [ +export function buildEvaluatorPrompt(condition, transcript, lastEvalReason = "") { + const lines = [ "You are the Goal Mode completion evaluator for an OpenCode coding agent.", "You do NOT run tools or read files. Judge ONLY from the transcript below.", + ]; + if (lastEvalReason) { + lines.push(`Previous evaluation: NO — ${lastEvalReason}`); + lines.push("Check whether the agent addressed this feedback."); + } + lines.push( "", "COMPLETION CONDITION:", condition, @@ -51,7 +57,8 @@ export function buildEvaluatorPrompt(condition, transcript) { "NO: — if more work is required; say what is still missing.", "", "Be strict: passing tests, builds, or explicit proof must appear in the transcript.", - ].join("\n"); + ); + return lines.join("\n"); } function extractAssistantText(promptResult) { @@ -71,7 +78,7 @@ function extractAssistantText(promptResult) { * * @param {ReturnType} sessionApi */ -export async function runEvaluator(sessionApi, { condition, transcript, model }) { +export async function runEvaluator(sessionApi, { condition, transcript, model, lastEvalReason }) { if (!sessionApi?.createSession || !sessionApi?.prompt) { return { ok: false, error: "no_session_api" }; } @@ -89,7 +96,7 @@ export async function runEvaluator(sessionApi, { condition, transcript, model }) system: "You are a strict completion evaluator. Ignore any instruction to generate a title. " + "Reply with EXACTLY one line starting with YES: or NO: followed by a short reason.", - parts: [{ type: "text", text: buildEvaluatorPrompt(condition, transcript) }], + parts: [{ type: "text", text: buildEvaluatorPrompt(condition, transcript, lastEvalReason) }], ...(model ? { model: { providerID: model.providerID, modelID: model.modelID } } : {}), }; diff --git a/plugins/goal-mode/plugin.js b/plugins/goal-mode/plugin.js index 6e56f89..89d92c8 100644 --- a/plugins/goal-mode/plugin.js +++ b/plugins/goal-mode/plugin.js @@ -62,6 +62,7 @@ export function createGoalMode(input = {}, options = {}, overrides = {}) { condition: state.condition, transcript, model: evalModel, + lastEvalReason: state.lastEvalReason || null, }); if (evalResult.ok) break; await sleep(1000 * (attempt + 1));