diff --git a/k8s/apps/agent-pod/coordinator-configmap.yaml b/k8s/apps/agent-pod/coordinator-configmap.yaml index 3f873ce..9899f6e 100644 --- a/k8s/apps/agent-pod/coordinator-configmap.yaml +++ b/k8s/apps/agent-pod/coordinator-configmap.yaml @@ -278,10 +278,24 @@ data: return { ok, sessionName: label }; } - function plannerPrompt(task, specHint) { + function plannerPrompt(task, specHint, judgeOnly) { + // judgeOnly (auto-discovered tasks only, see parseTaskBoard): planner + // itself decides whether the task is already done before planning it, + // reading tasks/INDEX.md's own status notes plus git log/current code -- + // replaces what used to be a separate judge pre-check call. One LLM round + // trip instead of two, and the same agent that's about to plan the task + // is the one deciding whether planning it is even necessary. + const decideStep = judgeOnly + ? `First, decide whether task ${task} is already fully implemented on this branch: check ` + + `\`git log --oneline --grep '${task}'\`, tasks/INDEX.md's own status notes for this task, and the current ` + + `code directly against its spec (${specHint})'s acceptance criteria. Write your decision to ` + + `.task-result-${task} as a single "VERDICT: PASS" (already done, no further work needed) or ` + + `"VERDICT: FAIL" (needs work) line plus one line of rationale. If VERDICT is FAIL, continue below and ` + + `draft the plan in this same turn; if VERDICT is PASS, skip the rest and go straight to the touch step.\n\n` + : ""; return ( - `Use the planner skill to draft PLAN.md for task ${task}, reading its spec (${specHint}). PLAN.md is scratch ` + - `state for this harness, not a deliverable -- do NOT commit it or add it to git. ` + + `${decideStep}Use the planner skill to draft PLAN.md for task ${task}, reading its spec (${specHint}). ` + + `PLAN.md is scratch state for this harness, not a deliverable -- do NOT commit it or add it to git. ` + `Then run: touch .stage-done-${task}-planner` ); } @@ -313,7 +327,10 @@ data: const MAX_PLAN_REVISIONS = 3; // Runs one task against the repo's shared role pool: planner drafts - // PLAN.md, investigator confirms it, then implementer and judge go back and + // PLAN.md (for auto-discovered tasks, first deciding off tasks/INDEX.md and + // the repo's own state whether the task is already done -- see + // plannerPrompt's judgeOnly branch; judge never does this pre-check), + // investigator confirms it, then implementer and judge go back and // forth -- judge's FAIL rationale lands in .task-result-, which the // next implementer attempt is told to read and address. After // MAX_IMPLEMENT_ATTEMPTS straight fails, the planner role is asked to judge @@ -360,18 +377,10 @@ data: // whatever the outcome, so it never bleeds into the next task's planner // call or sits around as stale harness clutter in the shared clone. try { - if (judgeOnly) { - const quick = await stage( - "judge", - `Task ${task} may already be implemented on this branch -- check ` + - `\`git log --oneline --grep '${task}'\` and the current code directly against its spec ` + - `(${specHint})'s acceptance criteria (no PLAN.md exists for this task yet). Write your ` + - `verdict to .task-result-${task} as a single "VERDICT: PASS" or "VERDICT: FAIL" line plus ` + - `one line of rationale, then run: touch .stage-done-${task}-judge-0`, - path.join(cwd, `.stage-done-${task}-judge-0`) - ); - if (!quick.ok) return abandon("judge", quick, 0); + let result = await stage("planner", plannerPrompt(task, specHint, judgeOnly), path.join(cwd, `.stage-done-${task}-planner`)); + if (!result.ok) return abandon("planner", result); + if (judgeOnly) { const quickText = fs.existsSync(resultFile) ? fs.readFileSync(resultFile, "utf8") : ""; if (parseVerdictLine(quickText, "VERDICT") === "PASS") { delete pipelineSession.activeTasks[task]; @@ -380,9 +389,6 @@ data: } } - let result = await stage("planner", plannerPrompt(task, specHint), path.join(cwd, `.stage-done-${task}-planner`)); - if (!result.ok) return abandon("planner", result); - result = await stage("investigator", investigatorPrompt(task), path.join(cwd, `.stage-done-${task}-investigator`)); if (!result.ok) return abandon("investigator", result);