Code review polish:
- Type hints: List → List[Dict[str, Any]] for cache_get return and
cache_put results parameter, since rerank produces dict-shaped entries.
- TTL=0 short-circuits to None deterministically. Previously the test
for ttl_seconds=0 passed only because clock motion between cache_put
and cache_get made `time.time() - cached_at > 0` true. Now the
semantics match the docstring intent.
8/8 tests still pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cache layer for rerank results. Key is SHA256 of query + sorted
candidate IDs, so changing the candidate set automatically invalidates.
1-day TTL by default; corrupted cache files are silently dropped.
5 tests cover hit, miss, different-candidates, TTL expiry, corruption.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>