• v1.14.0-outer-loop: explicit while loop replaces inference recursion

    indifferentketchup released this 2026-05-23 20:29:21 +00:00 | 65 commits to main since this release

    Converts the ad-hoc executeToolPhase → runAssistantTurn recursion into an
    explicit while (stepNumber < effectiveCap) loop. A step is one stream-and-
    tool-execute iteration; the loop terminates on non-tool finish, step-cap hit,
    doom-loop, budget exhaustion, abort, or synthesis success.

    MAX_STEPS = 200 hard ceiling (4x old effective limit from budget). Per-agent
    steps: field in AGENTS.md frontmatter sets tighter caps (Refactorer: 5,
    Architect: 20, others: unset = bounded only by MAX_STEPS). Resolution:
    effectiveCap = Math.min(agent.steps ?? Infinity, MAX_STEPS).

    executeToolPhase no longer recurses — returns ToolPhaseResult struct
    (action: 'continue' | 'paused' | 'synthesis_done') so the caller decides
    whether to continue or break. steps: 0 handled as "no tool calls allowed"
    via runTextOnlyTurn (one text-only stream phase, tool calls ignored with
    warn log).

    Step-cap hits produce a sentinel summary (reuses cap_hit kind so
    CapHitSentinel.tsx renders without frontend changes; text distinguishes
    "Step limit reached" from "Tool budget exhausted"). Doom-loop check migrated
    to top of loop body — same predicate, same threshold (3), break instead of
    return.

    step_start parts are in the schema CHECK but not emitted as message_parts —
    writing before the stream phase creates a sequence-0 collision with
    partsFromAssistantMessage. Structured log line emitted instead. Adversarial
    review caught the collision pre-deploy.

    332/332 server tests passing. No frontend changes. No schema changes.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    Downloads