Fix loop and judge
An exec node's fix_loop repairs the node and measures it again until it
passes. This page is the loop's contract: when it opens, what runs in each
cycle, and how the judge's verdict is read. For why loops and caps work the
way they do, see Caps and budgets.
Keys
| Key | Meaning |
|---|---|
tasks or steps | The repair. Runs as an ordered group, like a node's own steps. No task or step in it may take an on_failure. |
judge | Optional. One task of any kind, which may not take an on_failure. The shipped one is strict_judge. |
max_attempts | Optional, above 0. The loop's attempt limit. |
The loop's limits resolve narrowest last, each replacing only what it sets:
policy.yaml'sloops.<node>.fix_loopentry, else itsdefault(attemptsandwall_clock_s);- the node's
policy:max_attempts, andtimeout_minutesfor the wall clock; - the loop's own
max_attempts; - the work item's own
max_attempts(kraft item set-policy).
See Policy. A node with a fix_loop cannot
be read_only.
When the loop opens
After the node's tasks run (and after any on_failure recovery), Kraft reads
every measuring task's findings and records a findings_measured event. The
loop opens when either is true:
- a finding's severity is in
findings.loop_severitiesinpolicy.yaml(defaultcriticalandimportant); - a task failed without reporting any findings. Kraft writes one
criticalfinding for it, as a subprocess task describes.
Otherwise the node completes. Findings below the loop severities are kept and shown at the review gate.
One cycle
Each cycle runs these checks in order:
- A measuring task ended
needs_context: the item stops with its question. - Every failure came from a task Kraft runs itself (a
builtinorforgetask), and nothing else reported a finding: the item stops, because no worker commit can change the outcome. - A token or dollar budget is spent: the item stops.
- The judge, when it is due.
- The attempt count or wall clock is past its limit:
<node>.fix_loop exhausted after N fix cycle(s). - After a repair, the same set of loop-severity findings came back, or one
finding came back unchanged three cycles running:
stuck: ....
Steps 1 to 3 stop the item for you. Steps 5 and 6, and a judge's
stop_needs_human, leave the node stuck: its
escalation runs before the
item stops.
If nothing stopped the loop, Kraft records fix_cycle_started, runs the
repair, and measures the whole node again from its first step.
A repair that ends done, or that fails in an agent or subprocess task, spends
the attempt. A repair that was paused, rate limited or refused to start, or
whose builtin or forge step failed, did not try anything: Kraft gives the
attempt back (fix_cycle_refunded) instead of measuring again.
What a repair task is told
A repair task's own prompt is not used. Its harness, profile, model and skill
still are. Kraft writes its instruction instead:
- which tasks failed, or that a review reported findings;
- the loop-severity findings, each with its tag, a finding that was in the last
measurement marked
REPEAT; - the judge's reasoning, when the judge ran this cycle;
- once there are two rounds, every round so far, with any finding that was fixed and came back;
- the path of the previous attempt's result file and session summary.
The judge
The judge runs before every cycle except the first one of each entry into the node, which repairs without asking. It does not run when a steer from a person or a gate review is waiting to be delivered: the steer is the answer to the trend the judge would rule on.
Its own prompt is not used either. Its instruction lists every round so far
with each finding's tag, the attempts used of the limit, and the seconds used
of the wall clock. It answers in its result file:
verdict, and its reasoning in concerns.
verdict | What happens |
|---|---|
continue | The cycle goes ahead. The repair task gets concerns as the judge's reasoning. |
stop_needs_human | The node is stuck with judge: and the reasoning. |
stop_downgrade | The node completes with the remaining findings unresolved, and concerns is the note you see at the review gate. Only when no task in the node failed outright; otherwise the cycle goes ahead. |
Kraft reads a verdict only from a judge that ended done or
done_with_concerns. Any other status, a missing verdict or an unknown one
counts as continue. A verdict never buys a cycle past the attempt limit or
the wall clock: step 5 runs after the judge. A loop with no judge always
continues. Each verdict is recorded as a judge_verdict event.