aa7c24fa18
Two changes that together stop PR #29's per-cycle ``max_pages=20`` truncation WARN on its 2700+ comment history: 1. **Exponential backoff** in ``_pr_comments_cache.get_pr_comments``: on a failed live delta the cache stamps ``consecutive_failures`` and ``next_attempt_after`` (default base 60s × 2^(failures-1), capped at 30 min). The next cycle inside the backoff window short-circuits — serves the cached bulk stale with ``completed=False`` and does NOT hit the flaky endpoint again. First successful delta clears the counter, so a transient outage doesn't permanently throttle. Truncated cold seeds (page-cap hit on first walk) are also counted as failures so the every-cycle 30s pagination tax stops on PR-sized threads that genuinely exceed the cap. 2. **Reviewer prefetch cutover** in ``_review_prompt.py``: the reviewer's ``fetch_review_context`` now routes through ``_pr_comments_cache.get_pr_comments`` instead of the raw ``_review_pipeline.fetch_pr_comments``. Mirrors the Phase 2 feature-flag pattern: default ON, env off-switch ``REVIEW_DISPATCHER_USE_COMMENT_CACHE=0`` for rollback, WARN and fall back to the legacy paginator on any cache exception so a cache failure can never break a review cycle. Implementer dispatcher has used this cache directly since 2026-05-13 without incident. Coverage: 30 new tests (14 backoff + 16 cutover-wrapper). Touched-module suite: 43 passing. NOTE: the matching MCP wrapper (``forgejo_fetch_pr_comments_cached``) lives in ``tools/mcp_forgejo_server.py`` which is currently untracked; it'll ride with the Phase 1 commit that lands the MCP server file itself. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>