mirror of
https://github.com/wassname/pi-plan.git
synced 2026-08-18 12:20:10 +08:00
persist judge transcript to .pi/judge/<stamp>.md and reference it from the sign-off log line
'Did the judge really re-run verify?' was unanswerable post-hoc; now every sign-off's full judge output survives on disk. Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
@@ -96,6 +96,8 @@ committing before sign-off is for durable evidence, not for the judge's visibili
|
||||
- accept: a sign-off line is appended to `## Log` and the goal is ticked `[x]` in the same write
|
||||
(exact goal-line match only; on wording drift the result asks the agent to tick it). The
|
||||
tool-written log line is the audit trail; a hand-tick without one shows in the diff.
|
||||
- every run saves the judge's full transcript to `.pi/judge/<stamp>.md`, referenced from the log
|
||||
line, so "did the judge really re-run verify?" stays answerable after the fact.
|
||||
- reject: the goal stays open and the agent gets the missing list.
|
||||
- judge ran but failed/errored/timed out, or returned no VERDICT line: accepted inconclusive,
|
||||
logged as such. There is no pre-emptive "no model" path -- a null judgeModel just omits
|
||||
|
||||
+16
-6
@@ -228,11 +228,21 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
|
||||
// decideSignOff runs the judge and derives the outcome + the one log line. judgeModel is never
|
||||
// checked pre-emptively: null just means pi's configured default runs (buildJudgeArgs omits
|
||||
// --model), so accepted_inconclusive always means "the judge ran but failed", never "no model".
|
||||
const outcome = await decideSignOff(
|
||||
{ goal: params.goal, plan, judgeModel },
|
||||
signal,
|
||||
(task) => runJudge(task, judgeModel, ctx.cwd, signal),
|
||||
);
|
||||
let judgeRaw: JudgeResult | null = null;
|
||||
const outcome = await decideSignOff({ goal: params.goal, plan, judgeModel }, signal, async (task) => {
|
||||
judgeRaw = await runJudge(task, judgeModel, ctx.cwd, signal);
|
||||
return judgeRaw;
|
||||
});
|
||||
// Persist the judge's full transcript so "did the judge really re-run verify?" is answerable
|
||||
// after the fact (dogfood finding: with only the one log line, an accept is unauditable).
|
||||
let transcriptNote = "";
|
||||
if (judgeRaw !== null) {
|
||||
const raw: JudgeResult = judgeRaw;
|
||||
mkdirSync(join(ctx.cwd, ".pi", "judge"), { recursive: true });
|
||||
const rel = `.pi/judge/${stamp().replace(/[: ]/g, "-")}.md`;
|
||||
writeFileSync(join(ctx.cwd, rel), `goal: ${params.goal}\nmodel: ${judgeModel ?? "pi default"}\nerror: ${raw.error ?? "none"}\n\n${raw.output}\n`);
|
||||
transcriptNote = ` (${rel})`;
|
||||
}
|
||||
if (outcome.logEntry) {
|
||||
// Sign-off write: tick the goal [x] (exact-subject match; dogfood showed agent bookkeeping
|
||||
// is the drift point) and append the audit log line, one write. On wording drift the tick
|
||||
@@ -246,7 +256,7 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
|
||||
? `\n\nGoal ticked [x] in ${PLAN_REL}.`
|
||||
: `\n\nNo exact goal line matched your wording -- tick it [x] in ${PLAN_REL} yourself.`;
|
||||
}
|
||||
writePlan(ctx, appendLog(updated, `${stamp()} ${outcome.logEntry}`));
|
||||
writePlan(ctx, appendLog(updated, `${stamp()} ${outcome.logEntry}${transcriptNote}`));
|
||||
updateWidget(ctx);
|
||||
return result(outcome.resultText + tickNote, outcome.isError);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user