fix(ai): _run_dir_loop APIError path doesn't flush partial dir entry, loses cached work #83

Open
opened 2026-04-18 20:24:07 -06:00 by claude-code · 0 comments
Collaborator

Problem

_run_dir_loop has two early-exit paths: budget exhaustion and API error. The budget path flushes a partial dir cache entry so the work already done in this loop (any file cache entries the agent wrote before the budget tripped) is preserved and usable by synthesis. The API error path just breaks.

luminos_lib/ai.py:1207-1225:

for turn in range(max_turns):
    if tracker.budget_exceeded():
        print(f"  [AI]   Context budget reached ...", file=sys.stderr)
        partial = _flush_partial_dir_entry(dir_path, target, cache)
        if partial and not summary:
            summary = partial
        break

    try:
        content_blocks, _usage = _call_api_streaming(
            client, ctx.system, ctx.messages, ctx.dir_tools, tracker,
        )
    except anthropic.APIError as e:
        print(f"  [AI]   API error: {e}", file=sys.stderr)
        break                   # ← no flush, no partial summary

Consequence

A transient API error (rate limit, 500, network blip) after the agent has written several file cache entries results in:

  • No dir cache entry for this directory
  • Synthesis sees nothing for this dir
  • On resume (without --fresh), the whole dir is re-investigated from scratch — even though the file entries are still there

The budget path's logic is exactly what we want here too: cache whatever the agent already produced, mark it partial, don't waste it.

Fix

Before break in the APIError path, call the same helper:

except anthropic.APIError as e:
    print(f"  [AI]   API error: {e}", file=sys.stderr)
    partial = _flush_partial_dir_entry(dir_path, target, cache)
    if partial and not summary:
        summary = partial
    break

_flush_partial_dir_entry is already idempotent (returns "" if a dir entry already exists), so calling it here is safe.

Acceptance

  • APIError during a dir loop produces a partial dir cache entry when the agent has written at least one file entry
  • Resume-without-fresh after an APIError skips the partially-cached dir (matches budget-exceeded behaviour)
  • Test in test_ai_pure.py covers the _flush_partial_dir_entry idempotency for both paths (budget + APIError)
## Problem `_run_dir_loop` has two early-exit paths: budget exhaustion and API error. The budget path flushes a partial `dir` cache entry so the work already done in this loop (any `file` cache entries the agent wrote before the budget tripped) is preserved and usable by synthesis. The API error path just breaks. `luminos_lib/ai.py:1207-1225`: ```python for turn in range(max_turns): if tracker.budget_exceeded(): print(f" [AI] Context budget reached ...", file=sys.stderr) partial = _flush_partial_dir_entry(dir_path, target, cache) if partial and not summary: summary = partial break try: content_blocks, _usage = _call_api_streaming( client, ctx.system, ctx.messages, ctx.dir_tools, tracker, ) except anthropic.APIError as e: print(f" [AI] API error: {e}", file=sys.stderr) break # ← no flush, no partial summary ``` ## Consequence A transient API error (rate limit, 500, network blip) after the agent has written several `file` cache entries results in: - No `dir` cache entry for this directory - Synthesis sees nothing for this dir - On resume (without `--fresh`), the whole dir is re-investigated from scratch — even though the `file` entries are still there The budget path's logic is exactly what we want here too: cache whatever the agent already produced, mark it partial, don't waste it. ## Fix Before `break` in the APIError path, call the same helper: ```python except anthropic.APIError as e: print(f" [AI] API error: {e}", file=sys.stderr) partial = _flush_partial_dir_entry(dir_path, target, cache) if partial and not summary: summary = partial break ``` `_flush_partial_dir_entry` is already idempotent (returns `""` if a dir entry already exists), so calling it here is safe. ## Acceptance - [ ] APIError during a dir loop produces a partial `dir` cache entry when the agent has written at least one `file` entry - [ ] Resume-without-fresh after an APIError skips the partially-cached dir (matches budget-exceeded behaviour) - [ ] Test in `test_ai_pure.py` covers the `_flush_partial_dir_entry` idempotency for both paths (budget + APIError)
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: archeious/luminos#83
No description provided.