maybeRunawayNudge appends one soft system note when a turn crosses maxToolRounds tool calls without finishing. The runawayNudged latch fires it exactly once per turn: this is consulted only when the pending queue drains, but toolRounds increments per call, so a multi-tool-call round can jump the cou
()
| 1194 | return |
| 1195 | } |
| 1196 | m.runawayNudged = true |
| 1197 | dbgWritef("nudge", "runaway-iteration nudge injected at %d tool calls this turn", m.toolRounds) |
| 1198 | m.history = append(m.history, chmctx.Message{ |
| 1199 | Role: chmctx.RoleSystem, |
| 1200 | Content: nudgeOrigin + fmt.Sprintf( |
| 1201 | "%d tool calls so far this turn without finishing. If you're still making real progress, keep going. If you're repeating a step that can't work here - a blocked install, a missing tool, a path failing the same way - stop chasing it (that loop burns the turn); verify another way. If you're stuck or unsure you're converging, tell the user where things stand and what's blocking you.", |
| 1202 | m.toolRounds), |
| 1203 | }) |
| 1204 | } |
| 1205 | |
| 1206 | // verifyNudgeMinRounds is how many tool calls a turn must have dispatched before |
| 1207 | // the finish re-grounding nudge can fire. Set so only a turn that did real, |
| 1208 | // multi-step work trips it: a quick answer or a one-line edit stays well under it, |
| 1209 | // while a build / refactor / test-fix loop clears it easily. Below this the |
| 1210 | // original request is still close in context and a re-ground would be noise; the |
| 1211 | // galaxy runs that shipped broken-but-claimed-done artifacts each made dozens. |