fix(run): the FinalGuard nudge round can never replace a non-blank answer
executus CI / test (pull_request) Successful in 49s
executus CI / test (pull_request) Successful in 49s
Live regression (mort run d5ec39f4, 2026-07-15): a research run's page-cache
file false-positived the guard, and the nudge round's meta closer ("my
answer above stands as-is") REPLACED the real answer — hosts deliver
Output text plus separately-drained attachments, so the user received the
closer and never saw the answer.
New merge policy: the nudge round exists to make tool calls (queue the
delivery); its final text is discarded and recorded as a final_nudge_result
audit event, so a round that declined to queue stays observable without
reaching the user. The only exception is a blank original stop turn, where
the nudge round's text is the only answer there is. Messages/Usage still
merge (audit, PostRun, checkpoint continuity).
Additive on top of 007b753 (mort main pins that commit as a pseudo-version;
this branch must never be rewritten).
Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
+11
-4
@@ -20,10 +20,17 @@ import (
|
||||
// A non-empty nudge sends the loop back for ONE bounded extra round: the nudge
|
||||
// is appended to the SAME conversation as the next user turn and the agent
|
||||
// runs again with the same toolbox, capped at finalNudgeMaxSteps steps — enough
|
||||
// to deliver a stranded artifact (or correct the final text), not enough to
|
||||
// start a new project. The guard is consulted at most ONCE per run; the nudge
|
||||
// round's own stop turn is final. Multi-phase runs are not guarded (their
|
||||
// output contract is the phase pipeline's, not a delivery surface's).
|
||||
// to deliver a stranded artifact, not enough to start a new project. The guard
|
||||
// is consulted at most ONCE per run; the nudge round's own stop turn is final.
|
||||
// Multi-phase runs are not guarded (their output contract is the phase
|
||||
// pipeline's, not a delivery surface's).
|
||||
//
|
||||
// OUTPUT CONTRACT: the nudge round exists to make TOOL CALLS (queue the
|
||||
// delivery); its final TEXT is discarded — the run's Output stays the original
|
||||
// answer unless that answer was blank. A host's nudge message should say so
|
||||
// explicitly ("any text you write here is not shown to the user"), and must
|
||||
// not instruct the model to compose a corrected reply. Discarded nudge text is
|
||||
// recorded as a final_nudge_result audit event.
|
||||
//
|
||||
// The call runs on the run goroutine, inside the run's deadline, and is
|
||||
// panic-isolated: a guard panic is logged and treated as "" (the run's
|
||||
|
||||
Reference in New Issue
Block a user