Skip to content

feat(cache): per-call freshness override max_cache_age_s#85

Merged
dongwhee merged 2 commits into
developfrom
feat/per-call-cache-freshness
Jul 5, 2026
Merged

feat(cache): per-call freshness override max_cache_age_s#85
dongwhee merged 2 commits into
developfrom
feat/per-call-cache-freshness

Conversation

@dongwhee

@dongwhee dongwhee commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a keyword-only max_cache_age_s (int | None, default None) to fetch_relevant() and the MCP fetch_page tool: None follows TRAWL_FETCH_CACHE_TTL (unchanged default), 0 treats any cached entry as stale and routes through the existing conditional-GET revalidation (may still 304-reuse identical content), N accepts entries younger than N seconds. Motivated by the field converging on per-call freshness knobs (Exa maxAgeHours, Feb 2026); lets openclaw/hermes/Claude Code choose fresh-vs-cache per call.

Documented limitations: profile fast/transfer paths and passthrough/PDF branches do not consult the fetch cache, so the parameter has no effect there.

Gates

Gate Result
Offline cache suites (test_fetch_cache.py + test_pipeline_cache.py, 6 new cases) + MCP stdio smoke PASS (44 checks)
Parity (default args, fetch cache disabled) 14/15 — hada_news fails identically on develop with and without this diff and with rs on/off: live front-page drift (markers GeekNews/topic?id absent today), environmental, not diff-caused

Review

/code-review low → 2 findings, both fixed: MCP input now int-coerced with a clean error on bad input; fetch_cache.get() no longer deletes records that are stale only under a per-call age (global-TTL deletion unchanged).

Notes

  • cache_hit is not currently emitted in telemetry JSONL (pre-existing gap, out of scope; noted for a future telemetry PR).
  • hada_news ground truth may need principled maintenance if the drift persists — separate decision, not touched here.

🤖 Generated with Claude Code

lyla added 2 commits July 6, 2026 08:38
Adds a keyword-only max_cache_age_s (int | None, default None) to
fetch_relevant() and the MCP fetch_page tool, threading through
fetch_cache.get/get_with_state/_read as max_age_s:
- None: follow TRAWL_FETCH_CACHE_TTL (unchanged default behavior)
- 0: treat any cached entry as stale; flows into the existing
  conditional-GET revalidation branch (may still 304-reuse)
- N: accept cached entries younger than N seconds

Motivated by the field converging on per-call freshness knobs
(Exa maxAgeHours, Feb 2026). Known documented limitation: profile
fast/transfer paths and passthrough/PDF branches do not consult the
fetch cache, so the parameter has no effect there.

MCP: optional integer property on fetch_page inputSchema, passed via
the _supports_keyword feature-detection pattern.

Tests: 6 new offline cases (age boundary, age=0, None-default at both
fetch_cache and pipeline level); full cache suites 42 pytest + MCP
stdio smoke pass. Parity 14/15 — hada_news fails identically on
develop with and without this diff and with rs on/off (live content
drift, markers absent from today's front page), i.e. environmental,
not diff-caused.
- MCP fetch_page: coerce max_cache_age_s to int with a clean error
  response on non-integer or negative input instead of a deep
  TypeError in fetch_cache.
- fetch_cache.get(): a per-call max_age_s stale judgement no longer
  deletes the record — per-call freshness preference must not destroy
  entries still fresh under the global TTL. Deletion with
  max_age_s=None unchanged.

44 checks pass (43 pytest + MCP smoke).
@dongwhee dongwhee merged commit b0e4cc4 into develop Jul 5, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant