Repeat-tool nudge — advisory reminder when a worker repeats the exact same call
safetyRails.checkPreCallCaps (iteration + token caps) runs once PER DISPATCH; a worker
grepping the same pattern forty times inside ONE dispatch is invisible to it, and the only thing
that eventually stops it is the blunt LOOP_MAX_TOOL_ROUNDS round cap ending the task rather
than redirecting it. src/tools/repeatToolNudge.ts closes that gap with a targeted, purely
advisory signal: when a worker calls the SAME tool with canonicalised-identical arguments 3, 5,
then 8 times in a row (ascending, escalating in tone), it appends a reminder to that call's own
result asking the model to re-read the last result and either change approach or conclude the
repeat is intentional. It never blocks, never rewrites the underlying result, and never appears
in any tool's list — it is a post-execute stage (src/core/toolDispatch.ts), not a Tool.
Canonicalisation sorts argument object keys before comparing, so reordered JSON keys still count
as the same call; any intervening DIFFERENT call resets the streak to zero. todo_write /
todo_read are excluded (a todo list is legitimately re-read/re-written with identical
arguments across many correct turns).
Thresholds are configurable, read at call time (same convention as the other safety-rails caps):
export CYBERINE_REPEAT_TOOL_THRESHOLDS="3,5,8" # default; ascending, any count
export CYBERINE_REPEAT_TOOL_THRESHOLDS="" # disable the nudge entirelyKnown Limitations and Deferred Work (src/tools/repeatToolNudge.ts). State is scoped by
ToolContext.cwd (the same practical per-worker unit src/tools/jobRegistry.ts's background
jobs already use) — two non-isolated workers that happen to share one cwd (no worktree
isolation) share one repeat-count bucket rather than being tracked independently; isolated
(isolate: true) build steps, which each get their own worktree cwd, are unaffected. State
lives in an in-process Map with a crude 500-worker eviction (clear-everything, not per-entry
LRU) — acceptable for an advisory signal, not for anything correctness-sensitive. Injecting the
reminder appends to the tool-result message's own content, which — like any change to that
message's bytes — can invalidate a provider's prompt cache for the rest of that step; firing
only at the three configured thresholds (never on every repeated call) is the mitigation, not a
cache-aware exemption.
Edit pacing — a loop implementer writes before its round budget runs out
A key-only loop implementer (loop-deepseek-build and the other loop--build workers) used to spend every tool round reading and never call a write tool. When the budget ran out, the loop asked for...
Durable worker transcripts — cyberine transcript
A loop worker's events.jsonl is telemetry, not a transcript: each entry's detail is a 120-character slice of the prompt, so when a fleet worker fails there was previously no way to see what it was...