fix(autopilot): wire the runaway backstop (guardTripped) into the loop - #331
Merged
Conversation
guardTripped bounds a file-a-ticket-per-iteration runaway (max iterations = board size × factor) but had NO runtime caller — the loop was prose in SKILL.md, so the backstop rested on orchestrator discipline alone (#317). Add ledger.mjs `nextIteration(run, boardSize, factor=2)`: the pure per-iteration guard the orchestrator is contractually required to call FIRST each iteration. It reads the persisted iteration counter (run.iterations, maintained by applyOutcome, so the bound is resume-safe and auditable) and delegates the trip test to guardTripped, returning `{ stop, escalate, iterations, cap, reason }`. A trip is a halt+escalate decision (not a silent continue); it never mutates the run, so the natural stop (board clear) and --limit stay intact. SKILL.md now documents the guard as a code call, not prose: the loop diagram calls nextIteration at the top of every iteration, the Loop-backstop rail is mechanical, and the driver-scripts list names nextIteration as guardTripped's real caller. Tests (engine.test.mjs): AC-317.1 the guard is invoked and returns continue under the cap (delegates to guardTripped, honours factor + boardSize floor); AC-317.2 a simulated non-converging runaway is halted by the guard at board size × factor (exactly 6 iterations on boardSize 3, then halt+escalate). Closes #317 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SATRHKa6mDHDuirhP6QuwL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #317 (parent epic #183)
Problem
ledger.mjsexportsguardTripped(run, boardSize, factor=2)— a correct, tested pure fn bounding a file-a-ticket-per-iteration runaway (max iterations = board size × factor) — but it had no runtime caller. The loop was prose inSKILL.md, so the runaway was bounded only by orchestrator discipline, not by code.Change (thin, mirrors #316's pattern)
nextIteration(run, boardSize, factor=2)added toledger.mjs: the pure per-iteration guard the orchestrator is contractually required to call first each iteration. It reads the persisted iteration counter (run.iterations, maintained byapplyOutcome→ resume-safe & auditable) and delegates the trip test toguardTripped, returning{ stop, escalate, iterations, cap, reason }. A trip is a halt + escalate decision, not a silent continue. It never mutates the run, so the natural stop (board clear) and--limitare untouched.SKILL.mdnow makes the backstop a code call, not prose: the loop diagram callsnextIterationat the top of every iteration; the Loop-backstop rail is mechanical; the driver-scripts list names it asguardTripped's real caller.Acceptance criteria
guardTrippedeach iteration and escalates/stops when it trips.nextIterationis that caller (delegates toguardTripped, returnsstop/escalate);SKILL.md's loop calls it first each iteration and halts+escalates on a trip. Verified by AC-317.1 + AC-317.2.escalate:trueand arunaway backstop trippedreason — so the guard, not the safety cap, stopped it.Verification
pnpm verify: 605/605 passing (was 600; +2 new AC-317 tests, existing autopilot tests unchanged).🤖 Generated with Claude Code