# Extractor / context-fetcher loop burns the step budget on one clause

## TL;DR
Track which chunks you have already served and widen the context on repeat requests instead of re-serving the same chunk. The extractor asks for context, the fetcher hands back the identical chunk, and the agent spins until its step budget dies. Cap retries per clause, then escalate to human review.

```text
step 41: extractor flags clause 12 "needs context" -> fetcher returns chunk 88 (already served at steps 39, 40) -> repeat until budget exhausted
```

1. Keep a served-chunk set per clause. If the fetcher is about to return a chunk id it already served for this clause, refuse and widen instead.
   Expected: the loop breaks on the first repeat.
2. Widen, do not retry. On a "needs context" flag, serve the chunk plus its neighbors rather than the same slice.
   Expected: the extractor sees new text on its second attempt.
3. Cap retries at 3 per clause, then mark it "needs_review" and move on.
   Expected: stubborn clauses land in review and the run finishes.
4. Make the extractor say what is missing. "Need the 3 sentences before this chunk" beats a bare "needs context".
   Expected: the fetcher can target instead of guessing.

## Use this when
- a run dies at max steps with the same chunk id fetched repeatedly
- the tool-call log shows extractor/fetcher ping-pong on one clause
- one clause consumes a wildly disproportionate share of the step budget
- "needs context" appears with no description of what context

## Not for this skill when
- the fetcher returns different chunks each time but the extractor still cannot proceed (a comprehension failure)
- the loop involves more than two tools or an external API (a broader orchestration bug)
- the step budget is simply too small for the document size (raise the budget)

## Variant phrasings
- agent loop extractor needs context same chunk returned
- context fetcher infinite loop contract review agent
- agent step budget exhausted single clause retry loop
- rag context expansion loop identical chunk

## Why it happens
The extractor and the fetcher disagree on what "context" means: the extractor wants surrounding text, the fetcher re-runs the same retrieval and returns the top hit, which is the chunk the extractor already has. Neither side remembers what was already tried, so the cycle repeats until an external limit kills it.

## Edge cases
- Widening has a limit: a clause spanning 10 chunks needs a different strategy (section-level fetch).
- Log the widen attempts or you cannot distinguish "needed 2 widens" from "broken".
- A global visited-set across clauses can starve legitimate re-reads; scope it per clause.
- If widening keeps failing, the chunking itself may be wrong (mid-sentence splits).

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_mdYDF3N23ThTtWV8v-zwUQ
